From 9f0ae0c82060e3dcd1fa7ac8bbe35a3f9a44dbba Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 10 May 2002 22:36:27 +0000
Subject: [PATCH] First pass at schema-fying pg_dump/pg_restore.  Much to do
 still, but the basic capability seems to work.

---
 doc/src/sgml/ref/pg_dump.sgml        |   41 +-
 doc/src/sgml/ref/pg_restore.sgml     |   29 +-
 src/bin/pg_dump/common.c             |  615 ++-
 src/bin/pg_dump/pg_backup.h          |   33 +-
 src/bin/pg_dump/pg_backup_archiver.c |  286 +-
 src/bin/pg_dump/pg_backup_archiver.h |   26 +-
 src/bin/pg_dump/pg_backup_db.c       |  136 +-
 src/bin/pg_dump/pg_backup_db.h       |    6 +-
 src/bin/pg_dump/pg_backup_null.c     |    4 +-
 src/bin/pg_dump/pg_backup_tar.c      |    4 +-
 src/bin/pg_dump/pg_dump.c            | 6883 ++++++++++++++------------
 src/bin/pg_dump/pg_dump.h            |  293 +-
 src/bin/pg_dump/pg_restore.c         |  150 +-
 13 files changed, 4421 insertions(+), 4085 deletions(-)

diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml
index 1167128716e..d2ab719fe34 100644
--- a/doc/src/sgml/ref/pg_dump.sgml
+++ b/doc/src/sgml/ref/pg_dump.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.44 2002/04/21 19:02:39 thomas Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.45 2002/05/10 22:36:26 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -407,10 +407,11 @@ PostgreSQL documentation
       <term><option>--superuser=<replaceable class="parameter">username</replaceable></option></term>
       <listitem>
        <para>
-        The scripts or archives created by <command>pg_dump</command>
-        need to have superuser access in certain cases, such as when
-        disabling triggers or setting ownership of schema elements.
-        This option specifies the user name to use for those cases.
+        Specify the superuser user name to use when disabling triggers.
+	This is only relevant if <option>--disable-triggers</> is used.
+	(Usually, it's better to specify
+	<option>--use-set-session-authorization</>, and then start the
+	resulting script as superuser.)
        </para>
       </listitem>
      </varlistentry>
@@ -481,6 +482,36 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>-X disable-triggers</></term>
+      <term><option>--disable-triggers</></term>
+      <listitem>
+       <para>
+        This option is only relevant when creating a data-only dump.
+	It instructs <command>pg_dump</command> to include commands
+	to temporarily disable triggers on the target tables while
+	the data is reloaded.  Use this if you have referential
+	integrity checks or other triggers on the tables that you
+	do not want to invoke during data reload.
+       </para>
+
+       <para>
+        Presently, the commands emitted for <option>--disable-triggers</>
+	must be done as superuser.  So, you should also specify
+	a superuser name with <option>-S</>, or preferably specify
+	<option>--use-set-session-authorization</> and then be careful to
+	start the resulting script as a superuser.  If you give neither
+	option, the entire script must be run as superuser.
+       </para>
+
+       <para>
+        This option is only meaningful for the plain-text format.  For
+        the other formats, you may specify the option when you
+        call <command>pg_restore</command>.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-Z <replaceable class="parameter">0..9</replaceable></option></term>
       <term><option>--compress=<replaceable class="parameter">0..9</replaceable></option></term>
diff --git a/doc/src/sgml/ref/pg_restore.sgml b/doc/src/sgml/ref/pg_restore.sgml
index 3e7f2c6fcc0..aa87e2e6f44 100644
--- a/doc/src/sgml/ref/pg_restore.sgml
+++ b/doc/src/sgml/ref/pg_restore.sgml
@@ -1,4 +1,4 @@
-<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_restore.sgml,v 1.24 2002/04/21 19:02:39 thomas Exp $ -->
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_restore.sgml,v 1.25 2002/05/10 22:36:26 tgl Exp $ -->
 
 <refentry id="APP-PGRESTORE">
  <docinfo>
@@ -336,8 +336,8 @@
       <term><option>--superuser=<replaceable class="parameter">username</replaceable></option></term>
       <listitem>
        <para>
-        Specify the superuser user name to use when disabling triggers and/or setting ownership of schema elements.
-        By default, <COMMAND>pg_restore</COMMAND> will use the current user name if it is a superuser.
+        Specify the superuser user name to use when disabling triggers.
+	This is only relevant if <option>--disable-triggers</> is used.
        </para>
       </listitem>
      </varlistentry>
@@ -402,6 +402,29 @@
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>-X disable-triggers</></term>
+      <term><option>--disable-triggers</></term>
+      <listitem>
+       <para>
+        This option is only relevant when performing a data-only restore.
+	It instructs <command>pg_restore</command> to execute commands
+	to temporarily disable triggers on the target tables while
+	the data is reloaded.  Use this if you have referential
+	integrity checks or other triggers on the tables that you
+	do not want to invoke during data reload.
+       </para>
+
+       <para>
+        Presently, the commands emitted for <option>--disable-triggers</>
+	must be done as superuser.  So, you should also specify
+	a superuser name with <option>-S</>, or preferably specify
+	<option>--use-set-session-authorization</> and run
+	<command>pg_restore</command> as a superuser.
+       </para>
+      </listitem>
+     </varlistentry>
+
     </variablelist>
    </para>
 
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 4188746471e..47692bdeac4 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -3,30 +3,15 @@
  * common.c
  *	  common routines between pg_dump and pg4_dump
  *
+ * Since pg4_dump is long-dead code, there is no longer any useful distinction
+ * between this file and pg_dump.c.
+ *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.63 2002/04/24 02:44:19 momjian Exp $
- *
- * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
- *
- *	 - Fixed dumpTable output to output lengths for char and varchar types!
- *	 - Added single. quote to twin single quote expansion for 'insert' string
- *	   mode.
- *
- * Modifications 14-Sep-2000 - pjw@rhyme.com.au
- *	-	Added enum for findTypeByOid to specify how to handle OID and which
- *		string to return - formatted type, or base type. If the base type
- *		is returned then fmtId is called on the string.
- *
- * Modifications 4-Apr-2001 - pjw@rhyme.com.au
- *	-	Changed flagInhAttrs to check all parent tables for overridden settings
- *		and set flags accordingly.
- *
- *		BEWARE: Since fmtId uses a static buffer, using 'useBaseTypeName' on more
- *				than one call in a line will cause problems.
+ *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.64 2002/05/10 22:36:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,255 +29,48 @@
 #include "strdup.h"
 #endif
 
-static char **findParentsByOid(TableInfo *tbinfo, int numTables,
-				 InhInfo *inhinfo, int numInherits,
-				 const char *oid,
-				 int *numParents,
-				 int (**parentIndexes)[]);
-static int	findTableByOid(TableInfo *tbinfo, int numTables, const char *oid);
+static void findParentsByOid(TableInfo *tblinfo, int numTables,
+							 InhInfo *inhinfo, int numInherits,
+							 const char *oid,
+							 int *numParentsPtr, int **parentIndexes);
+static void flagInhTables(TableInfo *tbinfo, int numTables,
+			 InhInfo *inhinfo, int numInherits);
 static void flagInhAttrs(TableInfo *tbinfo, int numTables,
 			 InhInfo *inhinfo, int numInherits);
 static int	strInArray(const char *pattern, char **arr, int arr_size);
 
-/*
- * findTypeByOid
- *	  given an oid of a type, return its typename
- *
- * Can return various special cases for oid 0.
- *
- * NOTE:  should hash this, but just do linear search for now
- */
-
-char *
-findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid, OidOptions opts)
-{
-	int			i;
-
-	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 "*";
-		else if ((opts & zeroAsNone) != 0)
-			return "NONE";
-	}
-
-	for (i = 0; i < numTypes; i++)
-	{
-		if (strcmp(tinfo[i].oid, oid) == 0)
-		{
-			if ((opts & useBaseTypeName) != 0)
-				return (char *) fmtId(tinfo[i].typname, false);
-			else
-				return tinfo[i].typedefn;
-		}
-	}
-
-	/* no suitable type name was found */
-	return (NULL);
-}
-
-/*
- * findOprByOid
- *	  given the oid of an operator, return the name of the operator
- *
- *
- * NOTE:  should hash this, but just do linear search for now
- *
- */
-char *
-findOprByOid(OprInfo *oprinfo, int numOprs, const char *oid)
-{
-	int			i;
-
-	for (i = 0; i < numOprs; i++)
-	{
-		if (strcmp(oprinfo[i].oid, oid) == 0)
-			return oprinfo[i].oprname;
-	}
-
-	/* should never get here */
-	write_msg(NULL, "failed sanity check, operator with oid %s not found\n", oid);
-
-	/* no suitable operator name was found */
-	return (NULL);
-}
-
-
-/*
- * findParentsByOid
- *	  given the oid of a class, return the names of its parent classes
- * and assign the number of parents, and parent indexes to the last arguments.
- *
- *
- * returns NULL if none
- */
-
-static char **
-findParentsByOid(TableInfo *tblinfo, int numTables,
-				 InhInfo *inhinfo, int numInherits, const char *oid,
-				 int *numParentsPtr, int (**parentIndexes)[])
-{
-	int			i,
-				j;
-	int			parentInd,
-				selfInd;
-	char	  **result;
-	int			numParents;
-
-	numParents = 0;
-	for (i = 0; i < numInherits; i++)
-	{
-		if (strcmp(inhinfo[i].inhrelid, oid) == 0)
-			numParents++;
-	}
-
-	*numParentsPtr = numParents;
-
-	if (numParents > 0)
-	{
-		result = (char **) malloc(sizeof(char *) * numParents);
-		(*parentIndexes) = malloc(sizeof(int) * numParents);
-		j = 0;
-		for (i = 0; i < numInherits; i++)
-		{
-			if (strcmp(inhinfo[i].inhrelid, oid) == 0)
-			{
-				parentInd = findTableByOid(tblinfo, numTables,
-										   inhinfo[i].inhparent);
-				if (parentInd < 0)
-				{
-					selfInd = findTableByOid(tblinfo, numTables, oid);
-					if (selfInd >= 0)
-						write_msg(NULL, "failed sanity check, parent oid %s of table %s (oid %s) not found\n",
-								  inhinfo[i].inhparent,
-								  tblinfo[selfInd].relname,
-								  oid);
-					else
-						write_msg(NULL, "failed sanity check, parent oid %s of table (oid %s) not found\n",
-								  inhinfo[i].inhparent,
-								  oid);
-
-					exit_nicely();
-				}
-				(**parentIndexes)[j] = parentInd;
-				result[j++] = tblinfo[parentInd].relname;
-			}
-		}
-		return result;
-	}
-	else
-	{
-		(*parentIndexes) = NULL;
-		return NULL;
-	}
-}
-
-/*
- * parseNumericArray
- *	  parse a string of numbers delimited by spaces into a character array
- */
-
-void
-parseNumericArray(const char *str, char **array, int arraysize)
-{
-	int			j,
-				argNum;
-	char		temp[100];
-	char		s;
-
-	argNum = 0;
-	j = 0;
-	for (;;)
-	{
-		s = *str++;
-		if (s == ' ' || s == '\0')
-		{
-			if (j > 0)
-			{
-				if (argNum >= arraysize)
-				{
-					write_msg(NULL, "parseNumericArray: too many numbers\n");
-					exit_nicely();
-				}
-				temp[j] = '\0';
-				array[argNum++] = strdup(temp);
-				j = 0;
-			}
-			if (s == '\0')
-				break;
-		}
-		else
-		{
-			if (!(isdigit((unsigned char) s) || s == '-') ||
-				j >= sizeof(temp) - 1)
-			{
-				write_msg(NULL, "parseNumericArray: bogus number\n");
-				exit_nicely();
-			}
-			temp[j++] = s;
-		}
-	}
-
-	while (argNum < arraysize)
-		array[argNum++] = strdup("0");
-}
-
-
-/*
- * strInArray:
- *	  takes in a string and a string array and the number of elements in the
- * string array.
- *	  returns the index if the string is somewhere in the array, -1 otherwise
- *
- */
-
-static int
-strInArray(const char *pattern, char **arr, int arr_size)
-{
-	int			i;
-
-	for (i = 0; i < arr_size; i++)
-	{
-		if (strcmp(pattern, arr[i]) == 0)
-			return i;
-	}
-	return -1;
-}
 
 /*
  * dumpSchema:
  *	  we have a valid connection, we are now going to dump the schema
  * into the file
- *
  */
 
 TableInfo *
 dumpSchema(Archive *fout,
 		   int *numTablesPtr,
-		   const char *tablename,
 		   const bool aclsSkip,
-		   const bool oids,
 		   const bool schemaOnly,
 		   const bool dataOnly)
 {
+	int			numNamespaces;
 	int			numTypes;
 	int			numFuncs;
 	int			numTables;
 	int			numInherits;
 	int			numAggregates;
 	int			numOperators;
-	int			numIndexes;
-	TypeInfo   *tinfo = NULL;
-	FuncInfo   *finfo = NULL;
-	AggInfo    *agginfo = NULL;
-	TableInfo  *tblinfo = NULL;
-	InhInfo    *inhinfo = NULL;
-	OprInfo    *oprinfo = NULL;
-	IndInfo    *indinfo = NULL;
+	NamespaceInfo *nsinfo;
+	TypeInfo   *tinfo;
+	FuncInfo   *finfo;
+	AggInfo    *agginfo;
+	TableInfo  *tblinfo;
+	InhInfo    *inhinfo;
+	OprInfo    *oprinfo;
+
+	if (g_verbose)
+		write_msg(NULL, "reading namespaces\n");
+	nsinfo = getNamespaces(&numNamespaces);
 
 	if (g_verbose)
 		write_msg(NULL, "reading user-defined types\n");
@@ -312,32 +90,40 @@ dumpSchema(Archive *fout,
 
 	if (g_verbose)
 		write_msg(NULL, "reading user-defined tables\n");
-	tblinfo = getTables(&numTables, finfo, numFuncs, tablename);
-
-	if (g_verbose)
-		write_msg(NULL, "reading index information\n");
-	indinfo = getIndexes(&numIndexes);
+	tblinfo = getTables(&numTables);
 
 	if (g_verbose)
 		write_msg(NULL, "reading table inheritance information\n");
 	inhinfo = getInherits(&numInherits);
 
+	/* Link tables to parents, mark parents of target tables interesting */
 	if (g_verbose)
-		write_msg(NULL, "finding the column names and types for each table\n");
+		write_msg(NULL, "finding inheritance relationships\n");
+	flagInhTables(tblinfo, numTables, inhinfo, numInherits);
+
+	if (g_verbose)
+		write_msg(NULL, "reading column info for interesting tables\n");
 	getTableAttrs(tblinfo, numTables);
 
 	if (g_verbose)
 		write_msg(NULL, "flagging inherited columns in subtables\n");
 	flagInhAttrs(tblinfo, numTables, inhinfo, numInherits);
 
-	if (!tablename && !dataOnly)
+	if (!dataOnly)
 	{
 		if (g_verbose)
 			write_msg(NULL, "dumping out database comment\n");
 		dumpDBComment(fout);
 	}
 
-	if (!tablename && fout)
+	if (!dataOnly)
+	{
+		if (g_verbose)
+			write_msg(NULL, "dumping out user-defined namespaces\n");
+		dumpNamespaces(fout, nsinfo, numNamespaces);
+	}
+
+	if (!dataOnly)
 	{
 		if (g_verbose)
 			write_msg(NULL, "dumping out user-defined types\n");
@@ -346,63 +132,102 @@ dumpSchema(Archive *fout,
 
 	if (g_verbose)
 		write_msg(NULL, "dumping out tables\n");
-
-	dumpTables(fout, tblinfo, numTables, tablename,
+	dumpTables(fout, tblinfo, numTables,
 			   aclsSkip, schemaOnly, dataOnly);
 
-	if (fout && !dataOnly)
+	if (!dataOnly)
 	{
 		if (g_verbose)
 			write_msg(NULL, "dumping out indexes\n");
-		dumpIndexes(fout, indinfo, numIndexes, tblinfo, numTables, tablename);
+		dumpIndexes(fout, tblinfo, numTables);
 	}
 
-	if (!tablename && !dataOnly)
+	if (!dataOnly)
 	{
 		if (g_verbose)
 			write_msg(NULL, "dumping out user-defined procedural languages\n");
-		dumpProcLangs(fout, finfo, numFuncs, tinfo, numTypes);
+		dumpProcLangs(fout, finfo, numFuncs);
 	}
 
-	if (!tablename && !dataOnly)
+	if (!dataOnly)
 	{
 		if (g_verbose)
 			write_msg(NULL, "dumping out user-defined functions\n");
-		dumpFuncs(fout, finfo, numFuncs, tinfo, numTypes);
+		dumpFuncs(fout, finfo, numFuncs);
 	}
 
-	if (!tablename && !dataOnly)
+	if (!dataOnly)
 	{
 		if (g_verbose)
 			write_msg(NULL, "dumping out user-defined aggregate functions\n");
-		dumpAggs(fout, agginfo, numAggregates, tinfo, numTypes);
+		dumpAggs(fout, agginfo, numAggregates);
 	}
 
-	if (!tablename && !dataOnly)
+	if (!dataOnly)
 	{
 		if (g_verbose)
 			write_msg(NULL, "dumping out user-defined operators\n");
-		dumpOprs(fout, oprinfo, numOperators, tinfo, numTypes);
+		dumpOprs(fout, oprinfo, numOperators);
 	}
 
 	*numTablesPtr = numTables;
-	clearAggInfo(agginfo, numAggregates);
-	clearOprInfo(oprinfo, numOperators);
-	clearTypeInfo(tinfo, numTypes);
-	clearFuncInfo(finfo, numFuncs);
-	clearInhInfo(inhinfo, numInherits);
-	clearIndInfo(indinfo, numIndexes);
 	return tblinfo;
 }
 
-/* flagInhAttrs -
- *	 for each table in tblinfo, flag its inherited attributes
- * so when we dump the table out, we don't dump out the inherited attributes
+/* flagInhTables -
+ *	 Fill in parentIndexes fields of every target table, and mark
+ *	 parents of target tables as interesting
  *
- * initializes the parentRels field of each table
+ * Note that only direct ancestors of targets are marked interesting.
+ * This is sufficient; we don't much care whether they inherited their
+ * attributes or not.
  *
  * modifies tblinfo
+ */
+static void
+flagInhTables(TableInfo *tblinfo, int numTables,
+			  InhInfo *inhinfo, int numInherits)
+{
+	int			i,
+				j;
+	int			numParents;
+	int		   *parentIndexes;
+
+	for (i = 0; i < numTables; i++)
+	{
+		/* Sequences and views never have parents */
+		if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
+			tblinfo[i].relkind == RELKIND_VIEW)
+			continue;
+
+		/* Don't bother computing anything for non-target tables, either */
+		if (!tblinfo[i].dump)
+			continue;
+
+		/* Find all the immediate parent tables */
+		findParentsByOid(tblinfo, numTables,
+						 inhinfo, numInherits,
+						 tblinfo[i].oid,
+						 &tblinfo[i].numParents,
+						 &tblinfo[i].parentIndexes);
+		numParents = tblinfo[i].numParents;
+		parentIndexes = tblinfo[i].parentIndexes;
+
+		/* Mark the parents as interesting for getTableAttrs */
+		for (j = 0; j < numParents; j++)
+		{
+			int			parentInd = parentIndexes[j];
+
+			tblinfo[parentInd].interesting = true;
+		}
+	}
+}
+
+/* flagInhAttrs -
+ *	 for each dumpable table in tblinfo, flag its inherited attributes
+ * so when we dump the table out, we don't dump out the inherited attributes
  *
+ * modifies tblinfo
  */
 static void
 flagInhAttrs(TableInfo *tblinfo, int numTables,
@@ -413,7 +238,8 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
 				k;
 	int			parentInd;
 	int			inhAttrInd;
-	int			(*parentIndexes)[];
+	int			numParents;
+	int		   *parentIndexes;
 	bool		foundAttr;		/* Attr was found in a parent */
 	bool		foundNotNull;	/* Attr was NOT NULL in a parent */
 	bool		defaultsMatch;	/* All non-empty defaults match */
@@ -421,23 +247,22 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
 	char	   *attrDef;
 	char	   *inhDef;
 
-	/*
-	 * we go backwards because the tables in tblinfo are in OID order,
-	 * meaning the subtables are after the parent tables we flag inherited
-	 * attributes from child tables first
-	 */
-	for (i = numTables - 1; i >= 0; i--)
+	for (i = 0; i < numTables; i++)
 	{
-		/* Sequences can never have parents, and attr info is undefined */
-		if (tblinfo[i].relkind == RELKIND_SEQUENCE)
+		/* Sequences and views never have parents */
+		if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
+			tblinfo[i].relkind == RELKIND_VIEW)
+			continue;
+
+		/* Don't bother computing anything for non-target tables, either */
+		if (!tblinfo[i].dump)
 			continue;
 
-		/* Get all the parents and their indexes. */
-		tblinfo[i].parentRels = findParentsByOid(tblinfo, numTables,
-												 inhinfo, numInherits,
-												 tblinfo[i].oid,
-												 &tblinfo[i].numParents,
-												 &parentIndexes);
+		numParents = tblinfo[i].numParents;
+		parentIndexes = tblinfo[i].parentIndexes;
+
+		if (numParents == 0)
+			continue;			/* nothing to see here, move along */
 
 		/*
 		 * For each attr, check the parent info: if no parent has an attr
@@ -459,18 +284,9 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
 
 			attrDef = tblinfo[i].adef_expr[j];
 
-			for (k = 0; k < tblinfo[i].numParents; k++)
+			for (k = 0; k < numParents; k++)
 			{
-				parentInd = (*parentIndexes)[k];
-
-				if (parentInd < 0)
-				{
-					/* shouldn't happen unless findParentsByOid is broken */
-					write_msg(NULL, "failed sanity check, table \"%s\" not found by flagInhAttrs\n",
-							  tblinfo[i].parentRels[k]);
-					exit_nicely();
-				};
-
+				parentInd = parentIndexes[k];
 				inhAttrInd = strInArray(tblinfo[i].attnames[j],
 										tblinfo[parentInd].attnames,
 										tblinfo[parentInd].numatts);
@@ -479,7 +295,7 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
 				{
 					foundAttr = true;
 					foundNotNull |= tblinfo[parentInd].notnull[inhAttrInd];
-					if (attrDef != NULL)		/* It we have a default,
+					if (attrDef != NULL)		/* If we have a default,
 												 * check parent */
 					{
 						inhDef = tblinfo[parentInd].adef_expr[inhAttrInd];
@@ -488,10 +304,10 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
 						{
 							defaultsFound = true;
 							defaultsMatch &= (strcmp(attrDef, inhDef) == 0);
-						};
-					};
-				};
-			};
+						}
+					}
+				}
+			}
 
 			/*
 			 * Based on the scan of the parents, decide if we can rely on
@@ -500,9 +316,9 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
 			if (foundAttr)		/* Attr was inherited */
 			{
 				/* Set inherited flag by default */
-				tblinfo[i].inhAttrs[j] = 1;
-				tblinfo[i].inhAttrDef[j] = 1;
-				tblinfo[i].inhNotNull[j] = 1;
+				tblinfo[i].inhAttrs[j] = true;
+				tblinfo[i].inhAttrDef[j] = true;
+				tblinfo[i].inhNotNull[j] = true;
 
 				/*
 				 * Clear it if attr had a default, but parents did not, or
@@ -510,8 +326,8 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
 				 */
 				if ((attrDef != NULL) && (!defaultsFound || !defaultsMatch))
 				{
-					tblinfo[i].inhAttrs[j] = 0;
-					tblinfo[i].inhAttrDef[j] = 0;
+					tblinfo[i].inhAttrs[j] = false;
+					tblinfo[i].inhAttrDef[j] = false;
 				}
 
 				/*
@@ -520,8 +336,8 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
 				 */
 				if (tblinfo[i].notnull[j] && !foundNotNull)
 				{
-					tblinfo[i].inhAttrs[j] = 0;
-					tblinfo[i].inhNotNull[j] = 0;
+					tblinfo[i].inhAttrs[j] = false;
+					tblinfo[i].inhNotNull[j] = false;
 				}
 			}
 		}
@@ -530,64 +346,199 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
 
 
 /*
- * findTableByName
- *	  finds the index (in tblinfo) of the table with the given relname
+ * findTableByOid
+ *	  finds the index (in tblinfo) of the table with the given oid
  *	returns -1 if not found
  *
  * NOTE:  should hash this, but just do linear search for now
  */
-
 int
-findTableByName(TableInfo *tblinfo, int numTables, const char *relname)
+findTableByOid(TableInfo *tblinfo, int numTables, const char *oid)
 {
 	int			i;
 
 	for (i = 0; i < numTables; i++)
 	{
-		if (strcmp(tblinfo[i].relname, relname) == 0)
+		if (strcmp(tblinfo[i].oid, oid) == 0)
 			return i;
 	}
 	return -1;
 }
 
+
 /*
- * findTableByOid
- *	  finds the index (in tblinfo) of the table with the given oid
+ * findFuncByOid
+ *	  finds the index (in finfo) of the function with the given OID
  *	returns -1 if not found
  *
  * NOTE:  should hash this, but just do linear search for now
  */
-
-static int
-findTableByOid(TableInfo *tblinfo, int numTables, const char *oid)
+int
+findFuncByOid(FuncInfo *finfo, int numFuncs, const char *oid)
 {
 	int			i;
 
-	for (i = 0; i < numTables; i++)
+	for (i = 0; i < numFuncs; i++)
 	{
-		if (strcmp(tblinfo[i].oid, oid) == 0)
+		if (strcmp(finfo[i].oid, oid) == 0)
 			return i;
 	}
 	return -1;
 }
 
-
 /*
- * findFuncByName
- *	  finds the index (in finfo) of the function with the given name
- *	returns -1 if not found
+ * findOprByOid
+ *	  given the oid of an operator, return the name of the operator
  *
  * NOTE:  should hash this, but just do linear search for now
  */
+char *
+findOprByOid(OprInfo *oprinfo, int numOprs, const char *oid)
+{
+	int			i;
 
-int
-findFuncByName(FuncInfo *finfo, int numFuncs, const char *name)
+	for (i = 0; i < numOprs; i++)
+	{
+		if (strcmp(oprinfo[i].oid, oid) == 0)
+			return oprinfo[i].oprname;
+	}
+
+	/* should never get here */
+	write_msg(NULL, "failed sanity check, operator with oid %s not found\n", oid);
+
+	/* no suitable operator name was found */
+	return (NULL);
+}
+
+
+/*
+ * findParentsByOid
+ *	  given the oid of a class, find its parent classes in tblinfo[]
+ *
+ * Returns the number of parents and their array indexes into the
+ * last two arguments.
+ */
+
+static void
+findParentsByOid(TableInfo *tblinfo, int numTables,
+				 InhInfo *inhinfo, int numInherits,
+				 const char *oid,
+				 int *numParentsPtr, int **parentIndexes)
+{
+	int			i,
+				j;
+	int			parentInd,
+				selfInd;
+	int			numParents;
+
+	numParents = 0;
+	for (i = 0; i < numInherits; i++)
+	{
+		if (strcmp(inhinfo[i].inhrelid, oid) == 0)
+			numParents++;
+	}
+
+	*numParentsPtr = numParents;
+
+	if (numParents > 0)
+	{
+		*parentIndexes = (int *) malloc(sizeof(int) * numParents);
+		j = 0;
+		for (i = 0; i < numInherits; i++)
+		{
+			if (strcmp(inhinfo[i].inhrelid, oid) == 0)
+			{
+				parentInd = findTableByOid(tblinfo, numTables,
+										   inhinfo[i].inhparent);
+				if (parentInd < 0)
+				{
+					selfInd = findTableByOid(tblinfo, numTables, oid);
+					if (selfInd >= 0)
+						write_msg(NULL, "failed sanity check, parent oid %s of table %s (oid %s) not found\n",
+								  inhinfo[i].inhparent,
+								  tblinfo[selfInd].relname,
+								  oid);
+					else
+						write_msg(NULL, "failed sanity check, parent oid %s of table (oid %s) not found\n",
+								  inhinfo[i].inhparent,
+								  oid);
+
+					exit_nicely();
+				}
+				(*parentIndexes)[j++] = parentInd;
+			}
+		}
+	}
+	else
+		*parentIndexes = NULL;
+}
+
+/*
+ * parseNumericArray
+ *	  parse a string of numbers delimited by spaces into a character array
+ */
+
+void
+parseNumericArray(const char *str, char **array, int arraysize)
+{
+	int			j,
+				argNum;
+	char		temp[100];
+	char		s;
+
+	argNum = 0;
+	j = 0;
+	for (;;)
+	{
+		s = *str++;
+		if (s == ' ' || s == '\0')
+		{
+			if (j > 0)
+			{
+				if (argNum >= arraysize)
+				{
+					write_msg(NULL, "parseNumericArray: too many numbers\n");
+					exit_nicely();
+				}
+				temp[j] = '\0';
+				array[argNum++] = strdup(temp);
+				j = 0;
+			}
+			if (s == '\0')
+				break;
+		}
+		else
+		{
+			if (!(isdigit((unsigned char) s) || s == '-') ||
+				j >= sizeof(temp) - 1)
+			{
+				write_msg(NULL, "parseNumericArray: bogus number\n");
+				exit_nicely();
+			}
+			temp[j++] = s;
+		}
+	}
+
+	while (argNum < arraysize)
+		array[argNum++] = strdup("0");
+}
+
+
+/*
+ * strInArray:
+ *	  takes in a string and a string array and the number of elements in the
+ * string array.
+ *	  returns the index if the string is somewhere in the array, -1 otherwise
+ */
+
+static int
+strInArray(const char *pattern, char **arr, int arr_size)
 {
 	int			i;
 
-	for (i = 0; i < numFuncs; i++)
+	for (i = 0; i < arr_size; i++)
 	{
-		if (strcmp(finfo[i].proname, name) == 0)
+		if (strcmp(pattern, arr[i]) == 0)
 			return i;
 	}
 	return -1;
diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h
index 32d4c1e88eb..dca162cd76d 100644
--- a/src/bin/pg_dump/pg_backup.h
+++ b/src/bin/pg_dump/pg_backup.h
@@ -15,27 +15,7 @@
  *
  *
  * IDENTIFICATION
- *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.18 2002/02/11 00:18:20 tgl Exp $
- *
- * Modifications - 28-Jun-2000 - pjw@rhyme.com.au
- *
- *	Initial version.
- *
- *
- * Modifications - 28-Jul-2000 - pjw@rhyme.com.au (1.45)
- *
- *		Added --create, --no-owner, --superuser, --no-reconnect (pg_dump & pg_restore)
- *		Added code to dump 'Create Schema' statement (pg_dump)
- *		Don't bother to disable/enable triggers if we don't have a superuser (pg_restore)
- *		Cleaned up code for reconnecting to database.
- *		Force a reconnect as superuser before enabling/disabling triggers.
- *
- * Modifications - 31-Jul-2000 - pjw@rhyme.com.au (1.46, 1.47)
- *		Added & Removed --throttle (pg_dump)
- *		Fixed minor bug in language dumping code: expbuffres were not being reset.
- *		Fixed version number initialization in _allocAH (pg_backup_archiver.c)
- *		Added second connection when restoring BLOBs to allow temp. table to survive
- *		(db reconnection causes temp tables to be lost).
+ *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.19 2002/05/10 22:36:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -87,6 +67,7 @@ typedef struct _restoreOptions
 								 * cirsumstances */
 	int			use_setsessauth;/* use SET SESSSION AUTHORIZATION instead
 								 * of \connect */
+	int			disable_triggers;/* disable triggers during data-only restore */
 	char	   *superuser;		/* Username to use as superuser */
 	int			dataOnly;
 	int			dropSchema;
@@ -152,10 +133,12 @@ PGconn *ConnectDatabase(Archive *AH,
 
 
 /* Called to add a TOC entry */
-extern void ArchiveEntry(Archive *AH, const char *oid, const char *name,
-			 const char *desc, const char *((*deps)[]), const char *defn,
-		   const char *dropStmt, const char *copyStmt, const char *owner,
-			 DataDumperPtr dumpFn, void *dumpArg);
+extern void ArchiveEntry(Archive *AHX, const char *oid, const char *name,
+						 const char *namespace, const char *owner,
+						 const char *desc, const char *((*deps)[]),
+						 const char *defn, const char *dropStmt,
+						 const char *copyStmt,
+						 DataDumperPtr dumpFn, void *dumpArg);
 
 /* Called to write *data* to the archive */
 extern int	WriteData(Archive *AH, const void *data, int dLen);
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 11c62a0298c..272b98cecef 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.45 2002/05/06 17:34:45 tgl Exp $
+ *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.46 2002/05/10 22:36:26 tgl Exp $
  *
  * Modifications - 28-Jun-2000 - pjw@rhyme.com.au
  *
@@ -95,8 +95,10 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
 		 const int compression, ArchiveMode mode);
 static int	_printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData);
 
+static void _doSetSessionAuth(ArchiveHandle *AH, const char *autharg);
 static void _reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te);
 static void _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user);
+static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName);
 
 static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt);
 static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
@@ -208,23 +210,13 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
 		AHX->minRemoteVersion = 070100;
 		AHX->maxRemoteVersion = 999999;
 
-		ConnectDatabase(AHX, ropt->dbname, ropt->pghost, ropt->pgport, ropt->username,
+		ConnectDatabase(AHX, ropt->dbname,
+						ropt->pghost, ropt->pgport, ropt->username,
 						ropt->requirePassword, ropt->ignoreVersion);
-
-		/*
-		 * If no superuser was specified then see if the current user will
-		 * do...
-		 */
-		if (!ropt->superuser)
-		{
-			if (UserIsSuperuser(AH, ConnectedUser(AH)))
-				ropt->superuser = strdup(ConnectedUser(AH));
-		}
-
 	}
 
 	/*
-	 * Work out if we have an implied data-only retore. This can happen if
+	 * Work out if we have an implied data-only restore. This can happen if
 	 * the dump was data only or if the user has used a toc list to
 	 * exclude all of the schema data. All we do is look for schema
 	 * entries - if none are found then we set the dataOnly flag.
@@ -253,12 +245,6 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
 		}
 	}
 
-	if (!ropt->superuser)
-		write_msg(modulename, "WARNING:\n"
-				  "  Data restoration may fail because existing triggers cannot be disabled\n"
-				  "  (no superuser user name specified).  This is only a problem when\n"
-		"  restoring into a database with already existing triggers.\n");
-
 	/*
 	 * Setup the output file if necessary.
 	 */
@@ -280,8 +266,9 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
 			{
 				/* We want the schema */
 				ahlog(AH, 1, "dropping %s %s\n", te->desc, te->name);
-				/* Reconnect if necessary */
+				/* Select owner and schema as necessary */
 				_reconnectAsOwner(AH, NULL, te);
+				_selectOutputSchema(AH, te->namespace);
 				/* Drop it */
 				ahprintf(AH, "%s", te->dropStmt);
 			}
@@ -376,6 +363,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
 						 * have reconnected)
 						 */
 						_reconnectAsOwner(AH, NULL, te);
+						_selectOutputSchema(AH, te->namespace);
 
 						ahlog(AH, 1, "restoring data for table %s\n", te->name);
 
@@ -433,7 +421,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
 				if ((reqs & REQ_DATA) != 0)		/* We loaded the data */
 				{
 					ahlog(AH, 1, "fixing up large object cross-reference for %s\n", te->name);
-					FixupBlobRefs(AH, te->name);
+					FixupBlobRefs(AH, te);
 				}
 			}
 			else
@@ -501,30 +489,31 @@ _canRestoreBlobs(ArchiveHandle *AH)
 static void
 _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
 {
-	char	   *oldUser = NULL;
+	char	   *oldUser;
+	char	   *oldSchema;
 
-	/* Can't do much if we're connected & don't have a superuser */
-	/* Also, don't bother with triggers unless a data-only retore. */
-	if (!ropt->dataOnly || (_restoringToDB(AH) && !ropt->superuser))
+	/* This hack is only needed in a data-only restore */
+	if (!ropt->dataOnly || !ropt->disable_triggers)
 		return;
 
+	oldUser = strdup(AH->currUser);
+	oldSchema = strdup(AH->currSchema);
+
 	/*
-	 * Reconnect as superuser if possible, since they are the only ones
-	 * who can update pg_class...
+	 * Become superuser if possible, since they are the only ones
+	 * who can update pg_class.  If -S was not given, but we are allowed
+	 * to use SET SESSION AUTHORIZATION, assume the initial user identity
+	 * is a superuser.  Otherwise we just have to bull ahead anyway.
 	 */
 	if (ropt->superuser)
 	{
-		if (!_restoringToDB(AH) || !ConnectedUserIsSuperuser(AH))
-		{
-			/*
-			 * If we're not allowing changes for ownership, then remember
-			 * the user so we can change it back here. Otherwise, let
-			 * _reconnectAsOwner do what it has to do.
-			 */
-			if (ropt->noOwner)
-				oldUser = strdup(ConnectedUser(AH));
-			_reconnectAsUser(AH, NULL, ropt->superuser);
-		}
+		_reconnectAsUser(AH, NULL, ropt->superuser);
+		/* be careful to preserve schema setting */
+		_selectOutputSchema(AH, oldSchema);
+	}
+	else if (AH->ropt->use_setsessauth)
+	{
+		_doSetSessionAuth(AH, "DEFAULT");
 	}
 
 	ahlog(AH, 1, "disabling triggers\n");
@@ -538,52 +527,59 @@ _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *rop
 	/*
 	 * Just update the AFFECTED table, if known.
 	 */
-
 	if (te && te->name && strlen(te->name) > 0)
-		ahprintf(AH, "UPDATE \"pg_class\" SET \"reltriggers\" = 0 WHERE \"relname\" = '%s';\n\n",
-				 te->name);
+		ahprintf(AH, "UPDATE pg_class SET reltriggers = 0 "
+				 "WHERE oid = '%s'::regclass;\n\n",
+				 fmtId(te->name, false));
 	else
-		ahprintf(AH, "UPDATE \"pg_class\" SET \"reltriggers\" = 0 WHERE \"relname\" !~ '^pg_';\n\n");
+		ahprintf(AH, "UPDATE pg_class SET reltriggers = 0 FROM pg_namespace "
+				 "WHERE relnamespace = pg_namespace.oid AND nspname !~ '^pg_';\n\n");
 
 	/*
-	 * Restore the user connection from the start of this procedure if
-	 * _reconnectAsOwner is disabled.
+	 * Restore original user and schema state.
 	 */
-	if (ropt->noOwner && oldUser)
+	if (ropt->superuser)
 	{
 		_reconnectAsUser(AH, NULL, oldUser);
-		free(oldUser);
+		/* be careful to preserve schema setting */
+		_selectOutputSchema(AH, oldSchema);
 	}
+	else if (AH->ropt->use_setsessauth)
+	{
+		_doSetSessionAuth(AH, fmtId(oldUser, false));
+	}
+	free(oldUser);
+	free(oldSchema);
 }
 
 static void
 _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
 {
-	char	   *oldUser = NULL;
+	char	   *oldUser;
+	char	   *oldSchema;
 
-	/* Can't do much if we're connected & don't have a superuser */
-	/* Also, don't bother with triggers unless a data-only retore. */
-	if (!ropt->dataOnly || (_restoringToDB(AH) && !ropt->superuser))
+	/* This hack is only needed in a data-only restore */
+	if (!ropt->dataOnly || !ropt->disable_triggers)
 		return;
 
+	oldUser = strdup(AH->currUser);
+	oldSchema = strdup(AH->currSchema);
+
 	/*
-	 * Reconnect as superuser if possible, since they are the only ones
-	 * who can update pg_class...
+	 * Become superuser if possible, since they are the only ones
+	 * who can update pg_class.  If -S was not given, but we are allowed
+	 * to use SET SESSION AUTHORIZATION, assume the initial user identity
+	 * is a superuser.  Otherwise we just have to bull ahead anyway.
 	 */
 	if (ropt->superuser)
 	{
-		if (!_restoringToDB(AH) || !ConnectedUserIsSuperuser(AH))
-		{
-			/*
-			 * If we're not allowing changes for ownership, then remember
-			 * the user so we can change it back here. Otherwise, let
-			 * _reconnectAsOwner do what it has to do
-			 */
-			if (ropt->noOwner)
-				oldUser = strdup(ConnectedUser(AH));
-
-			_reconnectAsUser(AH, NULL, ropt->superuser);
-		}
+		_reconnectAsUser(AH, NULL, ropt->superuser);
+		/* be careful to preserve schema setting */
+		_selectOutputSchema(AH, oldSchema);
+	}
+	else if (AH->ropt->use_setsessauth)
+	{
+		_doSetSessionAuth(AH, "DEFAULT");
 	}
 
 	ahlog(AH, 1, "enabling triggers\n");
@@ -593,29 +589,36 @@ _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt
 	 * 'SET' command when one is available.
 	 */
 	ahprintf(AH, "-- Enable triggers\n");
+
+	/*
+	 * Just update the AFFECTED table, if known.
+	 */
 	if (te && te->name && strlen(te->name) > 0)
-	{
 		ahprintf(AH, "UPDATE pg_class SET reltriggers = "
-		"(SELECT count(*) FROM pg_trigger where pg_class.oid = tgrelid) "
-				 "WHERE relname = '%s';\n\n",
-				 te->name);
-	}
+				 "(SELECT count(*) FROM pg_trigger where pg_class.oid = tgrelid) "
+				 "WHERE oid = '%s'::regclass;\n\n",
+				 fmtId(te->name, false));
 	else
-	{
-		ahprintf(AH, "UPDATE \"pg_class\" SET \"reltriggers\" = "
-		"(SELECT count(*) FROM pg_trigger where pg_class.oid = tgrelid) "
-				 "WHERE \"relname\" !~ '^pg_';\n\n");
-	}
+		ahprintf(AH, "UPDATE pg_class SET reltriggers = "
+				 "(SELECT count(*) FROM pg_trigger where pg_class.oid = tgrelid) "
+				 "FROM pg_namespace "
+				 "WHERE relnamespace = pg_namespace.oid AND nspname !~ '^pg_';\n\n");
 
 	/*
-	 * Restore the user connection from the start of this procedure if
-	 * _reconnectAsOwner is disabled.
+	 * Restore original user and schema state.
 	 */
-	if (ropt->noOwner && oldUser)
+	if (ropt->superuser)
 	{
 		_reconnectAsUser(AH, NULL, oldUser);
-		free(oldUser);
+		/* be careful to preserve schema setting */
+		_selectOutputSchema(AH, oldSchema);
 	}
+	else if (AH->ropt->use_setsessauth)
+	{
+		_doSetSessionAuth(AH, fmtId(oldUser, false));
+	}
+	free(oldUser);
+	free(oldSchema);
 }
 
 /*
@@ -642,8 +645,10 @@ WriteData(Archive *AHX, const void *data, int dLen)
 /* Public */
 void
 ArchiveEntry(Archive *AHX, const char *oid, const char *name,
-			 const char *desc, const char *((*deps)[]), const char *defn,
-		   const char *dropStmt, const char *copyStmt, const char *owner,
+			 const char *namespace, const char *owner,
+			 const char *desc, const char *((*deps)[]),
+			 const char *defn, const char *dropStmt,
+			 const char *copyStmt,
 			 DataDumperPtr dumpFn, void *dumpArg)
 {
 	ArchiveHandle *AH = (ArchiveHandle *) AHX;
@@ -664,21 +669,21 @@ ArchiveEntry(Archive *AHX, const char *oid, const char *name,
 	newToc->id = AH->lastID;
 
 	newToc->name = strdup(name);
+	newToc->namespace = namespace ? strdup(namespace) : NULL;
+	newToc->owner = strdup(owner);
 	newToc->desc = strdup(desc);
+	newToc->defn = strdup(defn);
+	newToc->dropStmt = strdup(dropStmt);
+	newToc->copyStmt = copyStmt ? strdup(copyStmt) : NULL;
 
 	newToc->oid = strdup(oid);
-	newToc->depOid = deps;
+	newToc->depOid = deps;		/* NB: not copied */
 	_fixupOidInfo(newToc);
 
-
-	newToc->defn = strdup(defn);
-	newToc->dropStmt = strdup(dropStmt);
-	newToc->copyStmt = copyStmt ? strdup(copyStmt) : NULL;
-	newToc->owner = strdup(owner);
 	newToc->printed = 0;
 	newToc->formatData = NULL;
-	newToc->dataDumper = dumpFn,
-		newToc->dataDumperArg = dumpArg;
+	newToc->dataDumper = dumpFn;
+	newToc->dataDumperArg = dumpArg;
 
 	newToc->hadDumper = dumpFn ? 1 : 0;
 
@@ -1667,6 +1672,7 @@ _allocAH(const char *FileSpec, const ArchiveFormat fmt,
 
 	AH->currUser = strdup("");	/* So it's valid, but we can free() it
 								 * later if necessary */
+	AH->currSchema = strdup(""); /* ditto */
 
 	AH->toc = (TocEntry *) calloc(1, sizeof(TocEntry));
 	if (!AH->toc)
@@ -1789,6 +1795,7 @@ WriteToc(ArchiveHandle *AH)
 		WriteStr(AH, te->defn);
 		WriteStr(AH, te->dropStmt);
 		WriteStr(AH, te->copyStmt);
+		WriteStr(AH, te->namespace);
 		WriteStr(AH, te->owner);
 
 		/* Dump list of dependencies */
@@ -1840,6 +1847,9 @@ ReadToc(ArchiveHandle *AH)
 		if (AH->version >= K_VERS_1_3)
 			te->copyStmt = ReadStr(AH);
 
+		if (AH->version >= K_VERS_1_6)
+			te->namespace = ReadStr(AH);
+
 		te->owner = ReadStr(AH);
 
 		/* Read TOC entry dependencies */
@@ -1975,6 +1985,33 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
 	return res;
 }
 
+/*
+ * Issue a SET SESSION AUTHORIZATION command.  Caller is responsible
+ * for updating state if appropriate.  Note that caller must also quote
+ * the argument if it's a username (it might be DEFAULT, too).
+ */
+static void
+_doSetSessionAuth(ArchiveHandle *AH, const char *autharg)
+{
+	if (RestoringToDB(AH))
+	{
+		PQExpBuffer qry = createPQExpBuffer();
+		PGresult   *res;
+
+		appendPQExpBuffer(qry, "SET SESSION AUTHORIZATION %s;", autharg);
+		res = PQexec(AH->connection, qry->data);
+
+		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
+			die_horribly(AH, modulename, "could not set session user to %s: %s",
+						 autharg, PQerrorMessage(AH->connection));
+
+		PQclear(res);
+		destroyPQExpBuffer(qry);
+	}
+	else
+		ahprintf(AH, "SET SESSION AUTHORIZATION %s;\n\n", autharg);
+}
+
 
 /*
  * Issue the commands to connect to the database as the specified user
@@ -1999,25 +2036,7 @@ _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
 	 */
 	if (!dbname && AH->ropt->use_setsessauth)
 	{
-		if (RestoringToDB(AH))
-		{
-			PQExpBuffer qry = createPQExpBuffer();
-			PGresult   *res;
-
-			appendPQExpBuffer(qry, "SET SESSION AUTHORIZATION %s;",
-							  fmtId(user, false));
-			res = PQexec(AH->connection, qry->data);
-
-			if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
-				die_horribly(AH, modulename, "could not set session user to %s: %s",
-							 user, PQerrorMessage(AH->connection));
-
-			PQclear(res);
-			destroyPQExpBuffer(qry);
-		}
-		else
-			ahprintf(AH, "SET SESSION AUTHORIZATION %s;\n\n",
-					 fmtId(user, false));
+		_doSetSessionAuth(AH, fmtId(user, false));
 	}
 	else if (AH->ropt && AH->ropt->noReconnect)
 	{
@@ -2038,6 +2057,11 @@ _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
 		ahprintf(AH, qry->data);
 
 		destroyPQExpBuffer(qry);
+
+		/* don't assume we still know the output schema */
+		if (AH->currSchema)
+			free(AH->currSchema);
+		AH->currSchema = strdup("");
 	}
 
 	/*
@@ -2066,6 +2090,43 @@ _reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te)
 }
 
 
+/*
+ * Issue the commands to select the specified schema as the current schema
+ * in the target database.
+ */
+static void
+_selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
+{
+	if (!schemaName || *schemaName == '\0' ||
+		strcmp(AH->currSchema, schemaName) == 0)
+		return;					/* no need to do anything */
+
+	if (RestoringToDB(AH))
+	{
+		PQExpBuffer qry = createPQExpBuffer();
+		PGresult   *res;
+
+		appendPQExpBuffer(qry, "SET search_path = %s;",
+						  fmtId(schemaName, false));
+		res = PQexec(AH->connection, qry->data);
+
+		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
+			die_horribly(AH, modulename, "could not set search_path to %s: %s",
+						 schemaName, PQerrorMessage(AH->connection));
+
+		PQclear(res);
+		destroyPQExpBuffer(qry);
+	}
+	else
+		ahprintf(AH, "SET search_path = %s;\n\n",
+				 fmtId(schemaName, false));
+
+	if (AH->currSchema)
+		free(AH->currSchema);
+	AH->currSchema = strdup(schemaName);
+}
+
+
 /*
  * fmtId
  *
@@ -2139,16 +2200,19 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
 {
 	char	   *pfx;
 
-	/* Reconnect if necessary */
+	/* Select owner and schema as necessary */
 	_reconnectAsOwner(AH, NULL, te);
+	_selectOutputSchema(AH, te->namespace);
 
 	if (isData)
 		pfx = "Data for ";
 	else
 		pfx = "";
 
-	ahprintf(AH, "--\n-- %sTOC Entry ID %d (OID %s)\n--\n-- Name: %s Type: %s Owner: %s\n",
-			 pfx, te->id, te->oid, te->name, te->desc, te->owner);
+	ahprintf(AH, "--\n-- %sTOC Entry ID %d (OID %s)\n--\n-- Name: %s Type: %s Schema: %s Owner: %s\n",
+			 pfx, te->id, te->oid, te->name, te->desc,
+			 te->namespace ? te->namespace : "-",
+			 te->owner);
 	if (AH->PrintExtraTocPtr !=NULL)
 		(*AH->PrintExtraTocPtr) (AH, te);
 	ahprintf(AH, "--\n\n");
diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h
index 0fbce03f52c..95ab2133ca5 100644
--- a/src/bin/pg_dump/pg_backup_archiver.h
+++ b/src/bin/pg_dump/pg_backup_archiver.h
@@ -17,17 +17,7 @@
  *
  *
  * IDENTIFICATION
- *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.42 2002/04/24 02:21:04 momjian Exp $
- *
- * Modifications - 28-Jun-2000 - pjw@rhyme.com.au
- *	-	Initial version.
- *
- * Modifications - 15-Sep-2000 - pjw@rhyme.com.au
- *	-	Added braceDepth to sqlparseInfo to handle braces in rule definitions.
- *
- * Modifications - 31-Mar-2001 - pjw@rhyme.com.au (1.50)
- *	-	Make dependencies work on ArchiveEntry calls so that UDTs will
- *		dump in correct order.
+ *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.43 2002/05/10 22:36:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -68,8 +58,8 @@ typedef z_stream *z_streamp;
 #include "libpq-fe.h"
 
 #define K_VERS_MAJOR 1
-#define K_VERS_MINOR 5
-#define K_VERS_REV 7
+#define K_VERS_MINOR 6
+#define K_VERS_REV 0
 
 /* Data block types */
 #define BLK_DATA 1
@@ -82,7 +72,8 @@ typedef z_stream *z_streamp;
 #define K_VERS_1_3 (( (1 * 256 + 3) * 256 + 0) * 256 + 0)		/* BLOBs */
 #define K_VERS_1_4 (( (1 * 256 + 4) * 256 + 0) * 256 + 0)		/* Date & name in header */
 #define K_VERS_1_5 (( (1 * 256 + 5) * 256 + 0) * 256 + 0)		/* Handle dependencies */
-#define K_VERS_MAX (( (1 * 256 + 5) * 256 + 255) * 256 + 0)
+#define K_VERS_1_6 (( (1 * 256 + 6) * 256 + 0) * 256 + 0)		/* Schema field in TOCs */
+#define K_VERS_MAX (( (1 * 256 + 6) * 256 + 255) * 256 + 0)
 
 /* No of BLOBs to restore in 1 TX */
 #define BLOB_BATCH_SIZE 100
@@ -235,6 +226,7 @@ typedef struct _archiveHandle
 	int			tocCount;		/* Number of TOC entries */
 	struct _tocEntry *currToc;	/* Used when dumping data */
 	char	   *currUser;		/* Restore: current username in script */
+	char	   *currSchema;		/* Restore: current schema in script */
 	int			compression;	/* Compression requested on open */
 	ArchiveMode mode;			/* File mode - r or w */
 	void	   *formatData;		/* Header data specific to file format */
@@ -254,11 +246,12 @@ typedef struct _tocEntry
 	int			hadDumper;		/* Archiver was passed a dumper routine
 								 * (used in restore) */
 	char	   *name;
+	char	   *namespace;		/* null or empty string if not in a schema */
+	char	   *owner;
 	char	   *desc;
 	char	   *defn;
 	char	   *dropStmt;
 	char	   *copyStmt;
-	char	   *owner;
 	char	   *oid;			/* Oid of source of entry */
 	Oid			oidVal;			/* Value of above */
 	const char *((*depOid)[]);
@@ -314,9 +307,6 @@ extern OutputContext SetOutput(ArchiveHandle *AH, char *filename, int compressio
 extern void ResetOutput(ArchiveHandle *AH, OutputContext savedContext);
 extern int	RestoringToDB(ArchiveHandle *AH);
 extern int	ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *newUser);
-extern int	UserIsSuperuser(ArchiveHandle *AH, char *user);
-extern char *ConnectedUser(ArchiveHandle *AH);
-extern int	ConnectedUserIsSuperuser(ArchiveHandle *AH);
 
 int			ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH);
 int			ahprintf(ArchiveHandle *AH, const char *fmt,...) __attribute__((format(printf, 2, 3)));
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index be638d226fc..eb7bcafbc30 100644
--- a/src/bin/pg_dump/pg_backup_db.c
+++ b/src/bin/pg_dump/pg_backup_db.c
@@ -5,25 +5,7 @@
  *	Implements the basic DB functions used by the archiver.
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.31 2002/01/18 19:17:05 momjian Exp $
- *
- * NOTES
- *
- * Modifications - 04-Jan-2001 - pjw@rhyme.com.au
- *
- *	  - Check results of PQ routines more carefully.
- *
- * Modifications - 19-Mar-2001 - pjw@rhyme.com.au
- *
- *	  - Avoid forcing table name to lower case in FixupBlobXrefs!
- *
- *
- * Modifications - 18-Jan-2002 - pjw@rhyme.com.au
- *
- *	  - Split ExecuteSqlCommandBuf into 3 routines for (slightly) improved
- *		clarity. Modify loop to cater for COPY commands buried in the SQL
- *		command buffer (prev version assumed COPY command was executed
- *		in prior call). This was to fix the buf in the 'set max oid' code.
+ *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.32 2002/05/10 22:36:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -219,57 +201,6 @@ _check_database_version(ArchiveHandle *AH, bool ignoreVersion)
 	}
 }
 
-/*
- * Check if a given user is a superuser.
- */
-int
-UserIsSuperuser(ArchiveHandle *AH, char *user)
-{
-	PQExpBuffer qry = createPQExpBuffer();
-	PGresult   *res;
-	int			i_usesuper;
-	int			ntups;
-	int			isSuper;
-
-	/* Get the superuser setting */
-	appendPQExpBuffer(qry, "select usesuper from pg_user where usename = '%s'", user);
-	res = PQexec(AH->connection, qry->data);
-
-	if (!res)
-		die_horribly(AH, modulename, "null result checking superuser status of %s\n", user);
-
-	if (PQresultStatus(res) != PGRES_TUPLES_OK)
-		die_horribly(AH, modulename, "could not check superuser status of %s: %s",
-					 user, PQerrorMessage(AH->connection));
-
-	ntups = PQntuples(res);
-
-	if (ntups == 0)
-		isSuper = 0;
-	else
-	{
-		i_usesuper = PQfnumber(res, "usesuper");
-		isSuper = (strcmp(PQgetvalue(res, 0, i_usesuper), "t") == 0);
-	}
-	PQclear(res);
-
-	destroyPQExpBuffer(qry);
-
-	return isSuper;
-}
-
-int
-ConnectedUserIsSuperuser(ArchiveHandle *AH)
-{
-	return UserIsSuperuser(AH, PQuser(AH->connection));
-}
-
-char *
-ConnectedUser(ArchiveHandle *AH)
-{
-	return PQuser(AH->connection);
-}
-
 /*
  * Reconnect to the server.  If dbname is not NULL, use that database,
  * else the one associated with the archive handle.  If username is
@@ -310,6 +241,11 @@ ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *username)
 	AH->username = strdup(newusername);
 	/* XXX Why don't we update AH->dbname? */
 
+	/* don't assume we still know the output schema */
+	if (AH->currSchema)
+		free(AH->currSchema);
+	AH->currSchema = strdup("");
+
 	return 1;
 }
 
@@ -481,13 +417,6 @@ ConnectDatabase(Archive *AHX,
 
 	PQsetNoticeProcessor(AH->connection, notice_processor, NULL);
 
-	/*
-	 * AH->currUser = PQuser(AH->connection);
-	 *
-	 * Removed because it prevented an initial \connect when dumping to SQL
-	 * in pg_dump.
-	 */
-
 	return AH->connection;
 }
 
@@ -775,8 +704,9 @@ ExecuteSqlCommandBuf(ArchiveHandle *AH, void *qryv, int bufLen)
 }
 
 void
-FixupBlobRefs(ArchiveHandle *AH, char *tablename)
+FixupBlobRefs(ArchiveHandle *AH, TocEntry *te)
 {
+	PQExpBuffer tblName;
 	PQExpBuffer tblQry;
 	PGresult   *res,
 			   *uRes;
@@ -784,44 +714,55 @@ FixupBlobRefs(ArchiveHandle *AH, char *tablename)
 				n;
 	char	   *attr;
 
-	if (strcmp(tablename, BLOB_XREF_TABLE) == 0)
+	if (strcmp(te->name, BLOB_XREF_TABLE) == 0)
 		return;
 
+	tblName = createPQExpBuffer();
 	tblQry = createPQExpBuffer();
 
-	appendPQExpBuffer(tblQry, "SELECT a.attname FROM pg_class c, pg_attribute a, pg_type t "
-	 " WHERE a.attnum > 0 AND a.attrelid = c.oid AND a.atttypid = t.oid "
-	 " AND t.typname in ('oid', 'lo') AND c.relname = '%s';", tablename);
+	if (te->namespace && strlen(te->namespace) > 0)
+		appendPQExpBuffer(tblName, "%s.",
+						  fmtId(te->namespace, false));
+	appendPQExpBuffer(tblName, "%s",
+					  fmtId(te->name, false));
+
+	appendPQExpBuffer(tblQry,
+					  "SELECT a.attname FROM "
+					  "pg_catalog.pg_attribute a, pg_catalog.pg_type t "
+					  "WHERE a.attnum > 0 AND a.attrelid = '%s'::regclass "
+					  "AND a.atttypid = t.oid AND t.typname in ('oid', 'lo')",
+					  tblName->data);
 
 	res = PQexec(AH->blobConnection, tblQry->data);
 	if (!res)
 		die_horribly(AH, modulename, "could not find oid columns of table \"%s\": %s",
-					 tablename, PQerrorMessage(AH->connection));
+					 te->name, PQerrorMessage(AH->connection));
 
 	if ((n = PQntuples(res)) == 0)
 	{
 		/* nothing to do */
-		ahlog(AH, 1, "no OID type columns in table %s\n", tablename);
+		ahlog(AH, 1, "no OID type columns in table %s\n", te->name);
 	}
 
 	for (i = 0; i < n; i++)
 	{
 		attr = PQgetvalue(res, i, 0);
 
-		ahlog(AH, 1, "fixing large object cross-references for %s.%s\n", tablename, attr);
+		ahlog(AH, 1, "fixing large object cross-references for %s.%s\n",
+			  te->name, attr);
 
 		resetPQExpBuffer(tblQry);
 
-		/*
-		 * We should use coalesce here (rather than 'exists'), but it
-		 * seems to be broken in 7.0.2 (weird optimizer strategy)
-		 */
-		appendPQExpBuffer(tblQry, "UPDATE \"%s\" SET \"%s\" = ", tablename, attr);
-		appendPQExpBuffer(tblQry, " (SELECT x.newOid FROM \"%s\" x WHERE x.oldOid = \"%s\".\"%s\")",
-						  BLOB_XREF_TABLE, tablename, attr);
-		appendPQExpBuffer(tblQry, " where exists"
-				  "(select * from %s x where x.oldOid = \"%s\".\"%s\");",
-						  BLOB_XREF_TABLE, tablename, attr);
+		/* Can't use fmtId twice in one call... */
+		appendPQExpBuffer(tblQry,
+						  "UPDATE %s SET %s = %s.newOid",
+						  tblName->data, fmtId(attr, false),
+						  BLOB_XREF_TABLE);
+		appendPQExpBuffer(tblQry,
+						  " FROM %s WHERE %s.oldOid = %s.%s",
+						  BLOB_XREF_TABLE,
+						  BLOB_XREF_TABLE,
+						  tblName->data, fmtId(attr, false));
 
 		ahlog(AH, 10, "SQL: %s\n", tblQry->data);
 
@@ -829,17 +770,18 @@ FixupBlobRefs(ArchiveHandle *AH, char *tablename)
 		if (!uRes)
 			die_horribly(AH, modulename,
 					"could not update column \"%s\" of table \"%s\": %s",
-					attr, tablename, PQerrorMessage(AH->blobConnection));
+					attr, te->name, PQerrorMessage(AH->blobConnection));
 
 		if (PQresultStatus(uRes) != PGRES_COMMAND_OK)
 			die_horribly(AH, modulename,
 				"error while updating column \"%s\" of table \"%s\": %s",
-					attr, tablename, PQerrorMessage(AH->blobConnection));
+					attr, te->name, PQerrorMessage(AH->blobConnection));
 
 		PQclear(uRes);
 	}
 
 	PQclear(res);
+	destroyPQExpBuffer(tblName);
 	destroyPQExpBuffer(tblQry);
 }
 
diff --git a/src/bin/pg_dump/pg_backup_db.h b/src/bin/pg_dump/pg_backup_db.h
index 463526922d9..d4baa55538d 100644
--- a/src/bin/pg_dump/pg_backup_db.h
+++ b/src/bin/pg_dump/pg_backup_db.h
@@ -2,12 +2,12 @@
  *	Definitions for pg_backup_db.c
  *
  *	IDENTIFICATION
- *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.h,v 1.5 2001/06/27 21:21:37 petere Exp $
+ *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.h,v 1.6 2002/05/10 22:36:26 tgl Exp $
  */
 
-#define BLOB_XREF_TABLE "dump_blob_xref"		/* MUST be lower case */
+#define BLOB_XREF_TABLE "pg_dump_blob_xref"		/* MUST be lower case */
 
-extern void FixupBlobRefs(ArchiveHandle *AH, char *tablename);
+extern void FixupBlobRefs(ArchiveHandle *AH, TocEntry *te);
 extern int	ExecuteSqlCommand(ArchiveHandle *AH, PQExpBuffer qry, char *desc, bool use_blob);
 extern int	ExecuteSqlCommandBuf(ArchiveHandle *AH, void *qry, int bufLen);
 
diff --git a/src/bin/pg_dump/pg_backup_null.c b/src/bin/pg_dump/pg_backup_null.c
index af8f52a7c20..beb6ed12b64 100644
--- a/src/bin/pg_dump/pg_backup_null.c
+++ b/src/bin/pg_dump/pg_backup_null.c
@@ -3,7 +3,7 @@
  * pg_backup_null.c
  *
  *	Implementation of an archive that is never saved; it is used by
- *	pg_dump to output output a plain text SQL script instead of save
+ *	pg_dump to output a plain text SQL script instead of save
  *	a real archive.
  *
  *	See the headers to pg_restore for more details.
@@ -17,7 +17,7 @@
  *
  *
  * IDENTIFICATION
- *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_null.c,v 1.8 2002/04/24 02:21:04 momjian Exp $
+ *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_null.c,v 1.9 2002/05/10 22:36:26 tgl Exp $
  *
  * Modifications - 09-Jul-2000 - pjw@rhyme.com.au
  *
diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c
index efd8a030133..783b8a31361 100644
--- a/src/bin/pg_dump/pg_backup_tar.c
+++ b/src/bin/pg_dump/pg_backup_tar.c
@@ -16,7 +16,7 @@
  *
  *
  * IDENTIFICATION
- *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_tar.c,v 1.21 2002/04/24 02:21:04 momjian Exp $
+ *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_tar.c,v 1.22 2002/05/10 22:36:26 tgl Exp $
  *
  * Modifications - 28-Jun-2000 - pjw@rhyme.com.au
  *
@@ -835,7 +835,7 @@ _CloseArchive(ArchiveHandle *AH)
 		ropt = NewRestoreOptions();
 		ropt->dropSchema = 1;
 		ropt->compression = 0;
-		ropt->superuser = PQuser(AH->connection);
+		ropt->superuser = NULL;
 		ropt->suppressDumpWarnings = true;
 
 		savVerbose = AH->public.verbose;
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 20c847ea63c..c3f89cb85df 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.258 2002/05/06 18:33:45 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.259 2002/05/10 22:36:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,6 +64,7 @@
 #include "pg_backup.h"
 #include "pg_backup_archiver.h"
 
+
 typedef enum _formatLiteralOptions
 {
 	CONV_ALL = 0,
@@ -74,31 +75,55 @@ typedef enum _formatLiteralOptions
 	/* only checks for 'opts == CONV_ALL' anyway. */
 } formatLiteralOptions;
 
-static void dumpComment(Archive *fout, const char *target, const char *oid,
-			const char *classname, int subid,
-			const char *((*deps)[]));
+typedef struct _dumpContext
+{
+	TableInfo  *tblinfo;
+	int			tblidx;
+	bool		oids;
+} DumpContext;
+
+static void help(const char *progname);
+static int	parse_version(const char *versionString);
+static NamespaceInfo *findNamespace(const char *nsoid, const char *objoid);
+static void dumpClasses(const TableInfo *tblinfo, const int numTables,
+						Archive *fout, const bool oids);
+static void dumpComment(Archive *fout, const char *target,
+						const char *namespace, const char *owner,
+						const char *oid, const char *classname, int subid,
+						const char *((*deps)[]));
+static void dumpOneBaseType(Archive *fout, TypeInfo *tinfo,
+							FuncInfo *g_finfo, int numFuncs,
+							TypeInfo *g_tinfo, int numTypes);
 static void dumpOneDomain(Archive *fout, TypeInfo *tinfo);
-static void dumpSequence(Archive *fout, TableInfo tbinfo, const bool schemaOnly, const bool dataOnly);
+static void dumpOneTable(Archive *fout, TableInfo *tbinfo,
+						 TableInfo *g_tblinfo);
+static void dumpOneSequence(Archive *fout, TableInfo *tbinfo,
+							const bool schemaOnly, const bool dataOnly);
 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,
-		  TableInfo *tblinfo, int numTables);
-static void formatStringLiteral(PQExpBuffer buf, const char *str, const formatLiteralOptions opts);
-static void clearTableInfo(TableInfo *, int);
-static void dumpOneFunc(Archive *fout, FuncInfo *finfo, int i,
-			TypeInfo *tinfo, int numTypes);
+static void dumpTriggers(Archive *fout, TableInfo *tblinfo, int numTables);
+static void dumpRules(Archive *fout, TableInfo *tblinfo, int numTables);
+static void formatStringLiteral(PQExpBuffer buf, const char *str,
+								const formatLiteralOptions opts);
+static void dumpOneFunc(Archive *fout, FuncInfo *finfo);
+static void dumpOneOpr(Archive *fout, OprInfo *oprinfo,
+					   OprInfo *g_oprinfo, int numOperators);
+static const char *convertRegProcReference(const char *proc);
+static const char *convertOperatorReference(const char *opr,
+						OprInfo *g_oprinfo, int numOperators);
+static void dumpOneAgg(Archive *fout, AggInfo *agginfo);
 static Oid	findLastBuiltinOid_V71(const char *);
 static Oid	findLastBuiltinOid_V70(void);
 static void setMaxOid(Archive *fout);
-
+static void selectSourceSchema(const char *schemaName);
+static char *getFormattedTypeName(const char *oid, OidOptions opts);
+static char *myFormatType(const char *typname, int32 typmod);
+static const char *fmtQualifiedId(const char *schema, const char *id);
 
 static void AddAcl(char *aclbuf, const char *keyword);
 static char *GetPrivileges(Archive *AH, const char *s);
 
 static int	dumpBlobs(Archive *AH, char *, void *);
 static int	dumpDatabase(Archive *AH);
-static PQExpBuffer getPKconstraint(TableInfo *tblInfo, IndInfo *indInfo);
 static const char *getAttrName(int attrnum, TableInfo *tblInfo);
 
 extern char *optarg;
@@ -108,10 +133,10 @@ extern int	optind,
 /* global decls */
 bool		g_verbose;			/* User wants verbose narration of our
 								 * activities. */
-Oid			g_last_builtin_oid; /* value of the last builtin oid */
 Archive    *g_fout;				/* the script file */
 PGconn	   *g_conn;				/* the database connection */
 
+/* various user-settable parameters */
 bool		force_quotes;		/* User wants to suppress double-quotes */
 bool		dumpData;			/* dump data using proper insert strings */
 bool		attrNames;			/* put attr names into insert strings */
@@ -119,1022 +144,1067 @@ bool		schemaOnly;
 bool		dataOnly;
 bool		aclsSkip;
 
+/* obsolete as of 7.3: */
+static Oid	g_last_builtin_oid; /* value of the last builtin oid */
+
+static char *selectTablename = NULL;	/* name of a single table to dump */
+
 char		g_opaque_type[10];	/* name for the opaque type */
 
 /* placeholders for the delimiters for comments */
 char		g_comment_start[10];
 char		g_comment_end[10];
 
+/* these are to avoid passing around info for findNamespace() */
+static NamespaceInfo *g_namespaces;
+static int	g_numNamespaces;
 
-typedef struct _dumpContext
+
+int
+main(int argc, char **argv)
 {
+	int			c;
+	const char *filename = NULL;
+	const char *format = "p";
+	const char *dbname = NULL;
+	const char *pghost = NULL;
+	const char *pgport = NULL;
+	const char *username = NULL;
+	bool		oids = false;
 	TableInfo  *tblinfo;
-	int			tblidx;
-	bool		oids;
-} DumpContext;
+	int			numTables;
+	bool		force_password = false;
+	int			compressLevel = -1;
+	bool		ignore_version = false;
+	int			plainText = 0;
+	int			outputClean = 0;
+	int			outputCreate = 0;
+	int			outputBlobs = 0;
+	int			outputNoOwner = 0;
+	int			outputNoReconnect = 0;
+	static int	use_setsessauth = 0;
+	static int	disable_triggers = 0;
+	char	   *outputSuperuser = NULL;
 
-static void
-help(const char *progname)
-{
-	printf(gettext("%s dumps a database as a text file or to other formats.\n\n"), progname);
-	puts(gettext("Usage:"));
-	printf(gettext("  %s [options] dbname\n\n"), progname);
-	puts(gettext("Options:"));
+	RestoreOptions *ropt;
 
 #ifdef HAVE_GETOPT_LONG
-	puts(gettext(
-		"  -a, --data-only          dump only the data, not the schema\n"
-		"  -b, --blobs              include large objects in dump\n"
-		"  -c, --clean              clean (drop) schema prior to create\n"
-		"  -C, --create             include commands to create database in dump\n"
-		"  -d, --inserts            dump data as INSERT, rather than COPY, commands\n"
-		"  -D, --column-inserts     dump data as INSERT commands with column names\n"
-		"  -f, --file=FILENAME      output file name\n"
-		"  -F, --format {c|t|p}     output file format (custom, tar, plain text)\n"
-		"  -h, --host=HOSTNAME      database server host name\n"
-		"  -i, --ignore-version     proceed even when server version mismatches\n"
-		"                           pg_dump version\n"
-		"  -n, --no-quotes          suppress most quotes around identifiers\n"
-		"  -N, --quotes             enable most quotes around identifiers\n"
-		"  -o, --oids               include oids in dump\n"
-		"  -O, --no-owner           do not output \\connect commands in plain\n"
-		"                           text format\n"
-		"  -p, --port=PORT          database server port number\n"
-		"  -R, --no-reconnect       disable ALL reconnections to the database in\n"
-		"                           plain text format\n"
-		"  -s, --schema-only        dump only the schema, no data\n"
-		"  -S, --superuser=NAME     specify the superuser user name to use in\n"
-		"                           plain text format\n"
-		"  -t, --table=TABLE        dump this table only (* for all)\n"
-		"  -U, --username=NAME      connect as specified database user\n"
-		"  -v, --verbose            verbose mode\n"
-		"  -W, --password           force password prompt (should happen automatically)\n"
-		"  -x, --no-privileges      do not dump privileges (grant/revoke)\n"
-		"  -X use-set-session-authorization, --use-set-session-authorization\n"
-		"                           output SET SESSION AUTHORIZATION commands rather\n"
-		"                           than \\connect commands\n"
-		"  -Z, --compress {0-9}     compression level for compressed formats\n"
-	));
-#else
-	puts(gettext(
-		"  -a                       dump only the data, not the schema\n"
-		"  -b                       include large objects in dump\n"
-		"  -c                       clean (drop) schema prior to create\n"
-		"  -C                       include commands to create database in dump\n"
-		"  -d                       dump data as INSERT, rather than COPY, commands\n"
-		"  -D                       dump data as INSERT commands with column names\n"
-		"  -f FILENAME              output file name\n"
-		"  -F {c|t|p}               output file format (custom, tar, plain text)\n"
-		"  -h HOSTNAME              database server host name\n"
-		"  -i                       proceed even when server version mismatches\n"
-		"                           pg_dump version\n"
-		"  -n                       suppress most quotes around identifiers\n"
-		"  -N                       enable most quotes around identifiers\n"
-		"  -o                       include oids in dump\n"
-		"  -O                       do not output \\connect commands in plain\n"
-		"                           text format\n"
-		"  -p PORT                  database server port number\n"
-		"  -R                       disable ALL reconnections to the database in\n"
-		"                           plain text format\n"
-		"  -s                       dump only the schema, no data\n"
-		"  -S NAME                  specify the superuser user name to use in\n"
-		"                           plain text format\n"
-		"  -t TABLE                 dump this table only (* for all)\n"
-		"  -U NAME                  connect as specified database user\n"
-		"  -v                       verbose mode\n"
-		"  -W                       force password prompt (should happen automatically)\n"
-		"  -x                       do not dump privileges (grant/revoke)\n"
-		"  -X use-set-session-authorization\n"
-		"                           output SET SESSION AUTHORIZATION commands rather\n"
-		"                           than \\connect commands\n"
-		"  -Z {0-9}                 compression level for compressed formats\n"
-	));
-#endif
-	puts(gettext("If no database name is not supplied, then the PGDATABASE environment\n"
-				 "variable value is used.\n\n"
-				 "Report bugs to <pgsql-bugs@postgresql.org>."));
-}
-
-
-void
-exit_nicely(void)
-{
-	PQfinish(g_conn);
-	if (g_verbose)
-		write_msg(NULL, "*** aborted because of error\n");
-	exit(1);
-}
-
+	static struct option long_options[] = {
+		{"data-only", no_argument, NULL, 'a'},
+		{"blobs", no_argument, NULL, 'b'},
+		{"clean", no_argument, NULL, 'c'},
+		{"create", no_argument, NULL, 'C'},
+		{"file", required_argument, NULL, 'f'},
+		{"format", required_argument, NULL, 'F'},
+		{"inserts", no_argument, NULL, 'd'},
+		{"attribute-inserts", no_argument, NULL, 'D'},
+		{"column-inserts", no_argument, NULL, 'D'},
+		{"host", required_argument, NULL, 'h'},
+		{"ignore-version", no_argument, NULL, 'i'},
+		{"no-reconnect", no_argument, NULL, 'R'},
+		{"no-quotes", no_argument, NULL, 'n'},
+		{"quotes", no_argument, NULL, 'N'},
+		{"oids", no_argument, NULL, 'o'},
+		{"no-owner", no_argument, NULL, 'O'},
+		{"port", required_argument, NULL, 'p'},
+		{"schema-only", no_argument, NULL, 's'},
+		{"superuser", required_argument, NULL, 'S'},
+		{"table", required_argument, NULL, 't'},
+		{"password", no_argument, NULL, 'W'},
+		{"username", required_argument, NULL, 'U'},
+		{"verbose", no_argument, NULL, 'v'},
+		{"no-privileges", no_argument, NULL, 'x'},
+		{"no-acl", no_argument, NULL, 'x'},
+		{"compress", required_argument, NULL, 'Z'},
+		{"help", no_argument, NULL, '?'},
+		{"version", no_argument, NULL, 'V'},
 
-#define COPYBUFSIZ		8192
+		/*
+		 * the following options don't have an equivalent short option
+		 * letter, but are available as '-X long-name'
+		 */
+		{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
+		{"disable-triggers", no_argument, &disable_triggers, 1},
 
-/*
- *	Dump a table's contents for loading using the COPY command
- *	- this routine is called by the Archiver when it wants the table
- *	  to be dumped.
- */
+		{NULL, 0, NULL, 0}
+	};
+	int			optindex;
+#endif
 
-static int
-dumpClasses_nodumpData(Archive *fout, char *oid, void *dctxv)
-{
-	const DumpContext *dctx = (DumpContext *) dctxv;
-	const char *classname = dctx->tblinfo[dctx->tblidx].relname;
-	const bool	hasoids = dctx->tblinfo[dctx->tblidx].hasoids;
-	const bool	oids = dctx->oids;
+#ifdef ENABLE_NLS
+	setlocale(LC_ALL, "");
+	bindtextdomain("pg_dump", LOCALEDIR);
+	textdomain("pg_dump");
+#endif
 
-	PGresult   *res;
-	char		query[255];
-	int			ret;
-	bool		copydone;
-	char		copybuf[COPYBUFSIZ];
+	g_verbose = false;
+	force_quotes = true;
 
-	if (g_verbose)
-		write_msg(NULL, "dumping out the contents of table %s\n", classname);
+	strcpy(g_comment_start, "-- ");
+	g_comment_end[0] = '\0';
+	strcpy(g_opaque_type, "opaque");
 
-	if (oids && hasoids)
-	{
-		/*
-		 * archprintf(fout, "COPY %s WITH OIDS FROM stdin;\n",
-		 * fmtId(classname, force_quotes));
-		 *
-		 * - Not used as of V1.3 (needs to be in ArchiveEntry call)
-		 *
-		 */
+	dataOnly = schemaOnly = dumpData = attrNames = false;
 
-		sprintf(query, "COPY %s WITH OIDS TO stdout;",
-				fmtId(classname, force_quotes));
-	}
+	if (!strrchr(argv[0], '/'))
+		progname = argv[0];
 	else
-	{
-		/*
-		 * archprintf(fout, "COPY %s FROM stdin;\n", fmtId(classname,
-		 * force_quotes));
-		 *
-		 * - Not used as of V1.3 (needs to be in ArchiveEntry call)
-		 *
-		 */
+		progname = strrchr(argv[0], '/') + 1;
 
-		sprintf(query, "COPY %s TO stdout;", fmtId(classname, force_quotes));
-	}
-	res = PQexec(g_conn, query);
-	if (!res ||
-		PQresultStatus(res) == PGRES_FATAL_ERROR)
+	/* Set default options based on progname */
+	if (strcmp(progname, "pg_backup") == 0)
 	{
-		write_msg(NULL, "SQL command to dump the contents of table \"%s\" failed\n",
-				  classname);
-		write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
-		write_msg(NULL, "The command was: %s\n", query);
-		exit_nicely();
+		format = "c";
+		outputBlobs = true;
 	}
-	else
+
+	if (argc > 1)
 	{
-		if (PQresultStatus(res) != PGRES_COPY_OUT)
-		{
-			write_msg(NULL, "SQL command to dump the contents of table \"%s\" executed abnormally.\n",
-					  classname);
-			write_msg(NULL, "The server returned status %d when %d was expected.\n",
-					  PQresultStatus(res), PGRES_COPY_OUT);
-			write_msg(NULL, "The command was: %s\n", query);
-			exit_nicely();
-		}
-		else
+		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
 		{
-			copydone = false;
-
-			while (!copydone)
-			{
-				ret = PQgetline(g_conn, copybuf, COPYBUFSIZ);
-
-				if (copybuf[0] == '\\' &&
-					copybuf[1] == '.' &&
-					copybuf[2] == '\0')
-				{
-					copydone = true;	/* don't print this... */
-				}
-				else
-				{
-					archputs(copybuf, fout);
-					switch (ret)
-					{
-						case EOF:
-							copydone = true;
-							/* FALLTHROUGH */
-						case 0:
-							archputc('\n', fout);
-							break;
-						case 1:
-							break;
-					}
-				}
-
-				/*
-				 * THROTTLE:
-				 *
-				 * There was considerable discussion in late July, 2000
-				 * regarding slowing down pg_dump when backing up large
-				 * tables. Users with both slow & fast (muti-processor)
-				 * machines experienced performance degradation when doing
-				 * a backup.
-				 *
-				 * Initial attempts based on sleeping for a number of ms for
-				 * each ms of work were deemed too complex, then a simple
-				 * 'sleep in each loop' implementation was suggested. The
-				 * latter failed because the loop was too tight. Finally,
-				 * the following was implemented:
-				 *
-				 * If throttle is non-zero, then See how long since the last
-				 * sleep. Work out how long to sleep (based on ratio). If
-				 * sleep is more than 100ms, then sleep reset timer EndIf
-				 * EndIf
-				 *
-				 * where the throttle value was the number of ms to sleep per
-				 * ms of work. The calculation was done in each loop.
-				 *
-				 * Most of the hard work is done in the backend, and this
-				 * solution still did not work particularly well: on slow
-				 * machines, the ratio was 50:1, and on medium paced
-				 * machines, 1:1, and on fast multi-processor machines, it
-				 * had little or no effect, for reasons that were unclear.
-				 *
-				 * Further discussion ensued, and the proposal was dropped.
-				 *
-				 * For those people who want this feature, it can be
-				 * implemented using gettimeofday in each loop,
-				 * calculating the time since last sleep, multiplying that
-				 * by the sleep ratio, then if the result is more than a
-				 * preset 'minimum sleep time' (say 100ms), call the
-				 * 'select' function to sleep for a subsecond period ie.
-				 *
-				 * select(0, NULL, NULL, NULL, &tvi);
-				 *
-				 * This will return after the interval specified in the
-				 * structure tvi. Fianally, call gettimeofday again to
-				 * save the 'last sleep time'.
-				 */
-			}
-			archprintf(fout, "\\.\n");
+			help(progname);
+			exit(0);
 		}
-		ret = PQendcopy(g_conn);
-		if (ret != 0)
+		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
 		{
-			write_msg(NULL, "SQL command to dump the contents of table \"%s\" failed: PQendcopy() failed.\n", classname);
-			write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
-			write_msg(NULL, "The command was: %s\n", query);
-			PQclear(res);
-			exit_nicely();
+			puts("pg_dump (PostgreSQL) " PG_VERSION);
+			exit(0);
 		}
 	}
 
-	return 1;
-}
+#ifdef HAVE_GETOPT_LONG
+	while ((c = getopt_long(argc, argv, "abcCdDf:F:h:inNoOp:RsS:t:uU:vWxX:zZ:V?", long_options, &optindex)) != -1)
+#else
+	while ((c = getopt(argc, argv, "abcCdDf:F:h:inNoOp:RsS:t:uU:vWxX:zZ:V?-")) != -1)
+#endif
 
-static int
-dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
-{
-	const DumpContext *dctx = (DumpContext *) dctxv;
-	const char *classname = dctx->tblinfo[dctx->tblidx].relname;
+	{
+		switch (c)
+		{
+			case 'a':			/* Dump data only */
+				dataOnly = true;
+				break;
 
-	PGresult   *res;
-	PQExpBuffer q = createPQExpBuffer();
-	int			tuple;
-	int			field;
+			case 'b':			/* Dump blobs */
+				outputBlobs = true;
+				break;
 
-	if (fout->remoteVersion >= 70100)
-		appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR SELECT * FROM ONLY %s", fmtId(classname, force_quotes));
-	else
-		appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR SELECT * FROM %s", fmtId(classname, force_quotes));
+			case 'c':			/* clean (i.e., drop) schema prior to
+								 * create */
+				outputClean = 1;
+				break;
 
-	res = PQexec(g_conn, q->data);
-	if (!res ||
-		PQresultStatus(res) != PGRES_COMMAND_OK)
-	{
-		write_msg(NULL, "dumpClasses(): SQL command failed\n");
-		write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
-		write_msg(NULL, "The command was: %s\n", q->data);
-		exit_nicely();
-	}
+			case 'C':			/* Create DB */
 
-	do
-	{
-		PQclear(res);
+				outputCreate = 1;
+				break;
 
-		res = PQexec(g_conn, "FETCH 100 FROM _pg_dump_cursor");
-		if (!res ||
-			PQresultStatus(res) != PGRES_TUPLES_OK)
-		{
-			write_msg(NULL, "dumpClasses(): SQL command failed\n");
-			write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
-			write_msg(NULL, "The command was: FETCH 100 FROM _pg_dump_cursor\n");
-			exit_nicely();
-		}
+			case 'd':			/* dump data as proper insert strings */
+				dumpData = true;
+				break;
 
-		for (tuple = 0; tuple < PQntuples(res); tuple++)
-		{
-			archprintf(fout, "INSERT INTO %s ", fmtId(classname, force_quotes));
-			if (attrNames == true)
-			{
-				resetPQExpBuffer(q);
-				appendPQExpBuffer(q, "(");
-				for (field = 0; field < PQnfields(res); field++)
-				{
-					if (field > 0)
-						appendPQExpBuffer(q, ",");
-					appendPQExpBuffer(q, fmtId(PQfname(res, field), force_quotes));
-				}
-				appendPQExpBuffer(q, ") ");
-				archprintf(fout, "%s", q->data);
-			}
-			archprintf(fout, "VALUES (");
-			for (field = 0; field < PQnfields(res); field++)
-			{
-				if (field > 0)
-					archprintf(fout, ",");
-				if (PQgetisnull(res, tuple, field))
-				{
-					archprintf(fout, "NULL");
-					continue;
-				}
-				switch (PQftype(res, field))
-				{
-					case INT2OID:
-					case INT4OID:
-					case OIDOID:		/* int types */
-					case FLOAT4OID:
-					case FLOAT8OID:		/* float types */
-						/* These types are printed without quotes */
-						archprintf(fout, "%s",
-								   PQgetvalue(res, tuple, field));
-						break;
-					case BITOID:
-					case VARBITOID:
-						archprintf(fout, "B'%s'",
-								   PQgetvalue(res, tuple, field));
-						break;
-					default:
+			case 'D':			/* dump data as proper insert strings with
+								 * attr names */
+				dumpData = true;
+				attrNames = true;
+				break;
 
-						/*
-						 * All other types are printed as string literals,
-						 * with appropriate escaping of special
-						 * characters.
-						 */
-						resetPQExpBuffer(q);
-						formatStringLiteral(q, PQgetvalue(res, tuple, field), CONV_ALL);
-						archprintf(fout, "%s", q->data);
-						break;
-				}
-			}
-			archprintf(fout, ");\n");
-		}
+			case 'f':
+				filename = optarg;
+				break;
 
-	} while (PQntuples(res) > 0);
-	PQclear(res);
+			case 'F':
+				format = optarg;
+				break;
 
-	res = PQexec(g_conn, "CLOSE _pg_dump_cursor");
-	if (!res ||
-		PQresultStatus(res) != PGRES_COMMAND_OK)
-	{
-		write_msg(NULL, "dumpClasses(): SQL command failed\n");
-		write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
-		write_msg(NULL, "The command was: CLOSE _pg_dump_cursor\n");
-		exit_nicely();
-	}
-	PQclear(res);
+			case 'h':			/* server host */
+				pghost = optarg;
+				break;
 
-	destroyPQExpBuffer(q);
-	return 1;
-}
+			case 'i':			/* ignore database version mismatch */
+				ignore_version = true;
+				break;
 
-/*
- * Convert a string value to an SQL string literal,
- * with appropriate escaping of special characters.
- * Quote mark ' goes to '' per SQL standard, other
- * stuff goes to \ sequences.
- * The literal is appended to the given PQExpBuffer.
- */
-static void
-formatStringLiteral(PQExpBuffer buf, const char *str, const formatLiteralOptions opts)
-{
-	appendPQExpBufferChar(buf, '\'');
-	while (*str)
-	{
-		char		ch = *str++;
+			case 'n':			/* Do not force double-quotes on
+								 * identifiers */
+				force_quotes = false;
+				break;
 
-		if (ch == '\\' || ch == '\'')
-		{
-			appendPQExpBufferChar(buf, ch);		/* double these */
-			appendPQExpBufferChar(buf, ch);
-		}
-		else if ((unsigned char) ch < (unsigned char) ' ' &&
-				 (opts == CONV_ALL
-				  || (ch != '\n' && ch != '\t')
-				  ))
-		{
-			/*
-			 * generate octal escape for control chars other than
-			 * whitespace
-			 */
-			appendPQExpBufferChar(buf, '\\');
-			appendPQExpBufferChar(buf, ((ch >> 6) & 3) + '0');
-			appendPQExpBufferChar(buf, ((ch >> 3) & 7) + '0');
-			appendPQExpBufferChar(buf, (ch & 7) + '0');
-		}
-		else
-			appendPQExpBufferChar(buf, ch);
-	}
-	appendPQExpBufferChar(buf, '\'');
-}
+			case 'N':			/* Force double-quotes on identifiers */
+				force_quotes = true;
+				break;
 
-/*
- * DumpClasses -
- *	  dump the contents of all the classes.
- */
-static void
-dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
-		 const char *onlytable, const bool oids, const bool force_quotes)
-{
-	int			i;
-	DataDumperPtr dumpFn;
-	DumpContext *dumpCtx;
-	char		copyBuf[512];
-	char	   *copyStmt;
+			case 'o':			/* Dump oids */
+				oids = true;
+				break;
 
-	if (g_verbose)
-	{
-		if (onlytable == NULL || (strlen(onlytable) == 0))
-			write_msg(NULL, "preparing to dump the contents of all %d tables/sequences\n", numTables);
-		else
-			write_msg(NULL, "preparing to dump the contents of only one table/sequence\n");
-	}
 
-	for (i = 0; i < numTables; i++)
-	{
-		const char *classname = tblinfo[i].relname;
+			case 'O':			/* Don't reconnect to match owner */
+				outputNoOwner = 1;
+				break;
 
-		/* Skip VIEW relations */
-		if (tblinfo[i].viewdef != NULL)
-			continue;
+			case 'p':			/* server port */
+				pgport = optarg;
+				break;
 
-		if (tblinfo[i].relkind == RELKIND_SEQUENCE)		/* already dumped */
-			continue;
+			case 'R':			/* No reconnect */
+				outputNoReconnect = 1;
+				break;
 
-		if (!onlytable || (strcmp(classname, onlytable) == 0) || (strlen(onlytable) == 0))
-		{
-			if (g_verbose)
-				write_msg(NULL, "preparing to dump the contents of table %s\n", classname);
+			case 's':			/* dump schema only */
+				schemaOnly = true;
+				break;
 
-#if 0
-			becomeUser(fout, tblinfo[i].usename);
-#endif
+			case 'S':			/* Username for superuser in plain text
+								 * output */
+				outputSuperuser = strdup(optarg);
+				break;
 
-			dumpCtx = (DumpContext *) malloc(sizeof(DumpContext));
-			dumpCtx->tblinfo = (TableInfo *) tblinfo;
-			dumpCtx->tblidx = i;
-			dumpCtx->oids = oids;
+			case 't':			/* Dump data for this table only */
+				{
+					int			i;
 
-			if (!dumpData)
-			{
-				/* Dump/restore using COPY */
-				dumpFn = dumpClasses_nodumpData;
-				sprintf(copyBuf, "COPY %s %sFROM stdin;\n",
-						fmtId(tblinfo[i].relname, force_quotes),
-						(oids && tblinfo[i].hasoids) ? "WITH OIDS " : "");
-				copyStmt = copyBuf;
-			}
-			else
-			{
-				/* Restore using INSERT */
-				dumpFn = dumpClasses_dumpData;
-				copyStmt = NULL;
-			}
+					selectTablename = strdup(optarg);
+
+					/*
+					 * quoted string? Then strip quotes and preserve
+					 * case...
+					 */
+					if (selectTablename[0] == '"')
+					{
+						char	*endptr;
+
+						endptr = selectTablename + strlen(selectTablename) - 1;
+						if (*endptr == '"')
+							*endptr = '\0';
+						strcpy(selectTablename, &selectTablename[1]);
+					}
+					else
+					{
+						/* otherwise, convert table name to lowercase... */
+						for (i = 0; selectTablename[i]; i++)
+							if (isupper((unsigned char) selectTablename[i]))
+								selectTablename[i] = tolower((unsigned char) selectTablename[i]);
+
+						/*
+						 * '*' is a special case meaning ALL tables, but
+						 * only if unquoted
+						 */
+						if (strcmp(selectTablename, "*") == 0)
+							selectTablename[0] = '\0';
+					}
+				}
+				break;
+
+			case 'u':
+				force_password = true;
+				username = simple_prompt("User name: ", 100, true);
+				break;
+
+			case 'U':
+				username = optarg;
+				break;
+
+			case 'v':			/* verbose */
+				g_verbose = true;
+				break;
+
+			case 'W':
+				force_password = true;
+				break;
+
+			case 'x':			/* skip ACL dump */
+				aclsSkip = true;
+				break;
+
+				/*
+				 * Option letters were getting scarce, so I invented this
+				 * new scheme: '-X feature' turns on some feature. Compare
+				 * to the -f option in GCC.  You should also add an
+				 * equivalent GNU-style option --feature.  Features that
+				 * require arguments should use '-X feature=foo'.
+				 */
+			case 'X':
+				if (strcmp(optarg, "use-set-session-authorization") == 0)
+					use_setsessauth = 1;
+				else if (strcmp(optarg, "disable-triggers") == 0)
+					disable_triggers = 1;
+				else
+				{
+					fprintf(stderr,
+							gettext("%s: invalid -X option -- %s\n"),
+							progname, optarg);
+					fprintf(stderr, gettext("Try '%s --help' for more information.\n"), progname);
+					exit(1);
+				}
+				break;
+			case 'Z':			/* Compression Level */
+				compressLevel = atoi(optarg);
+				break;
 
-			ArchiveEntry(fout, tblinfo[i].oid, tblinfo[i].relname,
-						 "TABLE DATA", NULL, "", "",
-						 copyStmt, tblinfo[i].usename,
-						 dumpFn, dumpCtx);
+#ifndef HAVE_GETOPT_LONG
+			case '-':
+				fprintf(stderr,
+						gettext("%s was compiled without support for long options.\n"
+						 "Use --help for help on invocation options.\n"),
+						progname);
+				exit(1);
+				break;
+#else
+				/* This covers the long options equivalent to -X xxx. */
+			case 0:
+				break;
+#endif
+			default:
+				fprintf(stderr, gettext("Try '%s --help' for more information.\n"), progname);
+				exit(1);
 		}
 	}
-}
 
+	if (optind < (argc - 1))
+	{
+		fprintf(stderr,
+			gettext("%s: too many command line options (first is '%s')\n"
+					"Try '%s --help' for more information.\n"),
+				progname, argv[optind + 1], progname);
+		exit(1);
+	}
 
+	/* Get the target database name */
+	if (optind < argc)
+		dbname = argv[optind];
+	else
+		dbname = getenv("PGDATABASE");
+	if (!dbname)
+	{
+		write_msg(NULL, "no database name specified\n");
+		exit(1);
+	}
 
-static int
-parse_version(const char *versionString)
-{
-	int			cnt;
-	int			vmaj,
-				vmin,
-				vrev;
+	if (dataOnly && schemaOnly)
+	{
+		write_msg(NULL, "The options \"schema only\" (-s) and \"data only\" (-a) cannot be used together.\n");
+		exit(1);
+	}
 
-	cnt = sscanf(versionString, "%d.%d.%d", &vmaj, &vmin, &vrev);
+	if (outputBlobs && selectTablename != NULL && strlen(selectTablename) > 0)
+	{
+		write_msg(NULL, "Large object output is not supported for a single table.\n");
+		write_msg(NULL, "Use all tables or a full dump instead.\n");
+		exit(1);
+	}
 
-	if (cnt < 2)
+	if (dumpData == true && oids == true)
 	{
-		write_msg(NULL, "unable to parse version string \"%s\"\n", versionString);
+		write_msg(NULL, "INSERT (-d, -D) and OID (-o) options cannot be used together.\n");
+		write_msg(NULL, "(The INSERT command cannot set oids.)\n");
 		exit(1);
 	}
 
-	if (cnt == 2)
-		vrev = 0;
+	if (outputBlobs == true && (format[0] == 'p' || format[0] == 'P'))
+	{
+		write_msg(NULL, "large object output is not supported for plain text dump files.\n");
+		write_msg(NULL, "(Use a different output format.)\n");
+		exit(1);
+	}
 
-	return (100 * vmaj + vmin) * 100 + vrev;
-}
+	/* open the output file */
+	switch (format[0])
+	{
 
+		case 'c':
+		case 'C':
+			g_fout = CreateArchive(filename, archCustom, compressLevel);
+			break;
 
+		case 'f':
+		case 'F':
+			g_fout = CreateArchive(filename, archFiles, compressLevel);
+			break;
 
-int
-main(int argc, char **argv)
-{
-	int			c;
-	const char *filename = NULL;
-	const char *format = "p";
-	const char *dbname = NULL;
-	const char *pghost = NULL;
-	const char *pgport = NULL;
-	const char *username = NULL;
-	char	   *tablename = NULL;
-	bool		oids = false;
-	TableInfo  *tblinfo;
-	int			numTables;
-	bool		force_password = false;
-	int			compressLevel = -1;
-	bool		ignore_version = false;
-	int			plainText = 0;
-	int			outputClean = 0;
-	int			outputCreate = 0;
-	int			outputBlobs = 0;
-	int			outputNoOwner = 0;
-	int			outputNoReconnect = 0;
-	static int	use_setsessauth = 0;
-	char	   *outputSuperuser = NULL;
+		case 'p':
+		case 'P':
+			plainText = 1;
+			g_fout = CreateArchive(filename, archNull, 0);
+			break;
 
-	RestoreOptions *ropt;
+		case 't':
+		case 'T':
+			g_fout = CreateArchive(filename, archTar, compressLevel);
+			break;
 
-#ifdef HAVE_GETOPT_LONG
-	static struct option long_options[] = {
-		{"data-only", no_argument, NULL, 'a'},
-		{"blobs", no_argument, NULL, 'b'},
-		{"clean", no_argument, NULL, 'c'},
-		{"create", no_argument, NULL, 'C'},
-		{"file", required_argument, NULL, 'f'},
-		{"format", required_argument, NULL, 'F'},
-		{"inserts", no_argument, NULL, 'd'},
-		{"attribute-inserts", no_argument, NULL, 'D'},
-		{"column-inserts", no_argument, NULL, 'D'},
-		{"host", required_argument, NULL, 'h'},
-		{"ignore-version", no_argument, NULL, 'i'},
-		{"no-reconnect", no_argument, NULL, 'R'},
-		{"no-quotes", no_argument, NULL, 'n'},
-		{"quotes", no_argument, NULL, 'N'},
-		{"oids", no_argument, NULL, 'o'},
-		{"no-owner", no_argument, NULL, 'O'},
-		{"port", required_argument, NULL, 'p'},
-		{"schema-only", no_argument, NULL, 's'},
-		{"superuser", required_argument, NULL, 'S'},
-		{"table", required_argument, NULL, 't'},
-		{"password", no_argument, NULL, 'W'},
-		{"username", required_argument, NULL, 'U'},
-		{"verbose", no_argument, NULL, 'v'},
-		{"no-privileges", no_argument, NULL, 'x'},
-		{"no-acl", no_argument, NULL, 'x'},
-		{"compress", required_argument, NULL, 'Z'},
-		{"help", no_argument, NULL, '?'},
-		{"version", no_argument, NULL, 'V'},
+		default:
+			write_msg(NULL, "invalid output format '%s' specified\n", format);
+			exit(1);
+	}
 
-		/*
-		 * the following options don't have an equivalent short option
-		 * letter, but are available as '-X long-name'
-		 */
-		{"use-set-session-authorization", no_argument, &use_setsessauth, 1}
-	};
-	int			optindex;
-#endif
+	if (g_fout == NULL)
+	{
+		write_msg(NULL, "could not open output file %s for writing\n", filename);
+		exit(1);
+	}
 
-#ifdef ENABLE_NLS
-	setlocale(LC_ALL, "");
-	bindtextdomain("pg_dump", LOCALEDIR);
-	textdomain("pg_dump");
-#endif
+	/* Let the archiver know how noisy to be */
+	g_fout->verbose = g_verbose;
 
-	g_verbose = false;
-	force_quotes = true;
+	/*
+	 * Open the database using the Archiver, so it knows about it. Errors
+	 * mean death.
+	 */
+	g_fout->minRemoteVersion = 70000;	/* we can handle back to 7.0 */
+	g_fout->maxRemoteVersion = parse_version(PG_VERSION);
+	g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport, username, force_password, ignore_version);
 
-	strcpy(g_comment_start, "-- ");
-	g_comment_end[0] = '\0';
-	strcpy(g_opaque_type, "opaque");
+	/*
+	 * Start serializable transaction to dump consistent data
+	 */
+	{
+		PGresult   *res;
 
-	dataOnly = schemaOnly = dumpData = attrNames = false;
+		res = PQexec(g_conn, "begin");
+		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
+			exit_horribly(g_fout, NULL, "BEGIN command failed: %s",
+						  PQerrorMessage(g_conn));
 
-	if (!strrchr(argv[0], '/'))
-		progname = argv[0];
-	else
-		progname = strrchr(argv[0], '/') + 1;
+		PQclear(res);
+		res = PQexec(g_conn, "set transaction isolation level serializable");
+		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
+			exit_horribly(g_fout, NULL, "could not set transaction isolation level to serializable: %s",
+						  PQerrorMessage(g_conn));
 
-	/* Set default options based on progname */
-	if (strcmp(progname, "pg_backup") == 0)
-	{
-		format = "c";
-		outputBlobs = true;
+		PQclear(res);
 	}
 
-	if (argc > 1)
+	if (g_fout->remoteVersion < 70300)
 	{
-		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
-		{
-			help(progname);
-			exit(0);
-		}
-		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
-		{
-			puts("pg_dump (PostgreSQL) " PG_VERSION);
-			exit(0);
-		}
+		if (g_fout->remoteVersion >= 70100)
+			g_last_builtin_oid = findLastBuiltinOid_V71(dbname);
+		else
+			g_last_builtin_oid = findLastBuiltinOid_V70();
+		if (g_verbose)
+			write_msg(NULL, "last built-in oid is %u\n", g_last_builtin_oid);
 	}
 
-#ifdef HAVE_GETOPT_LONG
-	while ((c = getopt_long(argc, argv, "abcCdDf:F:h:inNoOp:RsS:t:uU:vWxX:zZ:V?", long_options, &optindex)) != -1)
-#else
-	while ((c = getopt(argc, argv, "abcCdDf:F:h:inNoOp:RsS:t:uU:vWxX:zZ:V?-")) != -1)
-#endif
-
-	{
-		switch (c)
-		{
-			case 'a':			/* Dump data only */
-				dataOnly = true;
-				break;
-
-			case 'b':			/* Dump blobs */
-				outputBlobs = true;
-				break;
-
-			case 'c':			/* clean (i.e., drop) schema prior to
-								 * create */
-				outputClean = 1;
-				break;
+	/* Dump the database definition */
+	if (!dataOnly)
+		dumpDatabase(g_fout);
 
-			case 'C':			/* Create DB */
+	if (oids == true)
+		setMaxOid(g_fout);
 
-				outputCreate = 1;
-				break;
+	tblinfo = dumpSchema(g_fout, &numTables, aclsSkip, schemaOnly, dataOnly);
 
-			case 'd':			/* dump data as proper insert strings */
-				dumpData = true;
-				break;
+	if (!schemaOnly)
+		dumpClasses(tblinfo, numTables, g_fout, oids);
 
-			case 'D':			/* dump data as proper insert strings with
-								 * attr names */
-				dumpData = true;
-				attrNames = true;
-				break;
+	if (outputBlobs)
+		ArchiveEntry(g_fout, "0", "BLOBS", NULL, "",
+					 "BLOBS", NULL, "", "", NULL, dumpBlobs, NULL);
 
-			case 'f':
-				filename = optarg;
-				break;
+	if (!dataOnly)				/* dump indexes and triggers at the end
+								 * for performance */
+	{
+		dumpTriggers(g_fout, tblinfo, numTables);
+		dumpRules(g_fout, tblinfo, numTables);
+	}
 
-			case 'F':
-				format = optarg;
-				break;
+	/* Now sort the output nicely */
+	SortTocByOID(g_fout);
+	MoveToStart(g_fout, "SCHEMA");
+	MoveToStart(g_fout, "DATABASE");
+	MoveToEnd(g_fout, "TABLE DATA");
+	MoveToEnd(g_fout, "BLOBS");
+	MoveToEnd(g_fout, "INDEX");
+	MoveToEnd(g_fout, "CONSTRAINT");
+	MoveToEnd(g_fout, "TRIGGER");
+	MoveToEnd(g_fout, "RULE");
+	MoveToEnd(g_fout, "SEQUENCE SET");
 
-			case 'h':			/* server host */
-				pghost = optarg;
-				break;
+	/*
+	 * Moving all comments to end is annoying, but must do it for comments
+	 * on stuff we just moved, and we don't seem to have quite enough
+	 * dependency structure to get it really right...
+	 */
+	MoveToEnd(g_fout, "COMMENT");
 
-			case 'i':			/* ignore database version mismatch */
-				ignore_version = true;
-				break;
+	if (plainText)
+	{
+		ropt = NewRestoreOptions();
+		ropt->filename = (char *) filename;
+		ropt->dropSchema = outputClean;
+		ropt->aclsSkip = aclsSkip;
+		ropt->superuser = outputSuperuser;
+		ropt->create = outputCreate;
+		ropt->noOwner = outputNoOwner;
+		ropt->noReconnect = outputNoReconnect;
+		ropt->use_setsessauth = use_setsessauth;
+		ropt->disable_triggers = disable_triggers;
 
-			case 'n':			/* Do not force double-quotes on
-								 * identifiers */
-				force_quotes = false;
-				break;
+		if (compressLevel == -1)
+			ropt->compression = 0;
+		else
+			ropt->compression = compressLevel;
 
-			case 'N':			/* Force double-quotes on identifiers */
-				force_quotes = true;
-				break;
+		ropt->suppressDumpWarnings = true;		/* We've already shown
+												 * them */
 
-			case 'o':			/* Dump oids */
-				oids = true;
-				break;
+		RestoreArchive(g_fout, ropt);
+	}
 
+	CloseArchive(g_fout);
 
-			case 'O':			/* Don't reconnect to match owner */
-				outputNoOwner = 1;
-				break;
+	PQfinish(g_conn);
+	exit(0);
+}
 
-			case 'p':			/* server port */
-				pgport = optarg;
-				break;
 
-			case 'R':			/* No reconnect */
-				outputNoReconnect = 1;
-				break;
+static void
+help(const char *progname)
+{
+	printf(gettext("%s dumps a database as a text file or to other formats.\n\n"), progname);
+	puts(gettext("Usage:"));
+	printf(gettext("  %s [options] dbname\n\n"), progname);
+	puts(gettext("Options:"));
 
-			case 's':			/* dump schema only */
-				schemaOnly = true;
-				break;
+#ifdef HAVE_GETOPT_LONG
+	puts(gettext(
+		"  -a, --data-only          dump only the data, not the schema\n"
+		"  -b, --blobs              include large objects in dump\n"
+		"  -c, --clean              clean (drop) schema prior to create\n"
+		"  -C, --create             include commands to create database in dump\n"
+		"  -d, --inserts            dump data as INSERT, rather than COPY, commands\n"
+		"  -D, --column-inserts     dump data as INSERT commands with column names\n"
+		"  -f, --file=FILENAME      output file name\n"
+		"  -F, --format {c|t|p}     output file format (custom, tar, plain text)\n"
+		"  -h, --host=HOSTNAME      database server host name\n"
+		"  -i, --ignore-version     proceed even when server version mismatches\n"
+		"                           pg_dump version\n"
+		"  -n, --no-quotes          suppress most quotes around identifiers\n"
+		"  -N, --quotes             enable most quotes around identifiers\n"
+		"  -o, --oids               include oids in dump\n"
+		"  -O, --no-owner           do not output \\connect commands in plain\n"
+		"                           text format\n"
+		"  -p, --port=PORT          database server port number\n"
+		"  -R, --no-reconnect       disable ALL reconnections to the database in\n"
+		"                           plain text format\n"
+		"  -s, --schema-only        dump only the schema, no data\n"
+		"  -S, --superuser=NAME     specify the superuser user name to use in\n"
+		"                           plain text format\n"
+		"  -t, --table=TABLE        dump this table only (* for all)\n"
+		"  -U, --username=NAME      connect as specified database user\n"
+		"  -v, --verbose            verbose mode\n"
+		"  -W, --password           force password prompt (should happen automatically)\n"
+		"  -x, --no-privileges      do not dump privileges (grant/revoke)\n"
+		"  -X use-set-session-authorization, --use-set-session-authorization\n"
+		"                           output SET SESSION AUTHORIZATION commands rather\n"
+		"                           than \\connect commands\n"
+		"  -X disable-triggers, --disable-triggers\n"
+		"                           disable triggers during data-only restore\n"
+		"  -Z, --compress {0-9}     compression level for compressed formats\n"
+	));
+#else
+	puts(gettext(
+		"  -a                       dump only the data, not the schema\n"
+		"  -b                       include large objects in dump\n"
+		"  -c                       clean (drop) schema prior to create\n"
+		"  -C                       include commands to create database in dump\n"
+		"  -d                       dump data as INSERT, rather than COPY, commands\n"
+		"  -D                       dump data as INSERT commands with column names\n"
+		"  -f FILENAME              output file name\n"
+		"  -F {c|t|p}               output file format (custom, tar, plain text)\n"
+		"  -h HOSTNAME              database server host name\n"
+		"  -i                       proceed even when server version mismatches\n"
+		"                           pg_dump version\n"
+		"  -n                       suppress most quotes around identifiers\n"
+		"  -N                       enable most quotes around identifiers\n"
+		"  -o                       include oids in dump\n"
+		"  -O                       do not output \\connect commands in plain\n"
+		"                           text format\n"
+		"  -p PORT                  database server port number\n"
+		"  -R                       disable ALL reconnections to the database in\n"
+		"                           plain text format\n"
+		"  -s                       dump only the schema, no data\n"
+		"  -S NAME                  specify the superuser user name to use in\n"
+		"                           plain text format\n"
+		"  -t TABLE                 dump this table only (* for all)\n"
+		"  -U NAME                  connect as specified database user\n"
+		"  -v                       verbose mode\n"
+		"  -W                       force password prompt (should happen automatically)\n"
+		"  -x                       do not dump privileges (grant/revoke)\n"
+		"  -X use-set-session-authorization\n"
+		"                           output SET SESSION AUTHORIZATION commands rather\n"
+		"                           than \\connect commands\n"
+		"  -X disable-triggers      disable triggers during data-only restore\n"
+		"  -Z {0-9}                 compression level for compressed formats\n"
+	));
+#endif
+	puts(gettext("If no database name is not supplied, then the PGDATABASE environment\n"
+				 "variable value is used.\n\n"
+				 "Report bugs to <pgsql-bugs@postgresql.org>."));
+}
 
-			case 'S':			/* Username for superuser in plain text
-								 * output */
-				outputSuperuser = strdup(optarg);
-				break;
+static int
+parse_version(const char *versionString)
+{
+	int			cnt;
+	int			vmaj,
+				vmin,
+				vrev;
 
-			case 't':			/* Dump data for this table only */
-				{
-					int			i;
+	cnt = sscanf(versionString, "%d.%d.%d", &vmaj, &vmin, &vrev);
 
-					tablename = strdup(optarg);
+	if (cnt < 2)
+	{
+		write_msg(NULL, "unable to parse version string \"%s\"\n", versionString);
+		exit(1);
+	}
 
-					/*
-					 * quoted string? Then strip quotes and preserve
-					 * case...
-					 */
-					if (tablename[0] == '"')
-					{
-						strcpy(tablename, &tablename[1]);
-						if (*(tablename + strlen(tablename) - 1) == '"')
-							*(tablename + strlen(tablename) - 1) = '\0';
-					}
-					/* otherwise, convert table name to lowercase... */
-					else
-					{
-						for (i = 0; tablename[i]; i++)
-							if (isupper((unsigned char) tablename[i]))
-								tablename[i] = tolower((unsigned char) tablename[i]);
+	if (cnt == 2)
+		vrev = 0;
 
-						/*
-						 * '*' is a special case meaning ALL tables, but
-						 * only if unquoted
-						 */
-						if (strcmp(tablename, "*") == 0)
-							tablename[0] = '\0';
+	return (100 * vmaj + vmin) * 100 + vrev;
+}
 
-					}
-				}
-				break;
+void
+exit_nicely(void)
+{
+	PQfinish(g_conn);
+	if (g_verbose)
+		write_msg(NULL, "*** aborted because of error\n");
+	exit(1);
+}
 
-			case 'u':
-				force_password = true;
-				username = simple_prompt("User name: ", 100, true);
-				break;
+/*
+ * selectDumpableNamespace: policy-setting subroutine
+ *		Mark a namespace as to be dumped or not
+ */
+static void
+selectDumpableNamespace(NamespaceInfo *nsinfo)
+{
+	/*
+	 * If a specific table is being dumped, do not dump any complete
+	 * namespaces.  Otherwise, dump all non-system namespaces.
+	 */
+	if (selectTablename != NULL)
+		nsinfo->dump = false;
+	else if (strncmp(nsinfo->nspname, "pg_", 3) == 0)
+		nsinfo->dump = false;
+	else
+		nsinfo->dump = true;
+}
 
-			case 'U':
-				username = optarg;
-				break;
+/*
+ * selectDumpableTable: policy-setting subroutine
+ *		Mark a table as to be dumped or not
+ */
+static void
+selectDumpableTable(TableInfo *tbinfo)
+{
+	/*
+	 * Always dump if dumping parent namespace; else, if a particular
+	 * tablename has been specified, dump matching table name; else,
+	 * do not dump.
+	 */
+	if (tbinfo->relnamespace->dump)
+		tbinfo->dump = true;
+	else if (selectTablename != NULL)
+		tbinfo->dump = (strcmp(tbinfo->relname, selectTablename) == 0);
+	else
+		tbinfo->dump = false;
+}
 
-			case 'v':			/* verbose */
-				g_verbose = true;
-				break;
+/*
+ *	Dump a table's contents for loading using the COPY command
+ *	- this routine is called by the Archiver when it wants the table
+ *	  to be dumped.
+ */
 
-			case 'W':
-				force_password = true;
-				break;
+#define COPYBUFSIZ		8192
 
-			case 'x':			/* skip ACL dump */
-				aclsSkip = true;
-				break;
+static int
+dumpClasses_nodumpData(Archive *fout, char *oid, void *dctxv)
+{
+	const DumpContext *dctx = (DumpContext *) dctxv;
+	TableInfo  *tbinfo = &dctx->tblinfo[dctx->tblidx];
+	const char *classname = tbinfo->relname;
+	const bool	hasoids = tbinfo->hasoids;
+	const bool	oids = dctx->oids;
+	PQExpBuffer q = createPQExpBuffer();
+	PGresult   *res;
+	int			ret;
+	bool		copydone;
+	char		copybuf[COPYBUFSIZ];
 
-				/*
-				 * Option letters were getting scarce, so I invented this
-				 * new scheme: '-X feature' turns on some feature. Compare
-				 * to the -f option in GCC.  You should also add an
-				 * equivalent GNU-style option --feature.  Features that
-				 * require arguments should use '-X feature=foo'.
-				 */
-			case 'X':
-				if (strcmp(optarg, "use-set-session-authorization") == 0)
-					use_setsessauth = 1;
-				else
-				{
-					fprintf(stderr,
-							gettext("%s: invalid -X option -- %s\n"),
-							progname, optarg);
-					fprintf(stderr, gettext("Try '%s --help' for more information.\n"), progname);
-					exit(1);
-				}
-				break;
-			case 'Z':			/* Compression Level */
-				compressLevel = atoi(optarg);
-				break;
+	if (g_verbose)
+		write_msg(NULL, "dumping out the contents of table %s\n", classname);
 
-#ifndef HAVE_GETOPT_LONG
-			case '-':
-				fprintf(stderr,
-						gettext("%s was compiled without support for long options.\n"
-						 "Use --help for help on invocation options.\n"),
-						progname);
-				exit(1);
-				break;
-#else
-				/* This covers the long options equivalent to -X xxx. */
-			case 0:
-				break;
-#endif
-			default:
-				fprintf(stderr, gettext("Try '%s --help' for more information.\n"), progname);
-				exit(1);
-		}
-	}
+	/*
+	 * Make sure we are in proper schema.  We will qualify the table name
+	 * below anyway (in case its name conflicts with a pg_catalog table);
+	 * but this ensures reproducible results in case the table contains
+	 * regproc, regclass, etc columns.
+	 */
+	selectSourceSchema(tbinfo->relnamespace->nspname);
 
-	if (optind < (argc - 1))
+	if (oids && hasoids)
 	{
-		fprintf(stderr,
-			gettext("%s: too many command line options (first is '%s')\n"
-					"Try '%s --help' for more information.\n"),
-				progname, argv[optind + 1], progname);
-		exit(1);
+		appendPQExpBuffer(q, "COPY %s WITH OIDS TO stdout;",
+						  fmtQualifiedId(tbinfo->relnamespace->nspname,
+										 classname));
 	}
-
-	/* Get the target database name */
-	if (optind < argc)
-		dbname = argv[optind];
 	else
-		dbname = getenv("PGDATABASE");
-	if (!dbname)
-	{
-		write_msg(NULL, "no database name specified\n");
-		exit(1);
-	}
-
-	if (dataOnly && schemaOnly)
 	{
-		write_msg(NULL, "The options \"schema only\" (-s) and \"data only\" (-a) cannot be used together.\n");
-		exit(1);
+		appendPQExpBuffer(q, "COPY %s TO stdout;",
+						  fmtQualifiedId(tbinfo->relnamespace->nspname,
+										 classname));
 	}
-
-	if (outputBlobs && tablename != NULL && strlen(tablename) > 0)
+	res = PQexec(g_conn, q->data);
+	if (!res ||
+		PQresultStatus(res) == PGRES_FATAL_ERROR)
 	{
-		write_msg(NULL, "Large object output is not supported for a single table.\n");
-		write_msg(NULL, "Use all tables or a full dump instead.\n");
-		exit(1);
+		write_msg(NULL, "SQL command to dump the contents of table \"%s\" failed\n",
+				  classname);
+		write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
+		write_msg(NULL, "The command was: %s\n", q->data);
+		exit_nicely();
 	}
-
-	if (dumpData == true && oids == true)
+	if (PQresultStatus(res) != PGRES_COPY_OUT)
 	{
-		write_msg(NULL, "INSERT (-d, -D) and OID (-o) options cannot be used together.\n");
-		write_msg(NULL, "(The INSERT command cannot set oids.)\n");
-		exit(1);
+		write_msg(NULL, "SQL command to dump the contents of table \"%s\" executed abnormally.\n",
+				  classname);
+		write_msg(NULL, "The server returned status %d when %d was expected.\n",
+				  PQresultStatus(res), PGRES_COPY_OUT);
+		write_msg(NULL, "The command was: %s\n", q->data);
+		exit_nicely();
 	}
 
-	if (outputBlobs == true && (format[0] == 'p' || format[0] == 'P'))
-	{
-		write_msg(NULL, "large object output is not supported for plain text dump files.\n");
-		write_msg(NULL, "(Use a different output format.)\n");
-		exit(1);
-	}
+	copydone = false;
 
-	/* open the output file */
-	switch (format[0])
+	while (!copydone)
 	{
+		ret = PQgetline(g_conn, copybuf, COPYBUFSIZ);
 
-		case 'c':
-		case 'C':
-			g_fout = CreateArchive(filename, archCustom, compressLevel);
-			break;
-
-		case 'f':
-		case 'F':
-			g_fout = CreateArchive(filename, archFiles, compressLevel);
-			break;
-
-		case 'p':
-		case 'P':
-			plainText = 1;
-			g_fout = CreateArchive(filename, archNull, 0);
-			break;
-
-		case 't':
-		case 'T':
-			g_fout = CreateArchive(filename, archTar, compressLevel);
-			break;
+		if (copybuf[0] == '\\' &&
+			copybuf[1] == '.' &&
+			copybuf[2] == '\0')
+		{
+			copydone = true;	/* don't print this... */
+		}
+		else
+		{
+			archputs(copybuf, fout);
+			switch (ret)
+			{
+				case EOF:
+					copydone = true;
+					/* FALLTHROUGH */
+				case 0:
+					archputc('\n', fout);
+					break;
+				case 1:
+					break;
+			}
+		}
 
-		default:
-			write_msg(NULL, "invalid output format '%s' specified\n", format);
-			exit(1);
+		/*
+		 * THROTTLE:
+		 *
+		 * There was considerable discussion in late July, 2000
+		 * regarding slowing down pg_dump when backing up large
+		 * tables. Users with both slow & fast (muti-processor)
+		 * machines experienced performance degradation when doing
+		 * a backup.
+		 *
+		 * Initial attempts based on sleeping for a number of ms for
+		 * each ms of work were deemed too complex, then a simple
+		 * 'sleep in each loop' implementation was suggested. The
+		 * latter failed because the loop was too tight. Finally,
+		 * the following was implemented:
+		 *
+		 * If throttle is non-zero, then See how long since the last
+		 * sleep. Work out how long to sleep (based on ratio). If
+		 * sleep is more than 100ms, then sleep reset timer EndIf
+		 * EndIf
+		 *
+		 * where the throttle value was the number of ms to sleep per
+		 * ms of work. The calculation was done in each loop.
+		 *
+		 * Most of the hard work is done in the backend, and this
+		 * solution still did not work particularly well: on slow
+		 * machines, the ratio was 50:1, and on medium paced
+		 * machines, 1:1, and on fast multi-processor machines, it
+		 * had little or no effect, for reasons that were unclear.
+		 *
+		 * Further discussion ensued, and the proposal was dropped.
+		 *
+		 * For those people who want this feature, it can be
+		 * implemented using gettimeofday in each loop,
+		 * calculating the time since last sleep, multiplying that
+		 * by the sleep ratio, then if the result is more than a
+		 * preset 'minimum sleep time' (say 100ms), call the
+		 * 'select' function to sleep for a subsecond period ie.
+		 *
+		 * select(0, NULL, NULL, NULL, &tvi);
+		 *
+		 * This will return after the interval specified in the
+		 * structure tvi. Fianally, call gettimeofday again to
+		 * save the 'last sleep time'.
+		 */
 	}
+	archprintf(fout, "\\.\n");
 
-	if (g_fout == NULL)
+	ret = PQendcopy(g_conn);
+	if (ret != 0)
 	{
-		write_msg(NULL, "could not open output file %s for writing\n", filename);
-		exit(1);
+		write_msg(NULL, "SQL command to dump the contents of table \"%s\" failed: PQendcopy() failed.\n", classname);
+		write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
+		write_msg(NULL, "The command was: %s\n", q->data);
+		PQclear(res);
+		exit_nicely();
 	}
 
-	/* Let the archiver know how noisy to be */
-	g_fout->verbose = g_verbose;
+	destroyPQExpBuffer(q);
+	return 1;
+}
 
-	/*
-	 * Open the database using the Archiver, so it knows about it. Errors
-	 * mean death.
-	 */
-	g_fout->minRemoteVersion = 70000;	/* we can handle back to 7.0 */
-	g_fout->maxRemoteVersion = parse_version(PG_VERSION);
-	g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport, username, force_password, ignore_version);
+static int
+dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
+{
+	const DumpContext *dctx = (DumpContext *) dctxv;
+	TableInfo  *tbinfo = &dctx->tblinfo[dctx->tblidx];
+	const char *classname = tbinfo->relname;
+	PQExpBuffer q = createPQExpBuffer();
+	PGresult   *res;
+	int			tuple;
+	int			field;
 
 	/*
-	 * Start serializable transaction to dump consistent data
+	 * Make sure we are in proper schema.  We will qualify the table name
+	 * below anyway (in case its name conflicts with a pg_catalog table);
+	 * but this ensures reproducible results in case the table contains
+	 * regproc, regclass, etc columns.
 	 */
-	{
-		PGresult   *res;
-
-		res = PQexec(g_conn, "begin");
-		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
-			exit_horribly(g_fout, NULL, "BEGIN command failed: %s",
-						  PQerrorMessage(g_conn));
-
-		PQclear(res);
-		res = PQexec(g_conn, "set transaction isolation level serializable");
-		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
-			exit_horribly(g_fout, NULL, "could not set transaction isolation level to serializable: %s",
-						  PQerrorMessage(g_conn));
+	selectSourceSchema(tbinfo->relnamespace->nspname);
 
-		PQclear(res);
+	if (fout->remoteVersion >= 70100)
+	{
+		appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
+						  "SELECT * FROM ONLY %s",
+						  fmtQualifiedId(tbinfo->relnamespace->nspname,
+										 classname));
 	}
-
-	if (g_fout->remoteVersion >= 70100)
-		g_last_builtin_oid = findLastBuiltinOid_V71(dbname);
 	else
-		g_last_builtin_oid = findLastBuiltinOid_V70();
+	{
+		appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
+						  "SELECT * FROM %s",
+						  fmtQualifiedId(tbinfo->relnamespace->nspname,
+										 classname));
+	}
 
-	/* Dump the database definition */
-	if (!dataOnly)
-		dumpDatabase(g_fout);
+	res = PQexec(g_conn, q->data);
+	if (!res ||
+		PQresultStatus(res) != PGRES_COMMAND_OK)
+	{
+		write_msg(NULL, "dumpClasses(): SQL command failed\n");
+		write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
+		write_msg(NULL, "The command was: %s\n", q->data);
+		exit_nicely();
+	}
 
-	if (oids == true)
-		setMaxOid(g_fout);
+	do
+	{
+		PQclear(res);
 
-	if (g_verbose)
-		write_msg(NULL, "last built-in oid is %u\n", g_last_builtin_oid);
-	tblinfo = dumpSchema(g_fout, &numTables, tablename, aclsSkip, oids, schemaOnly, dataOnly);
+		res = PQexec(g_conn, "FETCH 100 FROM _pg_dump_cursor");
+		if (!res ||
+			PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			write_msg(NULL, "dumpClasses(): SQL command failed\n");
+			write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
+			write_msg(NULL, "The command was: FETCH 100 FROM _pg_dump_cursor\n");
+			exit_nicely();
+		}
+
+		for (tuple = 0; tuple < PQntuples(res); tuple++)
+		{
+			archprintf(fout, "INSERT INTO %s ", fmtId(classname, force_quotes));
+			if (attrNames == true)
+			{
+				resetPQExpBuffer(q);
+				appendPQExpBuffer(q, "(");
+				for (field = 0; field < PQnfields(res); field++)
+				{
+					if (field > 0)
+						appendPQExpBuffer(q, ",");
+					appendPQExpBuffer(q, fmtId(PQfname(res, field), force_quotes));
+				}
+				appendPQExpBuffer(q, ") ");
+				archprintf(fout, "%s", q->data);
+			}
+			archprintf(fout, "VALUES (");
+			for (field = 0; field < PQnfields(res); field++)
+			{
+				if (field > 0)
+					archprintf(fout, ",");
+				if (PQgetisnull(res, tuple, field))
+				{
+					archprintf(fout, "NULL");
+					continue;
+				}
+				switch (PQftype(res, field))
+				{
+					case INT2OID:
+					case INT4OID:
+					case OIDOID:		/* int types */
+					case FLOAT4OID:
+					case FLOAT8OID:		/* float types */
+						/* These types are printed without quotes */
+						archprintf(fout, "%s",
+								   PQgetvalue(res, tuple, field));
+						break;
+					case BITOID:
+					case VARBITOID:
+						archprintf(fout, "B'%s'",
+								   PQgetvalue(res, tuple, field));
+						break;
+					default:
 
-	if (!schemaOnly)
-		dumpClasses(tblinfo, numTables, g_fout, tablename, oids, force_quotes);
+						/*
+						 * All other types are printed as string literals,
+						 * with appropriate escaping of special
+						 * characters.
+						 */
+						resetPQExpBuffer(q);
+						formatStringLiteral(q, PQgetvalue(res, tuple, field), CONV_ALL);
+						archprintf(fout, "%s", q->data);
+						break;
+				}
+			}
+			archprintf(fout, ");\n");
+		}
 
-	if (outputBlobs)
-		ArchiveEntry(g_fout, "0", "BLOBS", "BLOBS", NULL, "", "", "", "", dumpBlobs, 0);
+	} while (PQntuples(res) > 0);
+	PQclear(res);
 
-	if (!dataOnly)				/* dump indexes and triggers at the end
-								 * for performance */
+	res = PQexec(g_conn, "CLOSE _pg_dump_cursor");
+	if (!res ||
+		PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
-		dumpTriggers(g_fout, tablename, tblinfo, numTables);
-		dumpRules(g_fout, tablename, tblinfo, numTables);
+		write_msg(NULL, "dumpClasses(): SQL command failed\n");
+		write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
+		write_msg(NULL, "The command was: CLOSE _pg_dump_cursor\n");
+		exit_nicely();
 	}
+	PQclear(res);
 
-	/* Now sort the output nicely */
-	SortTocByOID(g_fout);
-	MoveToStart(g_fout, "DATABASE");
-	MoveToEnd(g_fout, "TABLE DATA");
-	MoveToEnd(g_fout, "BLOBS");
-	MoveToEnd(g_fout, "INDEX");
-	MoveToEnd(g_fout, "CONSTRAINT");
-	MoveToEnd(g_fout, "TRIGGER");
-	MoveToEnd(g_fout, "RULE");
-	MoveToEnd(g_fout, "SEQUENCE SET");
-
-	/*
-	 * Moving all comments to end is annoying, but must do it for comments
-	 * on stuff we just moved, and we don't seem to have quite enough
-	 * dependency structure to get it really right...
-	 */
-	MoveToEnd(g_fout, "COMMENT");
+	destroyPQExpBuffer(q);
+	return 1;
+}
 
-	if (plainText)
+/*
+ * Convert a string value to an SQL string literal,
+ * with appropriate escaping of special characters.
+ * Quote mark ' goes to '' per SQL standard, other
+ * stuff goes to \ sequences.
+ * The literal is appended to the given PQExpBuffer.
+ */
+static void
+formatStringLiteral(PQExpBuffer buf, const char *str, const formatLiteralOptions opts)
+{
+	appendPQExpBufferChar(buf, '\'');
+	while (*str)
 	{
-		ropt = NewRestoreOptions();
-		ropt->filename = (char *) filename;
-		ropt->dropSchema = outputClean;
-		ropt->aclsSkip = aclsSkip;
-		ropt->superuser = outputSuperuser;
-		ropt->create = outputCreate;
-		ropt->noOwner = outputNoOwner;
-		ropt->noReconnect = outputNoReconnect;
-		ropt->use_setsessauth = use_setsessauth;
+		char		ch = *str++;
 
-		if (outputSuperuser)
-			ropt->superuser = outputSuperuser;
+		if (ch == '\\' || ch == '\'')
+		{
+			appendPQExpBufferChar(buf, ch);		/* double these */
+			appendPQExpBufferChar(buf, ch);
+		}
+		else if ((unsigned char) ch < (unsigned char) ' ' &&
+				 (opts == CONV_ALL
+				  || (ch != '\n' && ch != '\t')
+				  ))
+		{
+			/*
+			 * generate octal escape for control chars other than
+			 * whitespace
+			 */
+			appendPQExpBufferChar(buf, '\\');
+			appendPQExpBufferChar(buf, ((ch >> 6) & 3) + '0');
+			appendPQExpBufferChar(buf, ((ch >> 3) & 7) + '0');
+			appendPQExpBufferChar(buf, (ch & 7) + '0');
+		}
 		else
-			ropt->superuser = PQuser(g_conn);
+			appendPQExpBufferChar(buf, ch);
+	}
+	appendPQExpBufferChar(buf, '\'');
+}
 
-		if (compressLevel == -1)
-			ropt->compression = 0;
-		else
-			ropt->compression = compressLevel;
+/*
+ * DumpClasses -
+ *	  dump the contents of all the classes.
+ */
+static void
+dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
+			const bool oids)
+{
+	int			i;
+	DataDumperPtr dumpFn;
+	DumpContext *dumpCtx;
+	char		copyBuf[512];
+	char	   *copyStmt;
 
-		ropt->suppressDumpWarnings = true;		/* We've already shown
-												 * them */
+	for (i = 0; i < numTables; i++)
+	{
+		const char *classname = tblinfo[i].relname;
 
-		RestoreArchive(g_fout, ropt);
-	}
+		/* Skip VIEW relations */
+		if (tblinfo[i].relkind == RELKIND_VIEW)
+			continue;
 
-	CloseArchive(g_fout);
+		if (tblinfo[i].relkind == RELKIND_SEQUENCE)		/* already dumped */
+			continue;
 
-	clearTableInfo(tblinfo, numTables);
-	PQfinish(g_conn);
-	exit(0);
+		if (tblinfo[i].dump)
+		{
+			if (g_verbose)
+				write_msg(NULL, "preparing to dump the contents of table %s\n",
+						  classname);
+
+			dumpCtx = (DumpContext *) malloc(sizeof(DumpContext));
+			dumpCtx->tblinfo = (TableInfo *) tblinfo;
+			dumpCtx->tblidx = i;
+			dumpCtx->oids = oids;
+
+			if (!dumpData)
+			{
+				/* Dump/restore using COPY */
+				dumpFn = dumpClasses_nodumpData;
+				sprintf(copyBuf, "COPY %s %sFROM stdin;\n",
+						fmtId(tblinfo[i].relname, force_quotes),
+						(oids && tblinfo[i].hasoids) ? "WITH OIDS " : "");
+				copyStmt = copyBuf;
+			}
+			else
+			{
+				/* Restore using INSERT */
+				dumpFn = dumpClasses_dumpData;
+				copyStmt = NULL;
+			}
+
+			ArchiveEntry(fout, tblinfo[i].oid, tblinfo[i].relname,
+						 tblinfo[i].relnamespace->nspname, tblinfo[i].usename,
+						 "TABLE DATA", NULL, "", "", copyStmt,
+						 dumpFn, dumpCtx);
+		}
+	}
 }
 
+
 /*
  * dumpDatabase:
  *	dump the database definition
- *
  */
 static int
 dumpDatabase(Archive *AH)
@@ -1157,6 +1227,9 @@ dumpDatabase(Archive *AH)
 	if (g_verbose)
 		write_msg(NULL, "saving database definition\n");
 
+	/* Make sure we are in proper schema */
+	selectSourceSchema("pg_catalog");
+
 	/* Get the database owner and parameters from pg_database */
 	appendPQExpBuffer(dbQry, "select (select usename from pg_user where usesysid = datdba) as dba,"
 					  " encoding, datpath from pg_database"
@@ -1207,10 +1280,17 @@ dumpDatabase(Archive *AH)
 	appendPQExpBuffer(delQry, "DROP DATABASE %s;\n",
 					  fmtId(datname, force_quotes));
 
-	ArchiveEntry(AH, "0" /* OID */ , datname /* Name */ , "DATABASE", NULL,
-				 creaQry->data /* Create */ , delQry->data /* Del */ ,
-				 "" /* Copy */ , dba /* Owner */ ,
-				 NULL /* Dumper */ , NULL /* Dumper Arg */ );
+	ArchiveEntry(AH, "0",		/* OID */
+				 datname,		/* Name */
+				 NULL,			/* Namespace */
+				 dba,			/* Owner */
+				 "DATABASE",	/* Desc */
+				 NULL,			/* Deps */
+				 creaQry->data,	/* Create */
+				 delQry->data,	/* Del */
+				 NULL,			/* Copy */
+				 NULL,			/* Dumper */
+				 NULL);			/* Dumper Arg */
 
 	PQclear(res);
 
@@ -1246,6 +1326,9 @@ dumpBlobs(Archive *AH, char *junkOid, void *junkVal)
 	if (g_verbose)
 		write_msg(NULL, "saving large objects\n");
 
+	/* Make sure we are in proper schema */
+	selectSourceSchema("pg_catalog");
+
 	/* Cursor to get all BLOB tables */
 	if (AH->remoteVersion >= 70100)
 		appendPQExpBuffer(oidQry, "Declare blobOid Cursor for SELECT DISTINCT loid FROM pg_largeobject");
@@ -1290,1487 +1373,779 @@ dumpBlobs(Archive *AH, char *junkOid, void *junkVal)
 
 			StartBlob(AH, blobOid);
 
-			/* Now read it in chunks, sending data to archive */
-			do
-			{
-				cnt = lo_read(g_conn, loFd, buf, loBufSize);
-				if (cnt < 0)
-				{
-					write_msg(NULL, "dumpBlobs(): error reading large object: %s",
-							  PQerrorMessage(g_conn));
-					exit_nicely();
-				}
-
-				WriteData(AH, buf, cnt);
-
-			} while (cnt > 0);
-
-			lo_close(g_conn, loFd);
-
-			EndBlob(AH, blobOid);
-
-		}
-	} while (PQntuples(res) > 0);
-
-	destroyPQExpBuffer(oidQry);
-	destroyPQExpBuffer(oidFetchQry);
-
-	return 1;
-}
-
-/*
- * getTypes:
- *	  read all base types in the system catalogs and return them in the
- * TypeInfo* structure
- *
- *	numTypes is set to the number of types read in
- *
- */
-TypeInfo *
-getTypes(int *numTypes)
-{
-	PGresult   *res;
-	int			ntups;
-	int			i;
-	PQExpBuffer query = createPQExpBuffer();
-	TypeInfo   *tinfo;
-
-	int			i_oid;
-	int			i_typowner;
-	int			i_typname;
-	int			i_typlen;
-	int			i_typprtlen;
-	int			i_typinput;
-	int			i_typoutput;
-	int			i_typreceive;
-	int			i_typsend;
-	int			i_typelem;
-	int			i_typdelim;
-	int			i_typdefault;
-	int			i_typrelid;
-	int			i_typalign;
-	int			i_typstorage;
-	int			i_typbyval;
-	int			i_typisdefined;
-	int			i_usename;
-	int			i_typedefn;
-	int			i_typtype;
-
-	/* find all base types */
-
-	/*
-	 * we include even the built-in types because those may be used as
-	 * array elements by user-defined types
-	 *
-	 * we filter out the built-in types when we dump out the types
-	 */
-
-	if (g_fout->remoteVersion < 70100)
-	{
-		appendPQExpBuffer(query, "SELECT pg_type.oid, typowner, typname, typlen, typprtlen, "
-		  "typinput, typoutput, typreceive, typsend, typelem, typdelim, "
-						  "typdefault, typrelid, typalign, 'p'::char as typstorage, typbyval, typisdefined, "
-						  "(select usename from pg_user where typowner = usesysid) as usename, "
-						  "typname as typedefn, typtype "
-						  "from pg_type");
-	}
-	else
-	{
-		appendPQExpBuffer(query, "SELECT pg_type.oid, typowner, typname, typlen, typprtlen, "
-		  "typinput, typoutput, typreceive, typsend, typelem, typdelim, "
-						  "typdefault, typrelid, typalign, typstorage, typbyval, typisdefined, "
-						  "(select usename from pg_user where typowner = usesysid) as usename, "
-						  "format_type(pg_type.oid, NULL) as typedefn, typtype "
-						  "from pg_type");
-	}
-
-	res = PQexec(g_conn, query->data);
-	if (!res ||
-		PQresultStatus(res) != PGRES_TUPLES_OK)
-	{
-		write_msg(NULL, "query to obtain list of data types failed: %s", PQerrorMessage(g_conn));
-		exit_nicely();
-	}
-
-	ntups = PQntuples(res);
-
-	tinfo = (TypeInfo *) malloc(ntups * sizeof(TypeInfo));
-
-	i_oid = PQfnumber(res, "oid");
-	i_typowner = PQfnumber(res, "typowner");
-	i_typname = PQfnumber(res, "typname");
-	i_typlen = PQfnumber(res, "typlen");
-	i_typprtlen = PQfnumber(res, "typprtlen");
-	i_typinput = PQfnumber(res, "typinput");
-	i_typoutput = PQfnumber(res, "typoutput");
-	i_typreceive = PQfnumber(res, "typreceive");
-	i_typsend = PQfnumber(res, "typsend");
-	i_typelem = PQfnumber(res, "typelem");
-	i_typdelim = PQfnumber(res, "typdelim");
-	i_typdefault = PQfnumber(res, "typdefault");
-	i_typrelid = PQfnumber(res, "typrelid");
-	i_typalign = PQfnumber(res, "typalign");
-	i_typstorage = PQfnumber(res, "typstorage");
-	i_typbyval = PQfnumber(res, "typbyval");
-	i_typisdefined = PQfnumber(res, "typisdefined");
-	i_usename = PQfnumber(res, "usename");
-	i_typedefn = PQfnumber(res, "typedefn");
-	i_typtype = PQfnumber(res, "typtype");
-
-	for (i = 0; i < ntups; i++)
-	{
-		tinfo[i].oid = strdup(PQgetvalue(res, i, i_oid));
-		tinfo[i].typowner = strdup(PQgetvalue(res, i, i_typowner));
-		tinfo[i].typname = strdup(PQgetvalue(res, i, i_typname));
-		tinfo[i].typlen = strdup(PQgetvalue(res, i, i_typlen));
-		tinfo[i].typprtlen = strdup(PQgetvalue(res, i, i_typprtlen));
-		tinfo[i].typinput = strdup(PQgetvalue(res, i, i_typinput));
-		tinfo[i].typoutput = strdup(PQgetvalue(res, i, i_typoutput));
-		tinfo[i].typreceive = strdup(PQgetvalue(res, i, i_typreceive));
-		tinfo[i].typsend = strdup(PQgetvalue(res, i, i_typsend));
-		tinfo[i].typelem = strdup(PQgetvalue(res, i, i_typelem));
-		tinfo[i].typdelim = strdup(PQgetvalue(res, i, i_typdelim));
-		if (PQgetisnull(res, i, i_typdefault))
-			tinfo[i].typdefault = NULL;
-		else
-			tinfo[i].typdefault = strdup(PQgetvalue(res, i, i_typdefault));
-		tinfo[i].typrelid = strdup(PQgetvalue(res, i, i_typrelid));
-		tinfo[i].typalign = strdup(PQgetvalue(res, i, i_typalign));
-		tinfo[i].typstorage = strdup(PQgetvalue(res, i, i_typstorage));
-		tinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
-		tinfo[i].typedefn = strdup(PQgetvalue(res, i, i_typedefn));
-		tinfo[i].typtype = strdup(PQgetvalue(res, i, i_typtype));
-
-		if (strlen(tinfo[i].usename) == 0)
-			write_msg(NULL, "WARNING: owner of data type %s appears to be invalid\n",
-					  tinfo[i].typname);
+			/* Now read it in chunks, sending data to archive */
+			do
+			{
+				cnt = lo_read(g_conn, loFd, buf, loBufSize);
+				if (cnt < 0)
+				{
+					write_msg(NULL, "dumpBlobs(): error reading large object: %s",
+							  PQerrorMessage(g_conn));
+					exit_nicely();
+				}
 
-		if (strcmp(PQgetvalue(res, i, i_typbyval), "f") == 0)
-			tinfo[i].passedbyvalue = 0;
-		else
-			tinfo[i].passedbyvalue = 1;
+				WriteData(AH, buf, cnt);
 
-		/*
-		 * check for user-defined array types, omit system generated ones
-		 */
-		if ((strcmp(tinfo[i].typelem, "0") != 0) &&
-			tinfo[i].typname[0] != '_')
-			tinfo[i].isArray = 1;
-		else
-			tinfo[i].isArray = 0;
+			} while (cnt > 0);
 
-		if (strcmp(PQgetvalue(res, i, i_typisdefined), "f") == 0)
-			tinfo[i].isDefined = 0;
-		else
-			tinfo[i].isDefined = 1;
-	}
+			lo_close(g_conn, loFd);
 
-	*numTypes = ntups;
+			EndBlob(AH, blobOid);
 
-	PQclear(res);
+		}
+	} while (PQntuples(res) > 0);
 
-	destroyPQExpBuffer(query);
+	destroyPQExpBuffer(oidQry);
+	destroyPQExpBuffer(oidFetchQry);
 
-	return tinfo;
+	return 1;
 }
 
 /*
- * getOperators:
- *	  read all operators in the system catalogs and return them in the
- * OprInfo* structure
+ * getNamespaces:
+ *	  read all namespaces in the system catalogs and return them in the
+ * NamespaceInfo* structure
  *
- *	numOprs is set to the number of operators read in
+ *	numNamespaces is set to the number of namespaces read in
  */
-OprInfo *
-getOperators(int *numOprs)
+NamespaceInfo *
+getNamespaces(int *numNamespaces)
 {
 	PGresult   *res;
 	int			ntups;
 	int			i;
-	PQExpBuffer query = createPQExpBuffer();
-
-	OprInfo    *oprinfo;
-
+	PQExpBuffer query;
+	NamespaceInfo *nsinfo;
 	int			i_oid;
-	int			i_oprname;
-	int			i_oprkind;
-	int			i_oprcode;
-	int			i_oprleft;
-	int			i_oprright;
-	int			i_oprcom;
-	int			i_oprnegate;
-	int			i_oprrest;
-	int			i_oprjoin;
-	int			i_oprcanhash;
-	int			i_oprlsortop;
-	int			i_oprrsortop;
+	int			i_nspname;
 	int			i_usename;
+	int			i_nspacl;
 
 	/*
-	 * find all operators, including builtin operators, filter out
-	 * system-defined operators at dump-out time
+	 * Before 7.3, there are no real namespaces; create two dummy entries,
+	 * one for user stuff and one for system stuff.
 	 */
+	if (g_fout->remoteVersion < 70300)
+	{
+		nsinfo = (NamespaceInfo *) malloc(2 * sizeof(NamespaceInfo));
+
+		nsinfo[0].oid = strdup("0");
+		nsinfo[0].nspname = strdup("");
+		nsinfo[0].usename = strdup("");
+		nsinfo[0].nspacl = strdup("");
+
+		selectDumpableNamespace(&nsinfo[0]);
+
+		nsinfo[1].oid = strdup("1");
+		nsinfo[1].nspname = strdup("pg_catalog");
+		nsinfo[1].usename = strdup("");
+		nsinfo[1].nspacl = strdup("");
+
+		selectDumpableNamespace(&nsinfo[1]);
+
+		g_namespaces = nsinfo;
+		g_numNamespaces = *numNamespaces = 2;
+
+		return nsinfo;
+	}
+
+	query = createPQExpBuffer();
+
+	/* Make sure we are in proper schema */
+	selectSourceSchema("pg_catalog");
 
-	appendPQExpBuffer(query, "SELECT pg_operator.oid, oprname, oprkind, oprcode, "
-			   "oprleft, oprright, oprcom, oprnegate, oprrest, oprjoin, "
-					  "oprcanhash, oprlsortop, oprrsortop, "
-	"(select usename from pg_user where oprowner = usesysid) as usename "
-					  "from pg_operator");
+	/*
+	 * we fetch all namespaces including system ones, so that every object
+	 * we read in can be linked to a containing namespace.
+	 */
+	appendPQExpBuffer(query, "SELECT oid, nspname, "
+						  "(select usename from pg_user where nspowner = usesysid) as usename, "
+						  "nspacl "
+						  "FROM pg_namespace");
 
 	res = PQexec(g_conn, query->data);
 	if (!res ||
 		PQresultStatus(res) != PGRES_TUPLES_OK)
 	{
-		write_msg(NULL, "query to obtain list of operators failed: %s", PQerrorMessage(g_conn));
+		write_msg(NULL, "query to obtain list of namespaces failed: %s", PQerrorMessage(g_conn));
 		exit_nicely();
 	}
 
 	ntups = PQntuples(res);
-	*numOprs = ntups;
 
-	oprinfo = (OprInfo *) malloc(ntups * sizeof(OprInfo));
+	nsinfo = (NamespaceInfo *) malloc(ntups * sizeof(NamespaceInfo));
 
 	i_oid = PQfnumber(res, "oid");
-	i_oprname = PQfnumber(res, "oprname");
-	i_oprkind = PQfnumber(res, "oprkind");
-	i_oprcode = PQfnumber(res, "oprcode");
-	i_oprleft = PQfnumber(res, "oprleft");
-	i_oprright = PQfnumber(res, "oprright");
-	i_oprcom = PQfnumber(res, "oprcom");
-	i_oprnegate = PQfnumber(res, "oprnegate");
-	i_oprrest = PQfnumber(res, "oprrest");
-	i_oprjoin = PQfnumber(res, "oprjoin");
-	i_oprcanhash = PQfnumber(res, "oprcanhash");
-	i_oprlsortop = PQfnumber(res, "oprlsortop");
-	i_oprrsortop = PQfnumber(res, "oprrsortop");
+	i_nspname = PQfnumber(res, "nspname");
 	i_usename = PQfnumber(res, "usename");
+	i_nspacl = PQfnumber(res, "nspacl");
 
 	for (i = 0; i < ntups; i++)
 	{
-		oprinfo[i].oid = strdup(PQgetvalue(res, i, i_oid));
-		oprinfo[i].oprname = strdup(PQgetvalue(res, i, i_oprname));
-		oprinfo[i].oprkind = strdup(PQgetvalue(res, i, i_oprkind));
-		oprinfo[i].oprcode = strdup(PQgetvalue(res, i, i_oprcode));
-		oprinfo[i].oprleft = strdup(PQgetvalue(res, i, i_oprleft));
-		oprinfo[i].oprright = strdup(PQgetvalue(res, i, i_oprright));
-		oprinfo[i].oprcom = strdup(PQgetvalue(res, i, i_oprcom));
-		oprinfo[i].oprnegate = strdup(PQgetvalue(res, i, i_oprnegate));
-		oprinfo[i].oprrest = strdup(PQgetvalue(res, i, i_oprrest));
-		oprinfo[i].oprjoin = strdup(PQgetvalue(res, i, i_oprjoin));
-		oprinfo[i].oprcanhash = strdup(PQgetvalue(res, i, i_oprcanhash));
-		oprinfo[i].oprlsortop = strdup(PQgetvalue(res, i, i_oprlsortop));
-		oprinfo[i].oprrsortop = strdup(PQgetvalue(res, i, i_oprrsortop));
-		oprinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+		nsinfo[i].oid = strdup(PQgetvalue(res, i, i_oid));
+		nsinfo[i].nspname = strdup(PQgetvalue(res, i, i_nspname));
+		nsinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+		nsinfo[i].nspacl = strdup(PQgetvalue(res, i, i_nspacl));
 
-		if (strlen(oprinfo[i].usename) == 0)
-			write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
-					  oprinfo[i].oprname);
+		/* Decide whether to dump this namespace */
+		selectDumpableNamespace(&nsinfo[i]);
 
+		if (strlen(nsinfo[i].usename) == 0)
+			write_msg(NULL, "WARNING: owner of namespace %s appears to be invalid\n",
+					  nsinfo[i].nspname);
 	}
 
 	PQclear(res);
-
 	destroyPQExpBuffer(query);
 
-	return oprinfo;
-}
-
-void
-clearTypeInfo(TypeInfo *tp, int numTypes)
-{
-	int			i;
-
-	for (i = 0; i < numTypes; ++i)
-	{
-		if (tp[i].oid)
-			free(tp[i].oid);
-		if (tp[i].typowner)
-			free(tp[i].typowner);
-		if (tp[i].typname)
-			free(tp[i].typname);
-		if (tp[i].typlen)
-			free(tp[i].typlen);
-		if (tp[i].typprtlen)
-			free(tp[i].typprtlen);
-		if (tp[i].typinput)
-			free(tp[i].typinput);
-		if (tp[i].typoutput)
-			free(tp[i].typoutput);
-		if (tp[i].typreceive)
-			free(tp[i].typreceive);
-		if (tp[i].typsend)
-			free(tp[i].typsend);
-		if (tp[i].typelem)
-			free(tp[i].typelem);
-		if (tp[i].typdelim)
-			free(tp[i].typdelim);
-		if (tp[i].typdefault)
-			free(tp[i].typdefault);
-		if (tp[i].typrelid)
-			free(tp[i].typrelid);
-		if (tp[i].typalign)
-			free(tp[i].typalign);
-		if (tp[i].typstorage)
-			free(tp[i].typstorage);
-		if (tp[i].usename)
-			free(tp[i].usename);
-		if (tp[i].typedefn)
-			free(tp[i].typedefn);
-	}
-	free(tp);
-}
-
-void
-clearFuncInfo(FuncInfo *fun, int numFuncs)
-{
-	int			i,
-				a;
+	g_namespaces = nsinfo;
+	g_numNamespaces = *numNamespaces = ntups;
 
-	if (!fun)
-		return;
-	for (i = 0; i < numFuncs; ++i)
-	{
-		if (fun[i].oid)
-			free(fun[i].oid);
-		if (fun[i].proname)
-			free(fun[i].proname);
-		if (fun[i].usename)
-			free(fun[i].usename);
-		if (fun[i].argtypes)
-		{
-			for (a = 0; a < fun[i].nargs; ++a)
-				if (fun[i].argtypes[a])
-					free(fun[i].argtypes[a]);
-			free(fun[i].argtypes);
-		}
-		if (fun[i].prorettype)
-			free(fun[i].prorettype);
-		if (fun[i].prosrc)
-			free(fun[i].prosrc);
-		if (fun[i].probin)
-			free(fun[i].probin);
-	}
-	free(fun);
+	return nsinfo;
 }
 
-static void
-clearTableInfo(TableInfo *tblinfo, int numTables)
+/*
+ * findNamespace:
+ *		given a namespace OID and an object OID, look up the info read by
+ *		getNamespaces
+ *
+ * NB: for pre-7.3 source database, we use object OID to guess whether it's
+ * a system object or not.  In 7.3 and later there is no guessing.
+ */
+static NamespaceInfo *
+findNamespace(const char *nsoid, const char *objoid)
 {
-	int			i,
-				j;
+	int			i;
 
-	for (i = 0; i < numTables; ++i)
+	if (g_fout->remoteVersion >= 70300)
 	{
-
-		if (tblinfo[i].oid)
-			free(tblinfo[i].oid);
-		if (tblinfo[i].relacl)
-			free(tblinfo[i].relacl);
-		if (tblinfo[i].usename)
-			free(tblinfo[i].usename);
-
-		if (tblinfo[i].relname)
-			free(tblinfo[i].relname);
-
-		if (tblinfo[i].relkind == RELKIND_SEQUENCE)
-			continue;
-
-		/* Process Attributes */
-		for (j = 0; j < tblinfo[i].numatts; j++)
+		for (i = 0; i < g_numNamespaces; i++)
 		{
-			if (tblinfo[i].attnames[j])
-				free(tblinfo[i].attnames[j]);
-			if (tblinfo[i].typnames[j])
-				free(tblinfo[i].typnames[j]);
-		}
+			NamespaceInfo  *nsinfo = &g_namespaces[i];
 
-		if (tblinfo[i].triggers)
-		{
-			for (j = 0; j < tblinfo[i].ntrig; j++)
-			{
-				if (tblinfo[i].triggers[j].tgsrc)
-					free(tblinfo[i].triggers[j].tgsrc);
-				if (tblinfo[i].triggers[j].oid)
-					free(tblinfo[i].triggers[j].oid);
-				if (tblinfo[i].triggers[j].tgname)
-					free(tblinfo[i].triggers[j].tgname);
-				if (tblinfo[i].triggers[j].tgdel)
-					free(tblinfo[i].triggers[j].tgdel);
-			}
-			free(tblinfo[i].triggers);
+			if (strcmp(nsoid, nsinfo->oid) == 0)
+				return nsinfo;
 		}
-
-		if (tblinfo[i].atttypmod)
-			free((int *) tblinfo[i].atttypmod);
-		if (tblinfo[i].inhAttrs)
-			free((int *) tblinfo[i].inhAttrs);
-		if (tblinfo[i].inhAttrDef)
-			free((int *) tblinfo[i].inhAttrDef);
-		if (tblinfo[i].inhNotNull)
-			free((int *) tblinfo[i].inhNotNull);
-		if (tblinfo[i].attnames)
-			free(tblinfo[i].attnames);
-		if (tblinfo[i].atttypedefns)
-			free(tblinfo[i].atttypedefns);
-		if (tblinfo[i].typnames)
-			free(tblinfo[i].typnames);
-		if (tblinfo[i].notnull)
-			free(tblinfo[i].notnull);
-		if (tblinfo[i].primary_key_name)
-			free(tblinfo[i].primary_key_name);
-	}
-	free(tblinfo);
-}
-
-void
-clearInhInfo(InhInfo *inh, int numInherits)
-{
-	int			i;
-
-	if (!inh)
-		return;
-	for (i = 0; i < numInherits; ++i)
-	{
-		if (inh[i].inhrelid)
-			free(inh[i].inhrelid);
-		if (inh[i].inhparent)
-			free(inh[i].inhparent);
+		write_msg(NULL, "Failed to find namespace with OID %s.\n", nsoid);
+		exit_nicely();
 	}
-	free(inh);
-}
-
-void
-clearOprInfo(OprInfo *opr, int numOprs)
-{
-	int			i;
-
-	if (!opr)
-		return;
-	for (i = 0; i < numOprs; ++i)
-	{
-		if (opr[i].oid)
-			free(opr[i].oid);
-		if (opr[i].oprname)
-			free(opr[i].oprname);
-		if (opr[i].oprkind)
-			free(opr[i].oprkind);
-		if (opr[i].oprcode)
-			free(opr[i].oprcode);
-		if (opr[i].oprleft)
-			free(opr[i].oprleft);
-		if (opr[i].oprright)
-			free(opr[i].oprright);
-		if (opr[i].oprcom)
-			free(opr[i].oprcom);
-		if (opr[i].oprnegate)
-			free(opr[i].oprnegate);
-		if (opr[i].oprrest)
-			free(opr[i].oprrest);
-		if (opr[i].oprjoin)
-			free(opr[i].oprjoin);
-		if (opr[i].oprcanhash)
-			free(opr[i].oprcanhash);
-		if (opr[i].oprlsortop)
-			free(opr[i].oprlsortop);
-		if (opr[i].oprrsortop)
-			free(opr[i].oprrsortop);
-		if (opr[i].usename)
-			free(opr[i].usename);
-	}
-	free(opr);
-}
-
-void
-clearIndInfo(IndInfo *ind, int numIndexes)
-{
-	int			i,
-				a;
-
-	if (!ind)
-		return;
-	for (i = 0; i < numIndexes; ++i)
-	{
-		if (ind[i].indexreloid)
-			free(ind[i].indexreloid);
-		if (ind[i].indreloid)
-			free(ind[i].indreloid);
-		if (ind[i].indexrelname)
-			free(ind[i].indexrelname);
-		if (ind[i].indrelname)
-			free(ind[i].indrelname);
-		if (ind[i].indexdef)
-			free(ind[i].indexdef);
-		if (ind[i].indisprimary)
-			free(ind[i].indisprimary);
-		if (ind[i].indkey)
-		{
-			for (a = 0; a < ind[i].indnkeys; ++a)
-				if (ind[i].indkey[a])
-					free(ind[i].indkey[a]);
-			free(ind[i].indkey);
-		}
+	else
+	{
+		/* This code depends on the layout set up by getNamespaces. */
+		if (atooid(objoid) > g_last_builtin_oid)
+			i = 0;				/* user object */
+		else
+			i = 1;				/* system object */
+		return &g_namespaces[i];
 	}
-	free(ind);
-}
-
-void
-clearAggInfo(AggInfo *agginfo, int numArgs)
-{
-	int			i;
 
-	if (!agginfo)
-		return;
-	for (i = 0; i < numArgs; ++i)
-	{
-		if (agginfo[i].oid)
-			free(agginfo[i].oid);
-		if (agginfo[i].aggname)
-			free(agginfo[i].aggname);
-		if (agginfo[i].aggtransfn)
-			free(agginfo[i].aggtransfn);
-		if (agginfo[i].aggfinalfn)
-			free(agginfo[i].aggfinalfn);
-		if (agginfo[i].aggtranstype)
-			free(agginfo[i].aggtranstype);
-		if (agginfo[i].aggbasetype)
-			free(agginfo[i].aggbasetype);
-		if (agginfo[i].agginitval)
-			free(agginfo[i].agginitval);
-		if (agginfo[i].usename)
-			free(agginfo[i].usename);
-	}
-	free(agginfo);
+	return NULL;				/* keep compiler quiet */
 }
 
 /*
- * getAggregates:
- *	  read all the user-defined aggregates in the system catalogs and
- * return them in the AggInfo* structure
+ * getTypes:
+ *	  read all types in the system catalogs and return them in the
+ * TypeInfo* structure
  *
- * numAggs is set to the number of aggregates read in
+ *	numTypes is set to the number of types read in
  */
-AggInfo *
-getAggregates(int *numAggs)
+TypeInfo *
+getTypes(int *numTypes)
 {
 	PGresult   *res;
 	int			ntups;
 	int			i;
 	PQExpBuffer query = createPQExpBuffer();
-	AggInfo    *agginfo;
-
+	TypeInfo   *tinfo;
 	int			i_oid;
-	int			i_aggname;
-	int			i_aggtransfn;
-	int			i_aggfinalfn;
-	int			i_aggtranstype;
-	int			i_aggbasetype;
-	int			i_agginitval;
+	int			i_typname;
+	int			i_typnamespace;
 	int			i_usename;
-	int			i_convertok;
+	int			i_typelem;
+	int			i_typrelid;
+	int			i_typtype;
+	int			i_typisdefined;
 
-	/* find all user-defined aggregates */
+	/*
+	 * we include even the built-in types because those may be used as
+	 * array elements by user-defined types
+	 *
+	 * we filter out the built-in types when we dump out the types
+	 */
 
-	if (g_fout->remoteVersion < 70100)
-	{
-		appendPQExpBuffer(query, "SELECT pg_aggregate.oid, aggname, aggtransfn1 as aggtransfn, "
-			   "aggfinalfn, aggtranstype1 as aggtranstype, aggbasetype, "
-						  "agginitval1 as agginitval, "
-						  "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) as convertok, "
-						  "(select usename from pg_user where aggowner = usesysid) as usename "
-						  "from pg_aggregate");
-	}
-	else if (g_fout->remoteVersion < 70300)
+	/* Make sure we are in proper schema */
+	selectSourceSchema("pg_catalog");
+
+	if (g_fout->remoteVersion >= 70300)
 	{
-		appendPQExpBuffer(query, "SELECT pg_aggregate.oid, aggname, aggtransfn, "
-						  "aggfinalfn, aggtranstype, aggbasetype, "
-						  "agginitval, "
-						  "'t'::boolean as convertok, "
-						  "(select usename from pg_user where aggowner = usesysid) as usename "
-						  "from pg_aggregate");
+		appendPQExpBuffer(query, "SELECT pg_type.oid, typname, "
+						  "typnamespace, "
+						  "(select usename from pg_user where typowner = usesysid) as usename, "
+						  "typelem, typrelid, typtype, typisdefined "
+						  "FROM pg_type");
 	}
 	else
 	{
-		appendPQExpBuffer(query, "SELECT p.oid, proname as aggname, aggtransfn, "
-						  "aggfinalfn, aggtranstype, proargtypes[0] as aggbasetype, "
-						  "agginitval, "
-						  "'t'::boolean as convertok, "
-						  "(select usename from pg_user where proowner = usesysid) as usename "
-						  "from pg_aggregate a, pg_proc p "
-						  "where a.aggfnoid = p.oid");
+		appendPQExpBuffer(query, "SELECT pg_type.oid, typname, "
+						  "0::oid as typnamespace, "
+						  "(select usename from pg_user where typowner = usesysid) as usename, "
+						  "typelem, typrelid, typtype, typisdefined "
+						  "FROM pg_type");
 	}
 
 	res = PQexec(g_conn, query->data);
 	if (!res ||
 		PQresultStatus(res) != PGRES_TUPLES_OK)
 	{
-		write_msg(NULL, "query to obtain list of aggregate functions failed: %s",
-				  PQerrorMessage(g_conn));
+		write_msg(NULL, "query to obtain list of data types failed: %s", PQerrorMessage(g_conn));
 		exit_nicely();
 	}
 
 	ntups = PQntuples(res);
-	*numAggs = ntups;
 
-	agginfo = (AggInfo *) malloc(ntups * sizeof(AggInfo));
+	tinfo = (TypeInfo *) malloc(ntups * sizeof(TypeInfo));
 
 	i_oid = PQfnumber(res, "oid");
-	i_aggname = PQfnumber(res, "aggname");
-	i_aggtransfn = PQfnumber(res, "aggtransfn");
-	i_aggfinalfn = PQfnumber(res, "aggfinalfn");
-	i_aggtranstype = PQfnumber(res, "aggtranstype");
-	i_aggbasetype = PQfnumber(res, "aggbasetype");
-	i_agginitval = PQfnumber(res, "agginitval");
+	i_typname = PQfnumber(res, "typname");
+	i_typnamespace = PQfnumber(res, "typnamespace");
 	i_usename = PQfnumber(res, "usename");
-	i_convertok = PQfnumber(res, "convertok");
+	i_typelem = PQfnumber(res, "typelem");
+	i_typrelid = PQfnumber(res, "typrelid");
+	i_typtype = PQfnumber(res, "typtype");
+	i_typisdefined = PQfnumber(res, "typisdefined");
 
 	for (i = 0; i < ntups; i++)
 	{
-		agginfo[i].oid = strdup(PQgetvalue(res, i, i_oid));
-		agginfo[i].aggname = strdup(PQgetvalue(res, i, i_aggname));
-		agginfo[i].aggtransfn = strdup(PQgetvalue(res, i, i_aggtransfn));
-		agginfo[i].aggfinalfn = strdup(PQgetvalue(res, i, i_aggfinalfn));
-		agginfo[i].aggtranstype = strdup(PQgetvalue(res, i, i_aggtranstype));
-		agginfo[i].aggbasetype = strdup(PQgetvalue(res, i, i_aggbasetype));
-		agginfo[i].agginitval = strdup(PQgetvalue(res, i, i_agginitval));
-		agginfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
-		if (strlen(agginfo[i].usename) == 0)
-			write_msg(NULL, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n",
-					  agginfo[i].aggname);
+		tinfo[i].oid = strdup(PQgetvalue(res, i, i_oid));
+		tinfo[i].typname = strdup(PQgetvalue(res, i, i_typname));
+		tinfo[i].typnamespace = findNamespace(PQgetvalue(res, i, i_typnamespace),
+											  tinfo[i].oid);
+		tinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+		tinfo[i].typelem = strdup(PQgetvalue(res, i, i_typelem));
+		tinfo[i].typrelid = strdup(PQgetvalue(res, i, i_typrelid));
+		tinfo[i].typtype = *PQgetvalue(res, i, i_typtype);
+
+		if (strlen(tinfo[i].usename) == 0)
+			write_msg(NULL, "WARNING: owner of data type %s appears to be invalid\n",
+					  tinfo[i].typname);
 
-		agginfo[i].convertok = (PQgetvalue(res, i, i_convertok)[0] == 't');
+		/*
+		 * check for user-defined array types, omit system generated ones
+		 */
+		if ((strcmp(tinfo[i].typelem, "0") != 0) &&
+			tinfo[i].typname[0] != '_')
+			tinfo[i].isArray = true;
+		else
+			tinfo[i].isArray = false;
 
+		if (strcmp(PQgetvalue(res, i, i_typisdefined), "t") == 0)
+			tinfo[i].isDefined = true;
+		else
+			tinfo[i].isDefined = false;
 	}
 
+	*numTypes = ntups;
+
 	PQclear(res);
 
 	destroyPQExpBuffer(query);
 
-	return agginfo;
+	return tinfo;
 }
 
 /*
- * getFuncs:
- *	  read all the user-defined functions in the system catalogs and
- * return them in the FuncInfo* structure
- *
- * numFuncs is set to the number of functions read in
- *
+ * getOperators:
+ *	  read all operators in the system catalogs and return them in the
+ * OprInfo* structure
  *
+ *	numOprs is set to the number of operators read in
  */
-FuncInfo *
-getFuncs(int *numFuncs)
+OprInfo *
+getOperators(int *numOprs)
 {
 	PGresult   *res;
 	int			ntups;
 	int			i;
 	PQExpBuffer query = createPQExpBuffer();
-	FuncInfo   *finfo;
-
+	OprInfo    *oprinfo;
 	int			i_oid;
-	int			i_proname;
-	int			i_prolang;
-	int			i_pronargs;
-	int			i_proargtypes;
-	int			i_prorettype;
-	int			i_proretset;
-	int			i_prosrc;
-	int			i_probin;
-	int			i_provolatile;
-	int			i_isimplicit;
-	int			i_isstrict;
+	int			i_oprname;
+	int			i_oprnamespace;
 	int			i_usename;
+	int			i_oprcode;
 
-	/* find all user-defined funcs */
+	/*
+	 * find all operators, including builtin operators;
+	 * we filter out system-defined operators at dump-out time.
+	 */
 
-	if (g_fout->remoteVersion < 70100)
-	{
-		appendPQExpBuffer(query,
-		   "SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, "
-						  "proretset, proargtypes, prosrc, probin, "
-						  "(select usename from pg_user where proowner = usesysid) as usename, "
-						  "case when proiscachable then 'i' else 'v' end as provolatile, "
-						  "'f'::boolean as proimplicit, "
-						  "'f'::boolean as proisstrict "
-						  "from pg_proc "
-						  "where pg_proc.oid > '%u'::oid",
-						  g_last_builtin_oid);
-	}
-	else if (g_fout->remoteVersion < 70300)
+	/* Make sure we are in proper schema */
+	selectSourceSchema("pg_catalog");
+
+	if (g_fout->remoteVersion >= 70300)
 	{
-		appendPQExpBuffer(query,
-		   "SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, "
-						  "proretset, proargtypes, prosrc, probin, "
-						  "(select usename from pg_user where proowner = usesysid) as usename, "
-						  "case when proiscachable then 'i' else 'v' end as provolatile, "
-						  "'f'::boolean as proimplicit, "
-						  "proisstrict "
-						  "from pg_proc "
-						  "where pg_proc.oid > '%u'::oid",
-						  g_last_builtin_oid);
+		appendPQExpBuffer(query, "SELECT pg_operator.oid, oprname, "
+						  "oprnamespace, "
+						  "(select usename from pg_user where oprowner = usesysid) as usename, "
+						  "oprcode::oid "
+						  "from pg_operator");
 	}
 	else
 	{
-		appendPQExpBuffer(query,
-		   "SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, "
-						  "proretset, proargtypes, prosrc, probin, "
-						  "(select usename from pg_user where proowner = usesysid) as usename, "
-						  "provolatile, proimplicit, proisstrict "
-						  "from pg_proc "
-						  "where pg_proc.oid > '%u'::oid and not proisagg",
-						  g_last_builtin_oid);
+		appendPQExpBuffer(query, "SELECT pg_operator.oid, oprname, "
+						  "0::oid as oprnamespace, "
+						  "(select usename from pg_user where oprowner = usesysid) as usename, "
+						  "oprcode::oid "
+						  "from pg_operator");
 	}
 
 	res = PQexec(g_conn, query->data);
 	if (!res ||
 		PQresultStatus(res) != PGRES_TUPLES_OK)
 	{
-		write_msg(NULL, "query to obtain list of functions failed: %s",
-				  PQerrorMessage(g_conn));
+		write_msg(NULL, "query to obtain list of operators failed: %s", PQerrorMessage(g_conn));
 		exit_nicely();
 	}
 
 	ntups = PQntuples(res);
+	*numOprs = ntups;
 
-	*numFuncs = ntups;
-
-	finfo = (FuncInfo *) malloc(ntups * sizeof(FuncInfo));
-
-	memset((char *) finfo, 0, ntups * sizeof(FuncInfo));
+	oprinfo = (OprInfo *) malloc(ntups * sizeof(OprInfo));
 
 	i_oid = PQfnumber(res, "oid");
-	i_proname = PQfnumber(res, "proname");
-	i_prolang = PQfnumber(res, "prolang");
-	i_pronargs = PQfnumber(res, "pronargs");
-	i_proargtypes = PQfnumber(res, "proargtypes");
-	i_prorettype = PQfnumber(res, "prorettype");
-	i_proretset = PQfnumber(res, "proretset");
-	i_prosrc = PQfnumber(res, "prosrc");
-	i_probin = PQfnumber(res, "probin");
-	i_provolatile = PQfnumber(res, "provolatile");
-	i_isimplicit = PQfnumber(res, "proimplicit");
-	i_isstrict = PQfnumber(res, "proisstrict");
+	i_oprname = PQfnumber(res, "oprname");
+	i_oprnamespace = PQfnumber(res, "oprnamespace");
 	i_usename = PQfnumber(res, "usename");
+	i_oprcode = PQfnumber(res, "oprcode");
 
 	for (i = 0; i < ntups; i++)
 	{
-		finfo[i].oid = strdup(PQgetvalue(res, i, i_oid));
-		finfo[i].proname = strdup(PQgetvalue(res, i, i_proname));
-
-		finfo[i].prosrc = strdup(PQgetvalue(res, i, i_prosrc));
-		finfo[i].probin = strdup(PQgetvalue(res, i, i_probin));
-
-		finfo[i].prorettype = strdup(PQgetvalue(res, i, i_prorettype));
-		finfo[i].retset = (strcmp(PQgetvalue(res, i, i_proretset), "t") == 0);
-		finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
-		finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
-		finfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
-		finfo[i].provolatile = (PQgetvalue(res, i, i_provolatile))[0];
-		finfo[i].isimplicit = (strcmp(PQgetvalue(res, i, i_isimplicit), "t") == 0);
-		finfo[i].isstrict = (strcmp(PQgetvalue(res, i, i_isstrict), "t") == 0);
-
-		if (strlen(finfo[i].usename) == 0)
-			write_msg(NULL, "WARNING: owner of function \"%s\" appears to be invalid\n",
-					  finfo[i].proname);
+		oprinfo[i].oid = strdup(PQgetvalue(res, i, i_oid));
+		oprinfo[i].oprname = strdup(PQgetvalue(res, i, i_oprname));
+		oprinfo[i].oprnamespace = findNamespace(PQgetvalue(res, i, i_oprnamespace),
+												oprinfo[i].oid);
+		oprinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+		oprinfo[i].oprcode = strdup(PQgetvalue(res, i, i_oprcode));
 
-		finfo[i].argtypes = malloc(finfo[i].nargs * sizeof(finfo[i].argtypes[0]));
-		parseNumericArray(PQgetvalue(res, i, i_proargtypes),
-						  finfo[i].argtypes,
-						  finfo[i].nargs);
-		finfo[i].dumped = 0;
+		if (strlen(oprinfo[i].usename) == 0)
+			write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
+					  oprinfo[i].oprname);
 	}
 
 	PQclear(res);
 
 	destroyPQExpBuffer(query);
 
-	return finfo;
+	return oprinfo;
 }
 
 /*
- * getTables
- *	  read all the user-defined tables (no indexes, no catalogs)
- * in the system catalogs return them in the TableInfo* structure
+ * getAggregates:
+ *	  read all the user-defined aggregates in the system catalogs and
+ * return them in the AggInfo* structure
  *
- * numTables is set to the number of tables read in
+ * numAggs is set to the number of aggregates read in
  */
-TableInfo *
-getTables(int *numTables, FuncInfo *finfo, int numFuncs, const char *tablename)
+AggInfo *
+getAggregates(int *numAggs)
 {
 	PGresult   *res;
 	int			ntups;
 	int			i;
 	PQExpBuffer query = createPQExpBuffer();
-	PQExpBuffer delqry = createPQExpBuffer();
-	PQExpBuffer lockquery = createPQExpBuffer();
-	TableInfo  *tblinfo;
+	AggInfo    *agginfo;
 
-	int			i_reloid;
-	int			i_relname;
-	int			i_relkind;
-	int			i_relacl;
+	int			i_oid;
+	int			i_aggname;
+	int			i_aggnamespace;
 	int			i_usename;
-	int			i_relchecks;
-	int			i_reltriggers;
-	int			i_relhasindex;
-	int			i_relhasoids;
 
-	/*
-	 * find all the user-defined tables (no indexes and no catalogs),
-	 * ordering by oid is important so that we always process the parent
-	 * tables before the child tables when traversing the tblinfo*
-	 *
-	 * we ignore tables that are not type 'r' (ordinary relation) or 'S'
-	 * (sequence) or 'v' (view).
-	 */
+	/* Make sure we are in proper schema */
+	selectSourceSchema("pg_catalog");
 
-	if (g_fout->remoteVersion >= 70200)
-	{
-		appendPQExpBuffer(query,
-						"SELECT pg_class.oid, relname, relacl, relkind, "
-						  "(select usename from pg_user where relowner = usesysid) as usename, "
-					   "relchecks, reltriggers, relhasindex, relhasoids "
-						  "from pg_class "
-						  "where relname !~ '^pg_' "
-						  "and relkind in ('%c', '%c', '%c') "
-						  "order by oid",
-					   RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
-	}
-	else if (g_fout->remoteVersion >= 70100)
+	/* find all user-defined aggregates */
+
+	if (g_fout->remoteVersion >= 70300)
 	{
-		/* all tables have oids in 7.1 */
-		appendPQExpBuffer(query,
-						"SELECT pg_class.oid, relname, relacl, relkind, "
-						  "(select usename from pg_user where relowner = usesysid) as usename, "
-		  "relchecks, reltriggers, relhasindex, 't'::bool as relhasoids "
-						  "from pg_class "
-						  "where relname !~ '^pg_' "
-						  "and relkind in ('%c', '%c', '%c') "
-						  "order by oid",
-					   RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
+		appendPQExpBuffer(query, "SELECT pg_proc.oid, proname as aggname, "
+						  "pronamespace as aggnamespace, "
+						  "(select usename from pg_user where proowner = usesysid) as usename "
+						  "FROM pg_proc "
+						  "WHERE proisagg "
+						  "AND pronamespace != "
+						  "(select oid from pg_namespace where nspname = 'pg_catalog')");
 	}
 	else
 	{
-		/*
-		 * Before 7.1, view relkind was not set to 'v', so we must check
-		 * if we have a view by looking for a rule in pg_rewrite.
-		 */
-		appendPQExpBuffer(query,
-						  "SELECT c.oid, relname, relacl, "
-						  "CASE WHEN relhasrules and relkind = 'r' "
-				  "  and EXISTS(SELECT rulename FROM pg_rewrite r WHERE "
-				  "             r.ev_class = c.oid AND r.ev_type = '1') "
-						  "THEN '%c'::\"char\" "
-						  "ELSE relkind END AS relkind,"
-						  "(select usename from pg_user where relowner = usesysid) as usename, "
-		  "relchecks, reltriggers, relhasindex, 't'::bool as relhasoids "
-						  "from pg_class c "
-						  "where relname !~ '^pg_' "
-						  "and relkind in ('%c', '%c', '%c') "
-						  "order by oid",
-						  RELKIND_VIEW,
-					   RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
+		appendPQExpBuffer(query, "SELECT pg_aggregate.oid, aggname, "
+						  "0::oid as aggnamespace, "
+						  "(select usename from pg_user where aggowner = usesysid) as usename "
+						  "from pg_aggregate "
+						  "where oid > '%u'::oid",
+						  g_last_builtin_oid);
 	}
 
 	res = PQexec(g_conn, query->data);
 	if (!res ||
 		PQresultStatus(res) != PGRES_TUPLES_OK)
 	{
-		write_msg(NULL, "query to obtain list of tables failed: %s",
+		write_msg(NULL, "query to obtain list of aggregate functions failed: %s",
 				  PQerrorMessage(g_conn));
 		exit_nicely();
 	}
 
 	ntups = PQntuples(res);
+	*numAggs = ntups;
 
-	*numTables = ntups;
-
-	/*
-	 * First pass: extract data from result and lock tables.  We do the
-	 * locking before anything else, to minimize the window wherein a
-	 * table could disappear under us.
-	 *
-	 * Note that we have to collect info about all tables here, even when
-	 * dumping only one, because we don't know which tables might be
-	 * inheritance ancestors of the target table.  Possible future
-	 * improvement: suppress later collection of schema info about tables
-	 * that are determined not to be either targets or ancestors of
-	 * targets.
-	 */
-	tblinfo = (TableInfo *) malloc(ntups * sizeof(TableInfo));
+	agginfo = (AggInfo *) malloc(ntups * sizeof(AggInfo));
 
-	i_reloid = PQfnumber(res, "oid");
-	i_relname = PQfnumber(res, "relname");
-	i_relacl = PQfnumber(res, "relacl");
-	i_relkind = PQfnumber(res, "relkind");
+	i_oid = PQfnumber(res, "oid");
+	i_aggname = PQfnumber(res, "aggname");
+	i_aggnamespace = PQfnumber(res, "aggnamespace");
 	i_usename = PQfnumber(res, "usename");
-	i_relchecks = PQfnumber(res, "relchecks");
-	i_reltriggers = PQfnumber(res, "reltriggers");
-	i_relhasindex = PQfnumber(res, "relhasindex");
-	i_relhasoids = PQfnumber(res, "relhasoids");
 
 	for (i = 0; i < ntups; i++)
 	{
-		tblinfo[i].oid = strdup(PQgetvalue(res, i, i_reloid));
-		tblinfo[i].relname = strdup(PQgetvalue(res, i, i_relname));
-		tblinfo[i].relacl = strdup(PQgetvalue(res, i, i_relacl));
-		tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
-		tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0);
-		tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
-		tblinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
-		tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
-		tblinfo[i].ntrig = atoi(PQgetvalue(res, i, i_reltriggers));
-
-		/*
-		 * Read-lock target tables to make sure they aren't DROPPED or
-		 * altered in schema before we get around to dumping them.
-		 *
-		 * If no target tablename was specified, lock all tables we see,
-		 * otherwise lock only the specified table.  (This is incomplete
-		 * because we'll still try to collect schema info about all
-		 * tables, and could possibly lose during that phase.  But for the
-		 * typical use where we're dumping all tables anyway, it matters
-		 * not.)
-		 *
-		 * NOTE: it'd be kinda nice to lock views and sequences too, not only
-		 * plain tables, but the backend doesn't presently allow that.
-		 */
-		if ((tblinfo[i].relkind == RELKIND_RELATION) &&
-		(tablename == NULL || strcmp(tblinfo[i].relname, tablename) == 0))
-		{
-			PGresult   *lres;
-
-			resetPQExpBuffer(lockquery);
-			appendPQExpBuffer(lockquery,
-							  "LOCK TABLE %s IN ACCESS SHARE MODE",
-							  fmtId(tblinfo[i].relname, force_quotes));
-			lres = PQexec(g_conn, lockquery->data);
-			if (!lres || PQresultStatus(lres) != PGRES_COMMAND_OK)
-			{
-				write_msg(NULL, "Attempt to lock table \"%s\" failed.  %s",
-						  tblinfo[i].relname, PQerrorMessage(g_conn));
-				exit_nicely();
-			}
-			PQclear(lres);
-		}
-	}
-
-	PQclear(res);
-	res = NULL;
-
-	/*
-	 * Second pass: pick up additional information about each table, as
-	 * required.
-	 */
-	for (i = 0; i < *numTables; i++)
-	{
-		/* Emit notice if join for owner failed */
-		if (strlen(tblinfo[i].usename) == 0)
-			write_msg(NULL, "WARNING: owner of table \"%s\" appears to be invalid\n",
-					  tblinfo[i].relname);
-
-		/* Get definition if it's a view */
-		if (tblinfo[i].relkind == RELKIND_VIEW)
-		{
-			PGresult   *res2;
-
-			resetPQExpBuffer(query);
-
-			if (g_fout->remoteVersion < 70300)
-			{
-				appendPQExpBuffer(query, "SELECT definition as viewdef, "
-								  "(select oid from pg_rewrite where "
-								  " rulename=('_RET' || viewname)::name) as view_oid"
-								  " from pg_views where viewname = ");
-				formatStringLiteral(query, tblinfo[i].relname, CONV_ALL);
-				appendPQExpBuffer(query, ";");
-			}
-			else
-			{
-				/* Beginning in 7.3, viewname is not unique; use OID */
-				appendPQExpBuffer(query, "SELECT pg_get_viewdef(ev_class) as viewdef, "
-								  "oid as view_oid"
-								  " from pg_rewrite where"
-								  " ev_class = '%s'::oid and"
-								  " rulename = '_RETURN';",
-								  tblinfo[i].oid);
-			}
-
-			res2 = PQexec(g_conn, query->data);
-			if (!res2 || PQresultStatus(res2) != PGRES_TUPLES_OK)
-			{
-				write_msg(NULL, "query to obtain definition of view \"%s\" failed: %s",
-						  tblinfo[i].relname, PQerrorMessage(g_conn));
-				exit_nicely();
-			}
-
-			if (PQntuples(res2) != 1)
-			{
-				if (PQntuples(res2) < 1)
-					write_msg(NULL, "query to obtain definition of view \"%s\" returned no data\n",
-							  tblinfo[i].relname);
-				else
-					write_msg(NULL, "query to obtain definition of view \"%s\" returned more than one definition\n",
-							  tblinfo[i].relname);
-				exit_nicely();
-			}
-
-			if (PQgetisnull(res2, 0, 1))
-			{
-				write_msg(NULL, "query to obtain definition of view \"%s\" returned NULL oid\n",
-						  tblinfo[i].relname);
-				exit_nicely();
-			}
-
-			tblinfo[i].viewdef = strdup(PQgetvalue(res2, 0, 0));
-			tblinfo[i].viewoid = strdup(PQgetvalue(res2, 0, 1));
-
-			if (strlen(tblinfo[i].viewdef) == 0)
-			{
-				write_msg(NULL, "definition of view \"%s\" appears to be empty (length zero)\n",
-						  tblinfo[i].relname);
-				exit_nicely();
-			}
-			PQclear(res2);
-		}
-		else
-			tblinfo[i].viewdef = NULL;
-
-		/*
-		 * Get non-inherited CHECK constraints, if any.
-		 *
-		 * Exclude inherited CHECKs from CHECK constraints total. If a
-		 * constraint matches by name and condition with a constraint
-		 * belonging to a parent class (OR conditions match and both names
-		 * start with '$', we assume it was inherited.
-		 */
-		if (tblinfo[i].ncheck > 0)
-		{
-			PGresult   *res2;
-			int			i_rcname,
-						i_rcsrc;
-			int			ntups2;
-			int			i2;
+		agginfo[i].oid = strdup(PQgetvalue(res, i, i_oid));
+		agginfo[i].aggname = strdup(PQgetvalue(res, i, i_aggname));
+		agginfo[i].aggnamespace = findNamespace(PQgetvalue(res, i, i_aggnamespace),
+												agginfo[i].oid);
+		agginfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+		if (strlen(agginfo[i].usename) == 0)
+			write_msg(NULL, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n",
+					  agginfo[i].aggname);
+	}
 
-			if (g_verbose)
-				write_msg(NULL, "finding CHECK constraints for table %s\n",
-						  tblinfo[i].relname);
+	PQclear(res);
 
-			resetPQExpBuffer(query);
-			appendPQExpBuffer(query, "SELECT rcname, rcsrc from pg_relcheck "
-							  " where rcrelid = '%s'::oid "
-							  "   and not exists "
-				   "  (select * from pg_relcheck as c, pg_inherits as i "
-							"    where i.inhrelid = pg_relcheck.rcrelid "
-							  "      and (c.rcname = pg_relcheck.rcname "
-							  "          or (    c.rcname[0] = '$' "
-						 "              and pg_relcheck.rcname[0] = '$')"
-							  "          )"
-							  "      and c.rcsrc = pg_relcheck.rcsrc "
-							  "      and c.rcrelid = i.inhparent) "
-							  " order by rcname ",
-							  tblinfo[i].oid);
-			res2 = PQexec(g_conn, query->data);
-			if (!res2 ||
-				PQresultStatus(res2) != PGRES_TUPLES_OK)
-			{
-				write_msg(NULL, "query to obtain check constraints failed: %s", PQerrorMessage(g_conn));
-				exit_nicely();
-			}
-			ntups2 = PQntuples(res2);
-			if (ntups2 > tblinfo[i].ncheck)
-			{
-				write_msg(NULL, "expected %d check constraints on table \"%s\" but found %d\n",
-						  tblinfo[i].ncheck, tblinfo[i].relname, ntups2);
-				write_msg(NULL, "(The system catalogs might be corrupted.)\n");
-				exit_nicely();
-			}
+	destroyPQExpBuffer(query);
 
-			/*
-			 * Set ncheck to the number of *non-inherited* CHECK
-			 * constraints
-			 */
-			tblinfo[i].ncheck = ntups2;
+	return agginfo;
+}
 
-			i_rcname = PQfnumber(res2, "rcname");
-			i_rcsrc = PQfnumber(res2, "rcsrc");
-			tblinfo[i].check_expr = (char **) malloc(ntups2 * sizeof(char *));
-			for (i2 = 0; i2 < ntups2; i2++)
-			{
-				const char *name = PQgetvalue(res2, i2, i_rcname);
-				const char *expr = PQgetvalue(res2, i2, i_rcsrc);
+/*
+ * getFuncs:
+ *	  read all the user-defined functions in the system catalogs and
+ * return them in the FuncInfo* structure
+ *
+ * numFuncs is set to the number of functions read in
+ */
+FuncInfo *
+getFuncs(int *numFuncs)
+{
+	PGresult   *res;
+	int			ntups;
+	int			i;
+	PQExpBuffer query = createPQExpBuffer();
+	FuncInfo   *finfo;
 
-				resetPQExpBuffer(query);
-				if (name[0] != '$')
-				{
-					appendPQExpBuffer(query, "CONSTRAINT %s ",
-									  fmtId(name, force_quotes));
-				}
-				appendPQExpBuffer(query, "CHECK (%s)", expr);
-				tblinfo[i].check_expr[i2] = strdup(query->data);
-			}
-			PQclear(res2);
-		}
-		else
-			tblinfo[i].check_expr = NULL;
+	int			i_oid;
+	int			i_proname;
+	int			i_pronamespace;
+	int			i_usename;
+	int			i_prolang;
+	int			i_pronargs;
+	int			i_proargtypes;
+	int			i_prorettype;
 
-		/* Get primary key */
-		if (tblinfo[i].hasindex)
-		{
-			PGresult   *res2;
+	/* Make sure we are in proper schema */
+	selectSourceSchema("pg_catalog");
 
-			resetPQExpBuffer(query);
-			appendPQExpBuffer(query,
-							  "SELECT indexrelid FROM pg_index i WHERE i.indisprimary AND i.indrelid = '%s'::oid ",
-							  tblinfo[i].oid);
-			res2 = PQexec(g_conn, query->data);
-			if (!res2 || PQresultStatus(res2) != PGRES_TUPLES_OK)
-			{
-				write_msg(NULL, "query to obtain primary key of table \"%s\" failed: %s",
-						  tblinfo[i].relname, PQerrorMessage(g_conn));
-				exit_nicely();
-			}
+	/* find all user-defined funcs */
 
-			if (PQntuples(res2) > 1)
-			{
-				write_msg(NULL, "query to obtain primary key of table \"%s\" produced more than one result\n",
-						  tblinfo[i].relname);
-				exit_nicely();
-			}
+	if (g_fout->remoteVersion >= 70300)
+	{
+		appendPQExpBuffer(query,
+						  "SELECT pg_proc.oid, proname, prolang, "
+						  "pronargs, proargtypes, prorettype, "
+						  "pronamespace, "
+						  "(select usename from pg_user where proowner = usesysid) as usename "
+						  "FROM pg_proc "
+						  "WHERE NOT proisagg "
+						  "AND pronamespace != "
+						  "(select oid from pg_namespace where nspname = 'pg_catalog')");
+	}
+	else
+	{
+		appendPQExpBuffer(query,
+						  "SELECT pg_proc.oid, proname, prolang, "
+						  "pronargs, proargtypes, prorettype, "
+						  "0::oid as pronamespace, "
+						  "(select usename from pg_user where proowner = usesysid) as usename "
+						  "FROM pg_proc "
+						  "where pg_proc.oid > '%u'::oid",
+						  g_last_builtin_oid);
+	}
 
-			if (PQntuples(res2) == 1)
-				tblinfo[i].pkIndexOid = strdup(PQgetvalue(res2, 0, 0));
-			else
-				tblinfo[i].pkIndexOid = NULL;
+	res = PQexec(g_conn, query->data);
+	if (!res ||
+		PQresultStatus(res) != PGRES_TUPLES_OK)
+	{
+		write_msg(NULL, "query to obtain list of functions failed: %s",
+				  PQerrorMessage(g_conn));
+		exit_nicely();
+	}
 
-		}
-		else
-			tblinfo[i].pkIndexOid = NULL;
+	ntups = PQntuples(res);
 
-		/* Get primary key name (if primary key exist) */
-		if (tblinfo[i].pkIndexOid != NULL)
-		{
-			PGresult   *res2;
-			int			n;
+	*numFuncs = ntups;
 
-			resetPQExpBuffer(query);
-			appendPQExpBuffer(query,
-							  "SELECT relname FROM pg_class "
-							  "WHERE oid = '%s'::oid",
-							  tblinfo[i].pkIndexOid);
+	finfo = (FuncInfo *) malloc(ntups * sizeof(FuncInfo));
 
-			res2 = PQexec(g_conn, query->data);
-			if (!res2 || PQresultStatus(res2) != PGRES_TUPLES_OK)
-			{
-				write_msg(NULL, "query to obtain name of primary key of table \"%s\" failed: %s",
-						  tblinfo[i].relname, PQerrorMessage(g_conn));
-				exit_nicely();
-			}
+	memset((char *) finfo, 0, ntups * sizeof(FuncInfo));
 
-			n = PQntuples(res2);
-			if (n != 1)
-			{
-				if (n == 0)
-					write_msg(NULL, "query to obtain name of primary key of table \"%s\" returned no rows\n",
-							  tblinfo[i].relname);
-				else
-					write_msg(NULL, "query to obtain name of primary key of table \"%s\" returned %d rows\n",
-							  tblinfo[i].relname, n);
-				exit_nicely();
-			}
+	i_oid = PQfnumber(res, "oid");
+	i_proname = PQfnumber(res, "proname");
+	i_pronamespace = PQfnumber(res, "pronamespace");
+	i_usename = PQfnumber(res, "usename");
+	i_prolang = PQfnumber(res, "prolang");
+	i_pronargs = PQfnumber(res, "pronargs");
+	i_proargtypes = PQfnumber(res, "proargtypes");
+	i_prorettype = PQfnumber(res, "prorettype");
 
-			tblinfo[i].primary_key_name =
-				strdup(fmtId(PQgetvalue(res2, 0, 0), force_quotes));
-			if (tblinfo[i].primary_key_name == NULL)
-			{
-				write_msg(NULL, "out of memory\n");
-				exit_nicely();
-			}
-		}
+	for (i = 0; i < ntups; i++)
+	{
+		finfo[i].oid = strdup(PQgetvalue(res, i, i_oid));
+		finfo[i].proname = strdup(PQgetvalue(res, i, i_proname));
+		finfo[i].pronamespace = findNamespace(PQgetvalue(res, i, i_pronamespace),
+											  finfo[i].oid);
+		finfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+		finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
+		finfo[i].prorettype = strdup(PQgetvalue(res, i, i_prorettype));
+		finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
+		if (finfo[i].nargs == 0)
+			finfo[i].argtypes = NULL;
 		else
-			tblinfo[i].primary_key_name = NULL;
-
-		/* Get Triggers */
-		if (tblinfo[i].ntrig > 0)
 		{
-			PGresult   *res2;
-			int			i_tgoid,
-						i_tgname,
-						i_tgfoid,
-						i_tgtype,
-						i_tgnargs,
-						i_tgargs,
-						i_tgisconstraint,
-						i_tgconstrname,
-						i_tgdeferrable,
-						i_tgconstrrelid,
-						i_tgconstrrelname,
-						i_tginitdeferred;
-			int			ntups2;
-			int			i2;
-
-			if (g_verbose)
-				write_msg(NULL, "finding triggers for table %s\n", tblinfo[i].relname);
+			finfo[i].argtypes = malloc(finfo[i].nargs * sizeof(finfo[i].argtypes[0]));
+			parseNumericArray(PQgetvalue(res, i, i_proargtypes),
+							  finfo[i].argtypes,
+							  finfo[i].nargs);
+		}
 
-			resetPQExpBuffer(query);
-			appendPQExpBuffer(query,
-					   "SELECT tgname, tgfoid, tgtype, tgnargs, tgargs, "
-						   "tgisconstraint, tgconstrname, tgdeferrable, "
-							  "tgconstrrelid, tginitdeferred, oid, "
-			  "(select relname from pg_class where oid = tgconstrrelid) "
-							  "		as tgconstrrelname "
-							  "from pg_trigger "
-							  "where tgrelid = '%s'::oid ",
-							  tblinfo[i].oid);
-			res2 = PQexec(g_conn, query->data);
-			if (!res2 ||
-				PQresultStatus(res2) != PGRES_TUPLES_OK)
-			{
-				write_msg(NULL, "query to obtain list of triggers failed: %s", PQerrorMessage(g_conn));
-				exit_nicely();
-			}
-			ntups2 = PQntuples(res2);
-			if (ntups2 != tblinfo[i].ntrig)
-			{
-				write_msg(NULL, "expected %d triggers on table \"%s\" but found %d\n",
-						  tblinfo[i].ntrig, tblinfo[i].relname, ntups2);
-				exit_nicely();
-			}
-			i_tgname = PQfnumber(res2, "tgname");
-			i_tgfoid = PQfnumber(res2, "tgfoid");
-			i_tgtype = PQfnumber(res2, "tgtype");
-			i_tgnargs = PQfnumber(res2, "tgnargs");
-			i_tgargs = PQfnumber(res2, "tgargs");
-			i_tgoid = PQfnumber(res2, "oid");
-			i_tgisconstraint = PQfnumber(res2, "tgisconstraint");
-			i_tgconstrname = PQfnumber(res2, "tgconstrname");
-			i_tgdeferrable = PQfnumber(res2, "tgdeferrable");
-			i_tgconstrrelid = PQfnumber(res2, "tgconstrrelid");
-			i_tgconstrrelname = PQfnumber(res2, "tgconstrrelname");
-			i_tginitdeferred = PQfnumber(res2, "tginitdeferred");
-
-			tblinfo[i].triggers = (TrigInfo *) malloc(ntups2 * sizeof(TrigInfo));
-			resetPQExpBuffer(query);
-			for (i2 = 0; i2 < ntups2; i2++)
-			{
-				const char *tgfuncoid = PQgetvalue(res2, i2, i_tgfoid);
-				char	   *tgfunc = NULL;
-				int2		tgtype = atoi(PQgetvalue(res2, i2, i_tgtype));
-				int			tgnargs = atoi(PQgetvalue(res2, i2, i_tgnargs));
-				const char *tgargs = PQgetvalue(res2, i2, i_tgargs);
-				int			tgisconstraint;
-				int			tgdeferrable;
-				int			tginitdeferred;
-				char	   *tgconstrrelid;
-				char	   *tgname;
-				const char *p;
-				int			findx;
-
-				tgname = PQgetvalue(res2, i2, i_tgname);
-
-				if (strcmp(PQgetvalue(res2, i2, i_tgisconstraint), "f") == 0)
-					tgisconstraint = 0;
-				else
-					tgisconstraint = 1;
+		finfo[i].dumped = false;
 
-				if (strcmp(PQgetvalue(res2, i2, i_tgdeferrable), "f") == 0)
-					tgdeferrable = 0;
-				else
-					tgdeferrable = 1;
+		if (strlen(finfo[i].usename) == 0)
+			write_msg(NULL, "WARNING: owner of function \"%s\" appears to be invalid\n",
+					  finfo[i].proname);
+	}
 
-				if (strcmp(PQgetvalue(res2, i2, i_tginitdeferred), "f") == 0)
-					tginitdeferred = 0;
-				else
-					tginitdeferred = 1;
+	PQclear(res);
 
-				for (findx = 0; findx < numFuncs; findx++)
-				{
-					if (strcmp(finfo[findx].oid, tgfuncoid) == 0 &&
-						finfo[findx].nargs == 0 &&
-						strcmp(finfo[findx].prorettype, "0") == 0)
-						break;
-				}
+	destroyPQExpBuffer(query);
 
-				if (findx == numFuncs)
-				{
-					PGresult   *r;
-					int			numFuncs;
+	return finfo;
+}
 
-					/*
-					 * the funcname is an oid which we use to find the
-					 * name of the pg_proc.  We need to do this because
-					 * getFuncs() only reads in the user-defined funcs not
-					 * all the funcs.  We might not find what we want by
-					 * looking in FuncInfo*
-					 */
-					resetPQExpBuffer(query);
-					appendPQExpBuffer(query,
-									  "SELECT proname from pg_proc "
-									  "where pg_proc.oid = '%s'::oid",
-									  tgfuncoid);
-
-					r = PQexec(g_conn, query->data);
-					if (!r || PQresultStatus(r) != PGRES_TUPLES_OK)
-					{
-						write_msg(NULL, "query to obtain procedure name for trigger \"%s\" failed: %s",
-								  tgname, PQerrorMessage(g_conn));
-						exit_nicely();
-					}
+/*
+ * getTables
+ *	  read all the user-defined tables (no indexes, no catalogs)
+ * in the system catalogs return them in the TableInfo* structure
+ *
+ * numTables is set to the number of tables read in
+ */
+TableInfo *
+getTables(int *numTables)
+{
+	PGresult   *res;
+	int			ntups;
+	int			i;
+	PQExpBuffer query = createPQExpBuffer();
+	PQExpBuffer delqry = createPQExpBuffer();
+	PQExpBuffer lockquery = createPQExpBuffer();
+	TableInfo  *tblinfo;
 
-					/* Sanity: Check we got only one tuple */
-					numFuncs = PQntuples(r);
-					if (numFuncs != 1)
-					{
-						if (numFuncs == 0)
-							write_msg(NULL, "query to obtain procedure name for trigger \"%s\" (procedure OID %s) returned no rows\n",
-									  tgname, tgfuncoid);
-						else
-							write_msg(NULL, "query to obtain procedure name for trigger \"%s\" (procedure OID %s) returned %d rows\n",
-									  tgname, tgfuncoid, numFuncs);
-						exit_nicely();
-					}
+	int			i_reloid;
+	int			i_relname;
+	int			i_relnamespace;
+	int			i_relkind;
+	int			i_relacl;
+	int			i_usename;
+	int			i_relchecks;
+	int			i_reltriggers;
+	int			i_relhasindex;
+	int			i_relhasrules;
+	int			i_relhasoids;
 
-					tgfunc = strdup(PQgetvalue(r, 0, PQfnumber(r, "proname")));
-					PQclear(r);
-				}
-				else
-					tgfunc = strdup(finfo[findx].proname);
+	/* Make sure we are in proper schema */
+	selectSourceSchema("pg_catalog");
 
-				appendPQExpBuffer(delqry, "DROP TRIGGER %s ", fmtId(tgname, force_quotes));
-				appendPQExpBuffer(delqry, "ON %s;\n",
-								fmtId(tblinfo[i].relname, force_quotes));
+	/*
+	 * Find all the tables (including views and sequences).
+	 *
+	 * We include system catalogs, so that we can work if a user table
+	 * is defined to inherit from a system catalog (pretty weird, but...)
+	 *
+	 * We ignore tables that are not type 'r' (ordinary relation) or 'S'
+	 * (sequence) or 'v' (view).
+	 *
+	 * Note: in this phase we should collect only a minimal amount of
+	 * information about each table, basically just enough to decide if
+	 * it is interesting.
+	 */
 
-				resetPQExpBuffer(query);
-				if (tgisconstraint)
-				{
-					appendPQExpBuffer(query, "CREATE CONSTRAINT TRIGGER ");
-					appendPQExpBuffer(query, fmtId(PQgetvalue(res2, i2, i_tgconstrname), force_quotes));
-				}
-				else
-				{
-					appendPQExpBuffer(query, "CREATE TRIGGER ");
-					appendPQExpBuffer(query, fmtId(tgname, force_quotes));
-				}
-				appendPQExpBufferChar(query, ' ');
-				/* Trigger type */
-				findx = 0;
-				if (TRIGGER_FOR_BEFORE(tgtype))
-					appendPQExpBuffer(query, "BEFORE");
-				else
-					appendPQExpBuffer(query, "AFTER");
-				if (TRIGGER_FOR_INSERT(tgtype))
-				{
-					appendPQExpBuffer(query, " INSERT");
-					findx++;
-				}
-				if (TRIGGER_FOR_DELETE(tgtype))
-				{
-					if (findx > 0)
-						appendPQExpBuffer(query, " OR DELETE");
-					else
-						appendPQExpBuffer(query, " DELETE");
-					findx++;
-				}
-				if (TRIGGER_FOR_UPDATE(tgtype))
-				{
-					if (findx > 0)
-						appendPQExpBuffer(query, " OR UPDATE");
-					else
-						appendPQExpBuffer(query, " UPDATE");
-				}
-				appendPQExpBuffer(query, " ON %s ", fmtId(tblinfo[i].relname, force_quotes));
+	if (g_fout->remoteVersion >= 70300)
+	{
+		appendPQExpBuffer(query,
+						  "SELECT pg_class.oid, relname, relacl, relkind, "
+						  "relnamespace, "
 
-				if (tgisconstraint)
-				{
-					tgconstrrelid = PQgetvalue(res2, i2, i_tgconstrrelid);
+						  "(select usename from pg_user where relowner = usesysid) as usename, "
+						  "relchecks, reltriggers, "
+						  "relhasindex, relhasrules, relhasoids "
+						  "from pg_class "
+						  "where relkind in ('%c', '%c', '%c') "
+						  "order by oid",
+						  RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
+	}
+	else if (g_fout->remoteVersion >= 70200)
+	{
+		appendPQExpBuffer(query,
+						  "SELECT pg_class.oid, relname, relacl, relkind, "
+						  "0::oid as relnamespace, "
+						  "(select usename from pg_user where relowner = usesysid) as usename, "
+						  "relchecks, reltriggers, "
+						  "relhasindex, relhasrules, relhasoids "
+						  "from pg_class "
+						  "where relkind in ('%c', '%c', '%c') "
+						  "order by oid",
+					   RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
+	}
+	else if (g_fout->remoteVersion >= 70100)
+	{
+		/* all tables have oids in 7.1 */
+		appendPQExpBuffer(query,
+						"SELECT pg_class.oid, relname, relacl, relkind, "
+						  "0::oid as relnamespace, "
+						  "(select usename from pg_user where relowner = usesysid) as usename, "
+						  "relchecks, reltriggers, "
+						  "relhasindex, relhasrules, 't'::bool as relhasoids "
+						  "from pg_class "
+						  "where relkind in ('%c', '%c', '%c') "
+						  "order by oid",
+					   RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
+	}
+	else
+	{
+		/*
+		 * Before 7.1, view relkind was not set to 'v', so we must check
+		 * if we have a view by looking for a rule in pg_rewrite.
+		 */
+		appendPQExpBuffer(query,
+						  "SELECT c.oid, relname, relacl, "
+						  "CASE WHEN relhasrules and relkind = 'r' "
+				  "  and EXISTS(SELECT rulename FROM pg_rewrite r WHERE "
+				  "             r.ev_class = c.oid AND r.ev_type = '1') "
+						  "THEN '%c'::\"char\" "
+						  "ELSE relkind END AS relkind,"
+						  "0::oid as relnamespace, "
+						  "(select usename from pg_user where relowner = usesysid) as usename, "
+						  "relchecks, reltriggers, "
+						  "relhasindex, relhasrules, 't'::bool as relhasoids "
+						  "from pg_class c "
+						  "where relkind in ('%c', '%c') "
+						  "order by oid",
+						  RELKIND_VIEW,
+						  RELKIND_RELATION, RELKIND_SEQUENCE);
+	}
 
-					if (strcmp(tgconstrrelid, "0") != 0)
-					{
+	res = PQexec(g_conn, query->data);
+	if (!res ||
+		PQresultStatus(res) != PGRES_TUPLES_OK)
+	{
+		write_msg(NULL, "query to obtain list of tables failed: %s",
+				  PQerrorMessage(g_conn));
+		exit_nicely();
+	}
 
-						if (PQgetisnull(res2, i2, i_tgconstrrelname))
-						{
-							write_msg(NULL, "query produced NULL referenced table name for foreign key trigger \"%s\" on table \"%s\" (oid of table: %s)\n",
-							  tgname, tblinfo[i].relname, tgconstrrelid);
-							exit_nicely();
-						}
+	ntups = PQntuples(res);
 
-						appendPQExpBuffer(query, " FROM %s",
-										  fmtId(PQgetvalue(res2, i2, i_tgconstrrelname), force_quotes));
-					}
-					if (!tgdeferrable)
-						appendPQExpBuffer(query, " NOT");
-					appendPQExpBuffer(query, " DEFERRABLE INITIALLY ");
-					if (tginitdeferred)
-						appendPQExpBuffer(query, "DEFERRED");
-					else
-						appendPQExpBuffer(query, "IMMEDIATE");
+	*numTables = ntups;
 
-				}
+	/*
+	 * Extract data from result and lock dumpable tables.  We do the
+	 * locking before anything else, to minimize the window wherein a
+	 * table could disappear under us.
+	 *
+	 * Note that we have to save info about all tables here, even when
+	 * dumping only one, because we don't yet know which tables might be
+	 * inheritance ancestors of the target table.
+	 */
+	tblinfo = (TableInfo *) malloc(ntups * sizeof(TableInfo));
+	memset(tblinfo, 0, ntups * sizeof(TableInfo));
 
-				appendPQExpBuffer(query, " FOR EACH ROW");
-				appendPQExpBuffer(query, " EXECUTE PROCEDURE %s (",
-								  fmtId(tgfunc, force_quotes));
-				for (findx = 0; findx < tgnargs; findx++)
-				{
-					const char *s;
+	i_reloid = PQfnumber(res, "oid");
+	i_relname = PQfnumber(res, "relname");
+	i_relnamespace = PQfnumber(res, "relnamespace");
+	i_relacl = PQfnumber(res, "relacl");
+	i_relkind = PQfnumber(res, "relkind");
+	i_usename = PQfnumber(res, "usename");
+	i_relchecks = PQfnumber(res, "relchecks");
+	i_reltriggers = PQfnumber(res, "reltriggers");
+	i_relhasindex = PQfnumber(res, "relhasindex");
+	i_relhasrules = PQfnumber(res, "relhasrules");
+	i_relhasoids = PQfnumber(res, "relhasoids");
 
-					for (p = tgargs;;)
-					{
-						p = strchr(p, '\\');
-						if (p == NULL)
-						{
-							write_msg(NULL, "bad argument string (%s) for trigger \"%s\" on table \"%s\"\n",
-									  PQgetvalue(res2, i2, i_tgargs),
-									  tgname,
-									  tblinfo[i].relname);
-							exit_nicely();
-						}
-						p++;
-						if (*p == '\\')
-						{
-							p++;
-							continue;
-						}
-						if (p[0] == '0' && p[1] == '0' && p[2] == '0')
-							break;
-					}
-					p--;
-					appendPQExpBufferChar(query, '\'');
-					for (s = tgargs; s < p;)
-					{
-						if (*s == '\'')
-							appendPQExpBufferChar(query, '\\');
-						appendPQExpBufferChar(query, *s++);
-					}
-					appendPQExpBufferChar(query, '\'');
-					appendPQExpBuffer(query, (findx < tgnargs - 1) ? ", " : "");
-					tgargs = p + 4;
-				}
-				appendPQExpBuffer(query, ");\n");
+	for (i = 0; i < ntups; i++)
+	{
+		tblinfo[i].oid = strdup(PQgetvalue(res, i, i_reloid));
+		tblinfo[i].relname = strdup(PQgetvalue(res, i, i_relname));
+		tblinfo[i].relnamespace = findNamespace(PQgetvalue(res, i, i_relnamespace),
+												tblinfo[i].oid);
+		tblinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+		tblinfo[i].relacl = strdup(PQgetvalue(res, i, i_relacl));
+		tblinfo[i].relkind = *(PQgetvalue(res, i, i_relkind));
+		tblinfo[i].hasindex = (strcmp(PQgetvalue(res, i, i_relhasindex), "t") == 0);
+		tblinfo[i].hasrules = (strcmp(PQgetvalue(res, i, i_relhasrules), "t") == 0);
+		tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
+		tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
+		tblinfo[i].ntrig = atoi(PQgetvalue(res, i, i_reltriggers));
 
-				tblinfo[i].triggers[i2].tgsrc = strdup(query->data);
+		/* other fields were zeroed above */
 
-				/*** Initialize trcomments and troids ***/
+		/*
+		 * Decide whether we want to dump this table.
+		 */
+		selectDumpableTable(&tblinfo[i]);
+		tblinfo[i].interesting = tblinfo[i].dump;
 
-				resetPQExpBuffer(query);
-				appendPQExpBuffer(query, "TRIGGER %s ",
-								  fmtId(tgname, force_quotes));
-				appendPQExpBuffer(query, "ON %s",
-								fmtId(tblinfo[i].relname, force_quotes));
-				tblinfo[i].triggers[i2].tgcomment = strdup(query->data);
-				tblinfo[i].triggers[i2].oid = strdup(PQgetvalue(res2, i2, i_tgoid));
-				tblinfo[i].triggers[i2].tgname = strdup(fmtId(tgname, false));
-				tblinfo[i].triggers[i2].tgdel = strdup(delqry->data);
+		/*
+		 * Read-lock target tables to make sure they aren't DROPPED or
+		 * altered in schema before we get around to dumping them.
+		 *
+		 * Note that we don't explicitly lock parents of the target tables;
+		 * we assume our lock on the child is enough to prevent schema
+		 * alterations to parent tables.
+		 *
+		 * NOTE: it'd be kinda nice to lock views and sequences too, not only
+		 * plain tables, but the backend doesn't presently allow that.
+		 */
+		if (tblinfo[i].dump && tblinfo[i].relkind == RELKIND_RELATION)
+		{
+			PGresult   *lres;
 
-				if (tgfunc)
-					free(tgfunc);
+			resetPQExpBuffer(lockquery);
+			appendPQExpBuffer(lockquery,
+							  "LOCK TABLE %s IN ACCESS SHARE MODE",
+							  fmtQualifiedId(tblinfo[i].relnamespace->nspname,
+											 tblinfo[i].relname));
+			lres = PQexec(g_conn, lockquery->data);
+			if (!lres || PQresultStatus(lres) != PGRES_COMMAND_OK)
+			{
+				write_msg(NULL, "Attempt to lock table \"%s\" failed.  %s",
+						  tblinfo[i].relname, PQerrorMessage(g_conn));
+				exit_nicely();
 			}
-			PQclear(res2);
+			PQclear(lres);
 		}
-		else
-			tblinfo[i].triggers = NULL;
 
+		/* Emit notice if join for owner failed */
+		if (strlen(tblinfo[i].usename) == 0)
+			write_msg(NULL, "WARNING: owner of table \"%s\" appears to be invalid\n",
+					  tblinfo[i].relname);
 	}
 
+	PQclear(res);
 	destroyPQExpBuffer(query);
 	destroyPQExpBuffer(delqry);
 	destroyPQExpBuffer(lockquery);
@@ -2783,7 +2158,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs, const char *tablename)
  *	  read all the inheritance information
  * from the system catalogs return them in the InhInfo* structure
  *
- * numInherits is set to the number of tables read in
+ * numInherits is set to the number of pairs read in
  */
 InhInfo *
 getInherits(int *numInherits)
@@ -2797,6 +2172,9 @@ getInherits(int *numInherits)
 	int			i_inhrelid;
 	int			i_inhparent;
 
+	/* Make sure we are in proper schema */
+	selectSourceSchema("pg_catalog");
+
 	/* find all the inheritance information */
 
 	appendPQExpBuffer(query, "SELECT inhrelid, inhparent from pg_inherits");
@@ -2834,7 +2212,7 @@ getInherits(int *numInherits)
 
 /*
  * getTableAttrs -
- *	  for each table in tblinfo, read its attributes types and names
+ *	  for each interesting table, read its attributes types and names
  *
  * this is implemented in a very inefficient way right now, looping
  * through the tblinfo and doing a join per table to find the attrs and their
@@ -2849,25 +2227,39 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 				j;
 	PQExpBuffer q = createPQExpBuffer();
 	int			i_attname;
-	int			i_typname;
+	int			i_atttypname;
 	int			i_atttypmod;
 	int			i_attnotnull;
 	int			i_atthasdef;
-	int			i_atttypedefn;
 	PGresult   *res;
 	int			ntups;
+	bool		hasdefaults;
 
 	for (i = 0; i < numTables; i++)
 	{
+		/* Don't bother to collect info for sequences */
 		if (tblinfo[i].relkind == RELKIND_SEQUENCE)
 			continue;
 
+		/* Don't bother with uninteresting tables, either */
+		if (!tblinfo[i].interesting)
+			continue;
+
+		/*
+		 * Make sure we are in proper schema for this table; this allows
+		 * correct retrieval of formatted type names and default exprs
+		 */
+		selectSourceSchema(tblinfo[i].relnamespace->nspname);
+
 		/* find all the user attributes and their types */
-		/* we must read the attribute names in attribute number order! */
 
 		/*
+		 * we must read the attribute names in attribute number order!
 		 * because we will use the attnum to index into the attnames array
-		 * later
+		 * later.  We actually ask to order by "attrelid, attnum" because
+		 * (at least up to 7.3) the planner is not smart enough to realize
+		 * it needn't re-sort the output of an indexscan on
+		 * pg_attribute_relid_attnum_index.
 		 */
 		if (g_verbose)
 			write_msg(NULL, "finding the columns and types for table %s\n",
@@ -2875,33 +2267,27 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 
 		resetPQExpBuffer(q);
 
-		if (g_fout->remoteVersion < 70100)
+		if (g_fout->remoteVersion >= 70100)
 		{
-			/* Fake the LOJ below */
-			appendPQExpBuffer(q,
-				 "  SELECT a.attnum, a.attname, t.typname, a.atttypmod, "
-				"        a.attnotnull, a.atthasdef, NULL as atttypedefn "
-							  "    from pg_attribute a, pg_type t "
-							  "    where a.attrelid = '%s'::oid "
-							  "        and a.attnum > 0 "
-							  "        and a.atttypid = t.oid "
-							  " UNION ALL SELECT a.attnum, a.attname, NULL as typname, a.atttypmod, "
-				"        a.attnotnull, a.atthasdef, NULL as atttypedefn "
-							  "    from pg_attribute a "
-							  "    where a.attrelid = '%s'::oid "
-							  "        and a.attnum > 0 "
-							  "        and Not Exists(Select * From pg_type t where a.atttypid = t.oid)"
-							  "    order by attnum",
-							  tblinfo[i].oid, tblinfo[i].oid);
-
+			appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, "
+							  "attnotnull, atthasdef, "
+							  "format_type(atttypid,atttypmod) as atttypname "
+							  "from pg_attribute a "
+							  "where attrelid = '%s'::oid "
+							  "and attnum > 0::int2 "
+							  "order by attrelid, attnum",
+							  tblinfo[i].oid);
 		}
 		else
 		{
-			appendPQExpBuffer(q, "SELECT a.attnum, a.attname, t.typname, a.atttypmod, "
-							  "a.attnotnull, a.atthasdef, format_type(a.atttypid, a.atttypmod) as atttypedefn "
-							  "from pg_attribute a LEFT OUTER JOIN pg_type t ON a.atttypid = t.oid "
-							  "where a.attrelid = '%s'::oid "
-							  "and a.attnum > 0 order by attnum",
+			/* format_type not available before 7.1 */
+			appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, "
+							  "attnotnull, atthasdef, "
+							  "(select typname from pg_type where oid = atttypid) as atttypname "
+							  "from pg_attribute a "
+							  "where attrelid = '%s'::oid "
+							  "and attnum > 0::int2 "
+							  "order by attrelid, attnum",
 							  tblinfo[i].oid);
 		}
 
@@ -2916,82 +2302,87 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 		ntups = PQntuples(res);
 
 		i_attname = PQfnumber(res, "attname");
-		i_typname = PQfnumber(res, "typname");
+		i_atttypname = PQfnumber(res, "atttypname");
 		i_atttypmod = PQfnumber(res, "atttypmod");
 		i_attnotnull = PQfnumber(res, "attnotnull");
 		i_atthasdef = PQfnumber(res, "atthasdef");
-		i_atttypedefn = PQfnumber(res, "atttypedefn");
 
 		tblinfo[i].numatts = ntups;
 		tblinfo[i].attnames = (char **) malloc(ntups * sizeof(char *));
-		tblinfo[i].atttypedefns = (char **) malloc(ntups * sizeof(char *));
-		tblinfo[i].typnames = (char **) malloc(ntups * sizeof(char *));
+		tblinfo[i].atttypnames = (char **) malloc(ntups * sizeof(char *));
 		tblinfo[i].atttypmod = (int *) malloc(ntups * sizeof(int));
-		tblinfo[i].inhAttrs = (int *) malloc(ntups * sizeof(int));
-		tblinfo[i].inhAttrDef = (int *) malloc(ntups * sizeof(int));
-		tblinfo[i].inhNotNull = (int *) malloc(ntups * sizeof(int));
 		tblinfo[i].notnull = (bool *) malloc(ntups * sizeof(bool));
 		tblinfo[i].adef_expr = (char **) malloc(ntups * sizeof(char *));
-		tblinfo[i].parentRels = NULL;
-		tblinfo[i].numParents = 0;
+		tblinfo[i].inhAttrs = (bool *) malloc(ntups * sizeof(bool));
+		tblinfo[i].inhAttrDef = (bool *) malloc(ntups * sizeof(bool));
+		tblinfo[i].inhNotNull = (bool *) malloc(ntups * sizeof(bool));
+		hasdefaults = false;
+
 		for (j = 0; j < ntups; j++)
 		{
-			/* Sanity check on LOJ */
-			if (PQgetisnull(res, j, i_typname))
-			{
-				write_msg(NULL, "query produced NULL name for data type of column %d of table %s\n",
-						  j + 1, tblinfo[i].relname);
-				exit_nicely();
-			}
-
 			tblinfo[i].attnames[j] = strdup(PQgetvalue(res, j, i_attname));
-			tblinfo[i].atttypedefns[j] = strdup(PQgetvalue(res, j, i_atttypedefn));
-			tblinfo[i].typnames[j] = strdup(PQgetvalue(res, j, i_typname));
+			tblinfo[i].atttypnames[j] = strdup(PQgetvalue(res, j, i_atttypname));
 			tblinfo[i].atttypmod[j] = atoi(PQgetvalue(res, j, i_atttypmod));
-			tblinfo[i].inhAttrs[j] = 0; /* this flag is set in
-										 * flagInhAttrs() */
-			tblinfo[i].inhAttrDef[j] = 0;
-			tblinfo[i].inhNotNull[j] = 0;
-
-			tblinfo[i].notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't') ? true : false;
+			tblinfo[i].notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't');
+			tblinfo[i].adef_expr[j] = NULL;	/* fix below */
 			if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
-			{
-				PGresult   *res2;
-				int			numAttr;
+				hasdefaults = true;
+			/* these flags will be set in flagInhAttrs() */
+			tblinfo[i].inhAttrs[j] = false;
+			tblinfo[i].inhAttrDef[j] = false;
+			tblinfo[i].inhNotNull[j] = false;
+		}
 
-				if (g_verbose)
-					write_msg(NULL, "finding DEFAULT expression for column %s\n",
-							  tblinfo[i].attnames[j]);
+		PQclear(res);
 
-				resetPQExpBuffer(q);
-				appendPQExpBuffer(q, "SELECT adsrc from pg_attrdef "
-							 "where adrelid = '%s'::oid and adnum = %d ",
-								  tblinfo[i].oid, j + 1);
-				res2 = PQexec(g_conn, q->data);
-				if (!res2 ||
-					PQresultStatus(res2) != PGRES_TUPLES_OK)
-				{
-					write_msg(NULL, "query to get column default value failed: %s",
-							  PQerrorMessage(g_conn));
-					exit_nicely();
-				}
+		if (hasdefaults)
+		{
+			int			numDefaults;
+
+			if (g_verbose)
+				write_msg(NULL, "finding DEFAULT expressions for table %s\n",
+						  tblinfo[i].relname);
+
+			resetPQExpBuffer(q);
+			if (g_fout->remoteVersion >= 70200)
+			{
+				appendPQExpBuffer(q, "SELECT adnum, "
+								  "pg_get_expr(adbin, adrelid) AS adsrc "
+								  "FROM pg_attrdef "
+								  "WHERE adrelid = '%s'::oid",
+								  tblinfo[i].oid);
+			}
+			else
+			{
+				/* no pg_get_expr, so must rely on adsrc */
+				appendPQExpBuffer(q, "SELECT adnum, adsrc FROM pg_attrdef "
+								  "WHERE adrelid = '%s'::oid",
+								  tblinfo[i].oid);
+			}
+			res = PQexec(g_conn, q->data);
+			if (!res ||
+				PQresultStatus(res) != PGRES_TUPLES_OK)
+			{
+				write_msg(NULL, "query to get column default values failed: %s",
+						  PQerrorMessage(g_conn));
+				exit_nicely();
+			}
 
-				/* Sanity: Check we got only one tuple */
-				numAttr = PQntuples(res2);
-				if (numAttr != 1)
+			numDefaults = PQntuples(res);
+			for (j = 0; j < numDefaults; j++)
+			{
+				int		adnum = atoi(PQgetvalue(res, j, 0));
+
+				if (adnum <= 0 || adnum > ntups)
 				{
-					write_msg(NULL, "query to get default value for column \"%s\" returned %d rows; expected 1\n",
-							  tblinfo[i].attnames[j], numAttr);
+					write_msg(NULL, "bogus adnum value %d for table %s\n",
+							  adnum, tblinfo[i].relname);
 					exit_nicely();
 				}
-
-				tblinfo[i].adef_expr[j] = strdup(PQgetvalue(res2, 0, PQfnumber(res2, "adsrc")));
-				PQclear(res2);
+				tblinfo[i].adef_expr[adnum-1] = strdup(PQgetvalue(res, j, 1));
 			}
-			else
-				tblinfo[i].adef_expr[j] = NULL;
+			PQclear(res);
 		}
-		PQclear(res);
 	}
 
 	destroyPQExpBuffer(q);
@@ -2999,121 +2390,23 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 
 
 /*
- * getIndexes
- *	  read all the user-defined indexes information
- * from the system catalogs return them in the InhInfo* structure
- *
- * numIndexes is set to the number of indexes read in
- *
- *
- */
-IndInfo *
-getIndexes(int *numIndexes)
-{
-	int			i;
-	PQExpBuffer query = createPQExpBuffer();
-	PGresult   *res;
-	int			ntups;
-	IndInfo    *indinfo;
-
-	int			i_indexreloid;
-	int			i_indreloid;
-	int			i_indexrelname;
-	int			i_indrelname;
-	int			i_indexdef;
-	int			i_indisprimary;
-	int			i_indnkeys;
-	int			i_indkey;
-
-	/*
-	 * find all the user-defined indexes.
-	 *
-	 * Notice we skip indexes on system classes
-	 *
-	 * XXXX: Use LOJ
-	 */
-
-	appendPQExpBuffer(query,
-					  "SELECT i.indexrelid as indexreloid, "
-					  "i.indrelid as indreloid, "
-					  "t1.relname as indexrelname, t2.relname as indrelname, "
-					  "pg_get_indexdef(i.indexrelid) as indexdef, "
-					  "i.indisprimary, i.indkey, "
-					  "CASE WHEN i.indproc <> 0 "
-					  "  THEN (SELECT pronargs FROM pg_proc WHERE pg_proc.oid = i.indproc) "
-					  "  ELSE t1.relnatts END as indnkeys "
-					  "FROM pg_index i, pg_class t1, pg_class t2 "
-					  "WHERE t1.oid = i.indexrelid and t2.oid = i.indrelid "
-					  "and i.indexrelid > '%u'::oid "
-					  "and t2.relname !~ '^pg_' ",
-					  g_last_builtin_oid);
-
-	if (g_fout->remoteVersion < 70100)
-		appendPQExpBuffer(query, " and t2.relkind != 'l'");
-
-	res = PQexec(g_conn, query->data);
-	if (!res ||
-		PQresultStatus(res) != PGRES_TUPLES_OK)
-	{
-		write_msg(NULL, "query to obtain list of indexes failed: %s", PQerrorMessage(g_conn));
-		exit_nicely();
-	}
-
-	ntups = PQntuples(res);
-
-	*numIndexes = ntups;
-
-	indinfo = (IndInfo *) malloc(ntups * sizeof(IndInfo));
-
-	memset((char *) indinfo, 0, ntups * sizeof(IndInfo));
-
-	i_indexreloid = PQfnumber(res, "indexreloid");
-	i_indreloid = PQfnumber(res, "indreloid");
-	i_indexrelname = PQfnumber(res, "indexrelname");
-	i_indrelname = PQfnumber(res, "indrelname");
-	i_indexdef = PQfnumber(res, "indexdef");
-	i_indisprimary = PQfnumber(res, "indisprimary");
-	i_indnkeys = PQfnumber(res, "indnkeys");
-	i_indkey = PQfnumber(res, "indkey");
-
-	for (i = 0; i < ntups; i++)
-	{
-		indinfo[i].indexreloid = strdup(PQgetvalue(res, i, i_indexreloid));
-		indinfo[i].indreloid = strdup(PQgetvalue(res, i, i_indreloid));
-		indinfo[i].indexrelname = strdup(PQgetvalue(res, i, i_indexrelname));
-		indinfo[i].indrelname = strdup(PQgetvalue(res, i, i_indrelname));
-		indinfo[i].indexdef = strdup(PQgetvalue(res, i, i_indexdef));
-		indinfo[i].indisprimary = strdup(PQgetvalue(res, i, i_indisprimary));
-		indinfo[i].indnkeys = atoi(PQgetvalue(res, i, i_indnkeys));
-		indinfo[i].indkey = malloc(indinfo[i].indnkeys * sizeof(indinfo[i].indkey[0]));
-		parseNumericArray(PQgetvalue(res, i, i_indkey),
-						  indinfo[i].indkey,
-						  indinfo[i].indnkeys);
-	}
-	PQclear(res);
-
-	destroyPQExpBuffer(query);
-
-	return indinfo;
-}
-
-/*------------------------------------------------------------------
  * dumpComment --
  *
  * 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 comment-creation command, plus
- * OID, class name, and subid which are the primary key for pg_description.
+ * the namespace and owner of the object (for labeling the ArchiveEntry),
+ * plus OID, class name, and subid which are the lookup key for pg_description.
  * If a matching pg_description entry is found, it is dumped.
  * Additional dependencies can be passed for the comment, too --- this is
  * needed for VIEWs, whose comments are filed under the table OID but
  * which are dumped in order by their rule OID.
- *------------------------------------------------------------------
-*/
+ */
 
 static void
-dumpComment(Archive *fout, const char *target, const char *oid,
-			const char *classname, int subid,
+dumpComment(Archive *fout, const char *target,
+			const char *namespace, const char *owner,
+			const char *oid, const char *classname, int subid,
 			const char *((*deps)[]))
 {
 	PGresult   *res;
@@ -3124,11 +2417,24 @@ dumpComment(Archive *fout, const char *target, const char *oid,
 	if (dataOnly)
 		return;
 
+	/*
+	 * Note we do NOT change source schema here; preserve the caller's
+	 * setting, instead.
+	 */
+
 	/*** Build query to find comment ***/
 
 	query = createPQExpBuffer();
 
-	if (fout->remoteVersion >= 70200)
+	if (fout->remoteVersion >= 70300)
+	{
+		appendPQExpBuffer(query, "SELECT description FROM pg_catalog.pg_description "
+						  "WHERE objoid = '%s'::oid and classoid = "
+						  "'pg_catalog.%s'::regclass "
+						  "and objsubid = %d",
+						  oid, classname, subid);
+	}
+	else if (fout->remoteVersion >= 70200)
 	{
 		appendPQExpBuffer(query, "SELECT description FROM pg_description "
 						  "WHERE objoid = '%s'::oid and classoid = "
@@ -3163,27 +2469,140 @@ dumpComment(Archive *fout, const char *target, const char *oid,
 							PASS_LFTAB);
 		appendPQExpBuffer(query, ";\n");
 
-		ArchiveEntry(fout, oid, target, "COMMENT", deps,
-					 query->data, "" /* Del */ ,
-					 "" /* Copy */ , "" /* Owner */ , NULL, NULL);
-	}
+		ArchiveEntry(fout, oid, target, namespace, owner,
+					 "COMMENT", deps,
+					 query->data, "", NULL, NULL, NULL);
+	}
+
+	PQclear(res);
+	destroyPQExpBuffer(query);
+}
+
+/*
+ * dumpTableComment --
+ *
+ * As above, but dump comments for both the specified table (or view)
+ * and its columns.  For speed, we want to do this with only one query.
+ */
+static void
+dumpTableComment(Archive *fout, TableInfo *tbinfo,
+				 const char *reltypename,
+				 const char *((*deps)[]))
+{
+	PGresult   *res;
+	PQExpBuffer query;
+	PQExpBuffer target;
+	int			i_description;
+	int			i_objsubid;
+	int			ntups;
+	int			i;
+
+	/* Comments are SCHEMA not data */
+	if (dataOnly)
+		return;
+
+	/*
+	 * Note we do NOT change source schema here; preserve the caller's
+	 * setting, instead.
+	 */
+
+	/*** Build query to find comments ***/
+
+	query = createPQExpBuffer();
+	target = createPQExpBuffer();
+
+	if (fout->remoteVersion >= 70300)
+	{
+		appendPQExpBuffer(query, "SELECT description, objsubid FROM pg_catalog.pg_description "
+						  "WHERE objoid = '%s'::oid and classoid = "
+						  "'pg_catalog.pg_class'::regclass "
+						  "ORDER BY objoid, classoid, objsubid",
+						  tbinfo->oid);
+	}
+	else if (fout->remoteVersion >= 70200)
+	{
+		appendPQExpBuffer(query, "SELECT description, objsubid FROM pg_description "
+						  "WHERE objoid = '%s'::oid and classoid = "
+					   "(SELECT oid FROM pg_class where relname = 'pg_class') "
+						  "ORDER BY objoid, classoid, objsubid",
+						  tbinfo->oid);
+	}
+	else
+	{
+		/* Note: this will fail to find attribute comments in pre-7.2... */
+		appendPQExpBuffer(query, "SELECT description, 0 as objsubid FROM pg_description WHERE objoid = '%s'::oid", tbinfo->oid);
+	}
+
+	/*** Execute query ***/
+
+	res = PQexec(g_conn, query->data);
+	if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
+	{
+		write_msg(NULL, "query to get comments on table %s failed: %s",
+				  tbinfo->relname, PQerrorMessage(g_conn));
+		exit_nicely();
+	}
+	i_description = PQfnumber(res, "description");
+	i_objsubid = PQfnumber(res, "objsubid");
+
+	/*** If comments exist, build COMMENT ON statements ***/
+
+	ntups = PQntuples(res);
+	for (i = 0; i < ntups; i++)
+	{
+		const char *descr = PQgetvalue(res, i, i_description);
+		int objsubid = atoi(PQgetvalue(res, i, i_objsubid));
+
+		if (objsubid == 0)
+		{
+			resetPQExpBuffer(target);
+			appendPQExpBuffer(target, "%s %s", reltypename,
+							  fmtId(tbinfo->relname, force_quotes));
+
+			resetPQExpBuffer(query);
+			appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
+			formatStringLiteral(query, descr, PASS_LFTAB);
+			appendPQExpBuffer(query, ";\n");
+
+			ArchiveEntry(fout, tbinfo->oid, target->data,
+						 tbinfo->relnamespace->nspname, tbinfo->usename,
+						 "COMMENT", deps,
+						 query->data, "", NULL, NULL, NULL);
+		}
+		else if (objsubid > 0 && objsubid <= tbinfo->numatts)
+		{
+			resetPQExpBuffer(target);
+			appendPQExpBuffer(target, "COLUMN %s.",
+							  fmtId(tbinfo->relname, force_quotes));
+			appendPQExpBuffer(target, "%s",
+							  fmtId(tbinfo->attnames[objsubid-1],
+									force_quotes));
 
-	/*** Clear the statement buffer and return ***/
+			resetPQExpBuffer(query);
+			appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
+			formatStringLiteral(query, descr, PASS_LFTAB);
+			appendPQExpBuffer(query, ";\n");
+
+			ArchiveEntry(fout, tbinfo->oid, target->data,
+						 tbinfo->relnamespace->nspname, tbinfo->usename,
+						 "COMMENT", deps,
+						 query->data, "", NULL, NULL, NULL);
+		}
+	}
 
 	PQclear(res);
 	destroyPQExpBuffer(query);
+	destroyPQExpBuffer(target);
 }
 
-/*------------------------------------------------------------------
+/*
  * 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(Archive *fout)
 {
@@ -3191,6 +2610,9 @@ dumpDBComment(Archive *fout)
 	PQExpBuffer query;
 	int			i_oid;
 
+	/* Make sure we are in proper schema */
+	selectSourceSchema("pg_catalog");
+
 	/*** Build query to find comment ***/
 
 	query = createPQExpBuffer();
@@ -3214,19 +2636,303 @@ dumpDBComment(Archive *fout)
 		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),
-					"pg_database", 0, NULL);
+		dumpComment(fout, query->data, NULL, "",
+					PQgetvalue(res, 0, i_oid), "pg_database", 0, NULL);
+	}
+
+	PQclear(res);
+	destroyPQExpBuffer(query);
+}
+
+/*
+ * dumpNamespaces
+ *    writes out to fout the queries to recreate user-defined namespaces
+ */
+void
+dumpNamespaces(Archive *fout, NamespaceInfo *nsinfo, int numNamespaces)
+{
+	PQExpBuffer q = createPQExpBuffer();
+	PQExpBuffer delq = createPQExpBuffer();
+	int			i;
+
+	for (i = 0; i < numNamespaces; i++)
+	{
+		/* skip if not to be dumped */
+		if (!nsinfo[i].dump)
+			continue;
+
+		/* don't dump dummy namespace from pre-7.3 source */
+		if (strlen(nsinfo[i].nspname) == 0)
+			continue;
+
+		/* quick hack: don't dump CREATE SCHEMA for public namespace */
+		/* XXX need a better idea */
+		if (strcmp(nsinfo[i].nspname, "public") == 0)
+			continue;
+
+		resetPQExpBuffer(q);
+		resetPQExpBuffer(delq);
+
+#ifdef NOTYET					/* suppress till DROP SCHEMA works */
+		appendPQExpBuffer(delq, "DROP SCHEMA %s;\n",
+						  fmtId(nsinfo[i].nspname, force_quotes));
+#endif
+
+		appendPQExpBuffer(q, "CREATE SCHEMA %s;\n",
+						  fmtId(nsinfo[i].nspname, force_quotes));
+
+		ArchiveEntry(fout, nsinfo[i].oid, nsinfo[i].nspname,
+					 NULL,
+					 nsinfo[i].usename, "SCHEMA", NULL,
+					 q->data, delq->data, NULL, NULL, NULL);
+
+#ifdef NOTYET					/* suppress till COMMENT ON SCHEMA works */
+		/*** Dump Schema Comments ***/
+		resetPQExpBuffer(q);
+		appendPQExpBuffer(q, "SCHEMA %s",
+						  fmtId(nsinfo[i].nspname, force_quotes));
+		dumpComment(fout, q->data,
+					NULL, nsinfo[i].usename,
+					nsinfo[i].oid, "pg_namespace", 0, NULL);
+#endif
+	}
+
+	destroyPQExpBuffer(q);
+	destroyPQExpBuffer(delq);
+}
+
+/*
+ * dumpOneBaseType
+ *    writes out to fout the queries to recreate a user-defined base type
+ *    as requested by dumpTypes
+ */
+static void
+dumpOneBaseType(Archive *fout, TypeInfo *tinfo,
+				FuncInfo *g_finfo, int numFuncs,
+				TypeInfo *g_tinfo, int numTypes)
+{
+	PQExpBuffer q = createPQExpBuffer();
+	PQExpBuffer delq = createPQExpBuffer();
+	PQExpBuffer query = createPQExpBuffer();
+	PGresult   *res;
+	int			ntups;
+	int			funcInd;
+	char	   *typlen;
+	char	   *typprtlen;
+	char	   *typinput;
+	char	   *typoutput;
+	char	   *typreceive;
+	char	   *typsend;
+	char	   *typinputoid;
+	char	   *typoutputoid;
+	char	   *typreceiveoid;
+	char	   *typsendoid;
+	char	   *typdelim;
+	char	   *typdefault;
+	char	   *typbyval;
+	char	   *typalign;
+	char	   *typstorage;
+	const char *((*deps)[]);
+	int			depIdx = 0;
+
+	deps = malloc(sizeof(char *) * 10);
+
+	/* Set proper schema search path so regproc references list correctly */
+	selectSourceSchema(tinfo->typnamespace->nspname);
+
+	/* Fetch type-specific details */
+	if (fout->remoteVersion >= 70100)
+	{
+		appendPQExpBuffer(query, "SELECT typlen, typprtlen, "
+						  "typinput, typoutput, typreceive, typsend, "
+						  "typinput::oid as typinputoid, "
+						  "typoutput::oid as typoutputoid, "
+						  "typreceive::oid as typreceiveoid, "
+						  "typsend::oid as typsendoid, "
+						  "typdelim, typdefault, typbyval, typalign, "
+						  "typstorage "
+						  "FROM pg_type "
+						  "WHERE oid = '%s'::oid",
+						  tinfo->oid);
+	}
+	else
+	{
+		appendPQExpBuffer(query, "SELECT typlen, typprtlen, "
+						  "typinput, typoutput, typreceive, typsend, "
+						  "typinput::oid as typinputoid, "
+						  "typoutput::oid as typoutputoid, "
+						  "typreceive::oid as typreceiveoid, "
+						  "typsend::oid as typsendoid, "
+						  "typdelim, typdefault, typbyval, typalign, "
+						  "'p'::char as typstorage "
+						  "FROM pg_type "
+						  "WHERE oid = '%s'::oid",
+						  tinfo->oid);
+	}
+
+	res = PQexec(g_conn, query->data);
+	if (!res ||
+		PQresultStatus(res) != PGRES_TUPLES_OK)
+	{
+		write_msg(NULL, "query to obtain type information for %s failed: %s",
+				  tinfo->typname, PQerrorMessage(g_conn));
+		exit_nicely();
+	}
+
+	/* Expecting a single result only */
+	ntups = PQntuples(res);
+	if (ntups != 1)
+	{
+		write_msg(NULL, "Got %d rows instead of one from: %s",
+				  ntups, query->data);
+		exit_nicely();
+	}
+
+	typlen = PQgetvalue(res, 0, PQfnumber(res, "typlen"));
+	typprtlen = PQgetvalue(res, 0, PQfnumber(res, "typprtlen"));
+	typinput = PQgetvalue(res, 0, PQfnumber(res, "typinput"));
+	typoutput = PQgetvalue(res, 0, PQfnumber(res, "typoutput"));
+	typreceive = PQgetvalue(res, 0, PQfnumber(res, "typreceive"));
+	typsend = PQgetvalue(res, 0, PQfnumber(res, "typsend"));
+	typinputoid = PQgetvalue(res, 0, PQfnumber(res, "typinputoid"));
+	typoutputoid = PQgetvalue(res, 0, PQfnumber(res, "typoutputoid"));
+	typreceiveoid = PQgetvalue(res, 0, PQfnumber(res, "typreceiveoid"));
+	typsendoid = PQgetvalue(res, 0, PQfnumber(res, "typsendoid"));
+	typdelim = PQgetvalue(res, 0, PQfnumber(res, "typdelim"));
+	if (PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
+		typdefault = NULL;
+	else
+		typdefault = strdup(PQgetvalue(res, 0, PQfnumber(res, "typdefault")));
+	typbyval = PQgetvalue(res, 0, PQfnumber(res, "typbyval"));
+	typalign = PQgetvalue(res, 0, PQfnumber(res, "typalign"));
+	typstorage = PQgetvalue(res, 0, PQfnumber(res, "typstorage"));
+
+	/*
+	 * Before we create a type, we need to create the input and output
+	 * functions for it, if they haven't been created already.  So make
+	 * sure there are dependency entries for this.  But don't include
+	 * dependencies if the functions aren't going to be dumped.
+	 */
+	funcInd = findFuncByOid(g_finfo, numFuncs, typinputoid);
+	if (funcInd >= 0 && g_finfo[funcInd].pronamespace->dump)
+		(*deps)[depIdx++] = strdup(typinputoid);
+
+	funcInd = findFuncByOid(g_finfo, numFuncs, typoutputoid);
+	if (funcInd >= 0 && g_finfo[funcInd].pronamespace->dump)
+		(*deps)[depIdx++] = strdup(typoutputoid);
+
+	if (strcmp(typreceiveoid, typinputoid) != 0)
+	{
+		funcInd = findFuncByOid(g_finfo, numFuncs, typreceiveoid);
+		if (funcInd >= 0 && g_finfo[funcInd].pronamespace->dump)
+			(*deps)[depIdx++] = strdup(typreceiveoid);
+	}
+
+	if (strcmp(typsendoid, typoutputoid) != 0)
+	{
+		funcInd = findFuncByOid(g_finfo, numFuncs, typsendoid);
+		if (funcInd >= 0 && g_finfo[funcInd].pronamespace->dump)
+			(*deps)[depIdx++] = strdup(typsendoid);
+	}
+
+	appendPQExpBuffer(delq, "DROP TYPE %s;\n",
+					  fmtId(tinfo->typname, force_quotes));
+
+	appendPQExpBuffer(q,
+					  "CREATE TYPE %s "
+					  "( internallength = %s, externallength = %s,",
+					  fmtId(tinfo->typname, force_quotes),
+					  (strcmp(typlen, "-1") == 0) ? "variable" : typlen,
+					  (strcmp(typprtlen, "-1") == 0) ? "variable" : typprtlen);
+
+	if (fout->remoteVersion >= 70300)
+	{
+		/* regproc result is correctly quoted in 7.3 */
+		appendPQExpBuffer(q, " input = %s, output = %s, "
+						  "send = %s, receive = %s",
+						  typinput, typoutput, typsend, typreceive);
+	}
+	else
+	{
+		/* regproc delivers an unquoted name before 7.3 */
+		/* cannot combine these because fmtId uses static result area */
+		appendPQExpBuffer(q, " input = %s,",
+						  fmtId(typinput, force_quotes));
+		appendPQExpBuffer(q, " output = %s,",
+						  fmtId(typoutput, force_quotes));
+		appendPQExpBuffer(q, " send = %s,",
+						  fmtId(typsend, force_quotes));
+		appendPQExpBuffer(q, " receive = %s",
+						  fmtId(typreceive, force_quotes));
 	}
 
-	/*** Clear the statement buffer and return ***/
+	if (typdefault != NULL)
+	{
+		appendPQExpBuffer(q, ", default = ");
+		formatStringLiteral(q, typdefault, CONV_ALL);
+	}
+
+	if (tinfo->isArray)
+	{
+		char	   *elemType;
+
+		/* reselect schema in case changed by function dump */
+		selectSourceSchema(tinfo->typnamespace->nspname);
+		elemType = getFormattedTypeName(tinfo->typelem, zeroAsOpaque);
+		appendPQExpBuffer(q, ", element = %s, delimiter = ", elemType);
+		formatStringLiteral(q, typdelim, CONV_ALL);
+		free(elemType);
+
+		(*deps)[depIdx++] = strdup(tinfo->typelem);
+	}
+
+	if (strcmp(typalign, "c") == 0)
+		appendPQExpBuffer(q, ", alignment = char");
+	else if (strcmp(typalign, "s") == 0)
+		appendPQExpBuffer(q, ", alignment = int2");
+	else if (strcmp(typalign, "i") == 0)
+		appendPQExpBuffer(q, ", alignment = int4");
+	else if (strcmp(typalign, "d") == 0)
+		appendPQExpBuffer(q, ", alignment = double");
+
+	if (strcmp(typstorage, "p") == 0)
+		appendPQExpBuffer(q, ", storage = plain");
+	else if (strcmp(typstorage, "e") == 0)
+		appendPQExpBuffer(q, ", storage = external");
+	else if (strcmp(typstorage, "x") == 0)
+		appendPQExpBuffer(q, ", storage = extended");
+	else if (strcmp(typstorage, "m") == 0)
+		appendPQExpBuffer(q, ", storage = main");
+
+	if (strcmp(typbyval, "t") == 0)
+		appendPQExpBuffer(q, ", passedbyvalue);\n");
+	else
+		appendPQExpBuffer(q, ");\n");
+
+	(*deps)[depIdx++] = NULL;		/* End of List */
+
+	ArchiveEntry(fout, tinfo->oid, tinfo->typname,
+				 tinfo->typnamespace->nspname,
+				 tinfo->usename, "TYPE", deps,
+				 q->data, delq->data, NULL, NULL, NULL);
+
+	/*** Dump Type Comments ***/
+	resetPQExpBuffer(q);
+
+	appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo->typname, force_quotes));
+	dumpComment(fout, q->data,
+				tinfo->typnamespace->nspname, tinfo->usename,
+				tinfo->oid, "pg_type", 0, NULL);
 
 	PQclear(res);
+	destroyPQExpBuffer(q);
+	destroyPQExpBuffer(delq);
 	destroyPQExpBuffer(query);
 }
 
 /*
  * dumpOneDomain
- *    wites out to fout the queries to recrease a user-defined domains
+ *    writes out to fout the queries to recreate a user-defined domain
  *    as requested by dumpTypes
  */
 static void
@@ -3234,24 +2940,28 @@ dumpOneDomain(Archive *fout, TypeInfo *tinfo)
 {
 	PQExpBuffer q = createPQExpBuffer();
 	PQExpBuffer delq = createPQExpBuffer();
-
-	PGresult   *res;
 	PQExpBuffer query = createPQExpBuffer();
+	PGresult   *res;
 	int			ntups;
+	char	   *typnotnull;
+	char	   *typdefn;
+	char	   *typdefault;
+	char	   *typbasetype;
 	const char *((*deps)[]);
 	int			depIdx = 0;
 
-
 	deps = malloc(sizeof(char *) * 10);
 
+	/* Set proper schema search path so type references list correctly */
+	selectSourceSchema(tinfo->typnamespace->nspname);
+
 	/* Fetch domain specific details */
-	resetPQExpBuffer(query);
 	appendPQExpBuffer(query, "SELECT typnotnull, "
-							 "format_type(typbasetype, typtypmod) as typdefn, "
-							 "typbasetype "
-							 "FROM pg_type "
-							 "WHERE typname = '%s'",
-							 tinfo->typname);
+					  "format_type(typbasetype, typtypmod) as typdefn, "
+					  "typdefault, typbasetype "
+					  "FROM pg_type "
+					  "WHERE oid = '%s'::oid",
+					  tinfo->oid);
 
 	res = PQexec(g_conn, query->data);
 	if (!res ||
@@ -3264,68 +2974,79 @@ dumpOneDomain(Archive *fout, TypeInfo *tinfo)
 	/* Expecting a single result only */
 	ntups = PQntuples(res);
 	if (ntups != 1)
-		write_msg(NULL, "Domain %s non-existant.", fmtId(tinfo->typname, force_quotes));
+	{
+		write_msg(NULL, "Got %d rows instead of one from: %s",
+				  ntups, query->data);
+		exit_nicely();
+	}
 
+	typnotnull = PQgetvalue(res, 0, PQfnumber(res, "typnotnull"));
+	typdefn = PQgetvalue(res, 0, PQfnumber(res, "typdefn"));
+	if (PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
+		typdefault = NULL;
+	else
+		typdefault = strdup(PQgetvalue(res, 0, PQfnumber(res, "typdefault")));
+	typbasetype = PQgetvalue(res, 0, PQfnumber(res, "typbasetype"));
 
-	/* Drop the old copy */
-	resetPQExpBuffer(delq);
-	appendPQExpBuffer(delq, "DROP DOMAIN %s RESTRICT;\n", fmtId(tinfo->typname, force_quotes));
+	/* Command to drop the old copy */
+	appendPQExpBuffer(delq, "DROP DOMAIN %s RESTRICT;\n",
+					  fmtId(tinfo->typname, force_quotes));
 
-	resetPQExpBuffer(q);
 	appendPQExpBuffer(q,
 					  "CREATE DOMAIN %s AS %s",
 					  fmtId(tinfo->typname, force_quotes),
-					  PQgetvalue(res, 0, PQfnumber(res, "typdefn"))
-					  );
+					  typdefn);
 
 	/* Depends on the base type */
-	(*deps)[depIdx++] = strdup(PQgetvalue(res, 0, PQfnumber(res, "typbasetype")));
+	(*deps)[depIdx++] = strdup(typbasetype);
 
-	if (PQgetvalue(res, 0, PQfnumber(res, "typnotnull"))[0] == 't')
+	if (typnotnull[0] == 't')
 		appendPQExpBuffer(q, " NOT NULL");
 
-	if (tinfo->typdefault)
+	if (typdefault)
 	{
 		appendPQExpBuffer(q,
 						  " DEFAULT %s",
-						  tinfo->typdefault);
+						  typdefault);
 	}
 
 	appendPQExpBuffer(q, ";\n");
 
-
 	(*deps)[depIdx++] = NULL;		/* End of List */
 
-	ArchiveEntry(fout, tinfo->oid, tinfo->typname, "DOMAIN", deps,
-				 q->data, delq->data, "", tinfo->usename, NULL, NULL);
+	ArchiveEntry(fout, tinfo->oid, tinfo->typname,
+				 tinfo->typnamespace->nspname,
+				 tinfo->usename, "DOMAIN", deps,
+				 q->data, delq->data, NULL, NULL, NULL);
 
 	/*** Dump Domain Comments ***/
 	resetPQExpBuffer(q);
 
 	appendPQExpBuffer(q, "DOMAIN %s", fmtId(tinfo->typname, force_quotes));
-	dumpComment(fout, q->data, tinfo->oid, "pg_type", 0, NULL);
+	dumpComment(fout, q->data,
+				tinfo->typnamespace->nspname, tinfo->usename,
+				tinfo->oid, "pg_type", 0, NULL);
+
+	PQclear(res);
+	destroyPQExpBuffer(q);
+	destroyPQExpBuffer(delq);
+	destroyPQExpBuffer(query);
 }
 
 /*
  * dumpTypes
  *	  writes out to fout the queries to recreate all the user-defined types
- *
  */
 void
 dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
 		  TypeInfo *tinfo, int numTypes)
 {
 	int			i;
-	PQExpBuffer q = createPQExpBuffer();
-	PQExpBuffer delq = createPQExpBuffer();
-	int			funcInd;
-	const char *((*deps)[]);
-	int			depIdx;
 
 	for (i = 0; i < numTypes; i++)
 	{
-		/* skip all the builtin types */
-		if (atooid(tinfo[i].oid) <= g_last_builtin_oid)
+		/* Dump only types in dumpable namespaces */
+		if (!tinfo[i].typnamespace->dump)
 			continue;
 
 		/* skip relation types */
@@ -3338,133 +3059,24 @@ dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
 
 		/* skip all array types that start w/ underscore */
 		if ((tinfo[i].typname[0] == '_') &&
-			(strcmp(tinfo[i].typinput, "array_in") == 0))
+			atooid(tinfo[i].typelem) != 0)
 			continue;
 
-		/* Dump out domains as we run across them */
-		if (strcmp(tinfo[i].typtype, "d") == 0) {
+		/* Dump out in proper style */
+		if (tinfo[i].typtype == 'b')
+			dumpOneBaseType(fout, &tinfo[i],
+							finfo, numFuncs, tinfo, numTypes);
+		else if (tinfo[i].typtype == 'd')
 			dumpOneDomain(fout, &tinfo[i]);
-			continue;
-		}
-
-
-		deps = malloc(sizeof(char *) * 10);
-		depIdx = 0;
-
-		/*
-		 * before we create a type, we need to create the input and output
-		 * functions for it, if they haven't been created already
-		 */
-		funcInd = findFuncByName(finfo, numFuncs, tinfo[i].typinput);
-		if (funcInd != -1)
-		{
-			(*deps)[depIdx++] = strdup(finfo[funcInd].oid);
-			dumpOneFunc(fout, finfo, funcInd, tinfo, numTypes);
-		}
-
-		funcInd = findFuncByName(finfo, numFuncs, tinfo[i].typoutput);
-		if (funcInd != -1)
-		{
-			(*deps)[depIdx++] = strdup(finfo[funcInd].oid);
-			dumpOneFunc(fout, finfo, funcInd, tinfo, numTypes);
-		}
-
-		resetPQExpBuffer(delq);
-		appendPQExpBuffer(delq, "DROP TYPE %s;\n", fmtId(tinfo[i].typname, force_quotes));
-
-		resetPQExpBuffer(q);
-		appendPQExpBuffer(q,
-						  "CREATE TYPE %s "
-						  "( internallength = %s, externallength = %s,",
-						  fmtId(tinfo[i].typname, force_quotes),
-						  (strcmp(tinfo[i].typlen, "-1") == 0) ?
-						  "variable" : tinfo[i].typlen,
-						  (strcmp(tinfo[i].typprtlen, "-1") == 0) ?
-						  "variable" : tinfo[i].typprtlen);
-		/* cannot combine these because fmtId uses static result area */
-		appendPQExpBuffer(q, " input = %s,",
-						  fmtId(tinfo[i].typinput, force_quotes));
-		appendPQExpBuffer(q, " output = %s,",
-						  fmtId(tinfo[i].typoutput, force_quotes));
-		appendPQExpBuffer(q, " send = %s,",
-						  fmtId(tinfo[i].typsend, force_quotes));
-		appendPQExpBuffer(q, " receive = %s",
-						  fmtId(tinfo[i].typreceive, force_quotes));
-
-		if (tinfo[i].typdefault != NULL)
-		{
-			appendPQExpBuffer(q, ", default = ");
-			formatStringLiteral(q, tinfo[i].typdefault, CONV_ALL);
-		}
-
-		if (tinfo[i].isArray)
-		{
-			char	   *elemType;
-
-			elemType = findTypeByOid(tinfo, numTypes, tinfo[i].typelem, zeroAsOpaque);
-			if (elemType == NULL)
-			{
-				write_msg(NULL, "notice: array type %s - type for elements (oid %s) is not dumped\n",
-						  tinfo[i].typname, tinfo[i].typelem);
-				continue;
-			}
-
-			appendPQExpBuffer(q, ", element = %s, delimiter = ", elemType);
-			formatStringLiteral(q, tinfo[i].typdelim, CONV_ALL);
-
-			(*deps)[depIdx++] = strdup(tinfo[i].typelem);
-		}
-
-		if (strcmp(tinfo[i].typalign, "c") == 0)
-			appendPQExpBuffer(q, ", alignment = char");
-		else if (strcmp(tinfo[i].typalign, "s") == 0)
-			appendPQExpBuffer(q, ", alignment = int2");
-		else if (strcmp(tinfo[i].typalign, "i") == 0)
-			appendPQExpBuffer(q, ", alignment = int4");
-		else if (strcmp(tinfo[i].typalign, "d") == 0)
-			appendPQExpBuffer(q, ", alignment = double");
-
-		if (strcmp(tinfo[i].typstorage, "p") == 0)
-			appendPQExpBuffer(q, ", storage = plain");
-		else if (strcmp(tinfo[i].typstorage, "e") == 0)
-			appendPQExpBuffer(q, ", storage = external");
-		else if (strcmp(tinfo[i].typstorage, "x") == 0)
-			appendPQExpBuffer(q, ", storage = extended");
-		else if (strcmp(tinfo[i].typstorage, "m") == 0)
-			appendPQExpBuffer(q, ", storage = main");
-
-		if (tinfo[i].passedbyvalue)
-			appendPQExpBuffer(q, ", passedbyvalue);\n");
-		else
-			appendPQExpBuffer(q, ");\n");
-
-		(*deps)[depIdx++] = NULL;		/* End of List */
-
-		ArchiveEntry(fout, tinfo[i].oid, tinfo[i].typname, "TYPE", deps,
-				  q->data, delq->data, "", tinfo[i].usename, NULL, NULL);
-
-
-
-		/*** Dump Type Comments ***/
-
-		resetPQExpBuffer(q);
-
-		appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo[i].typname, force_quotes));
-		dumpComment(fout, q->data, tinfo[i].oid, "pg_type", 0, NULL);
 	}
-
-	destroyPQExpBuffer(q);
-	destroyPQExpBuffer(delq);
 }
 
 /*
  * dumpProcLangs
  *		  writes out to fout the queries to recreate user-defined procedural languages
- *
  */
 void
-dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs,
-			  TypeInfo *tinfo, int numTypes)
+dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs)
 {
 	PGresult   *res;
 	PQExpBuffer query = createPQExpBuffer();
@@ -3476,13 +3088,18 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs,
 	int			i_lanpltrusted;
 	int			i_lanplcallfoid;
 	int			i_lancompiler;
-	Oid			lanoid;
+	char	   *lanoid;
 	char	   *lanname;
 	char	   *lancompiler;
 	const char *lanplcallfoid;
+	const char *((*deps)[]);
+	int			depIdx;
 	int			i,
 				fidx;
 
+	/* Make sure we are in proper schema */
+	selectSourceSchema("pg_catalog");
+
 	appendPQExpBuffer(query, "SELECT oid, * FROM pg_language "
 					  "WHERE lanispl "
 					  "ORDER BY oid");
@@ -3504,29 +3121,38 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs,
 
 	for (i = 0; i < ntups; i++)
 	{
-		lanoid = atooid(PQgetvalue(res, i, i_oid));
-		if (lanoid <= g_last_builtin_oid)
-			continue;
-
+		lanoid = PQgetvalue(res, i, i_oid);
 		lanplcallfoid = PQgetvalue(res, i, i_lanplcallfoid);
+		lanname = PQgetvalue(res, i, i_lanname);
+		lancompiler = PQgetvalue(res, i, i_lancompiler);
 
-
-		for (fidx = 0; fidx < numFuncs; fidx++)
-		{
-			if (!strcmp(finfo[fidx].oid, lanplcallfoid))
-				break;
-		}
-		if (fidx >= numFuncs)
+		fidx = findFuncByOid(finfo, numFuncs, lanplcallfoid);
+		if (fidx < 0)
 		{
 			write_msg(NULL, "handler procedure for procedural language %s not found\n",
-					  PQgetvalue(res, i, i_lanname));
+					  lanname);
 			exit_nicely();
 		}
 
-		dumpOneFunc(fout, finfo, fidx, tinfo, numTypes);
+		/*
+		 * Current theory is to dump PLs iff their underlying functions
+		 * will be dumped (are in a dumpable namespace, or have a non-system
+		 * OID in pre-7.3 databases).  Actually, we treat the PL itself
+		 * as being in the underlying function's namespace, though it
+		 * isn't really.  This avoids searchpath problems for the HANDLER
+		 * clause.
+		 */
+		if (!finfo[fidx].pronamespace->dump)
+			continue;
+
+		resetPQExpBuffer(defqry);
+		resetPQExpBuffer(delqry);
 
-		lanname = PQgetvalue(res, i, i_lanname);
-		lancompiler = PQgetvalue(res, i, i_lancompiler);
+		/* Make a dependency to ensure function is dumped first */
+		deps = malloc(sizeof(char *) * 2);
+		depIdx = 0;
+
+		(*deps)[depIdx++] = strdup(lanplcallfoid);
 
 		appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE ");
 		formatStringLiteral(delqry, lanname, CONV_ALL);
@@ -3541,11 +3167,12 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs,
 		formatStringLiteral(defqry, lancompiler, CONV_ALL);
 		appendPQExpBuffer(defqry, ";\n");
 
-		ArchiveEntry(fout, PQgetvalue(res, i, i_oid), lanname, "PROCEDURAL LANGUAGE",
-				   NULL, defqry->data, delqry->data, "", "", NULL, NULL);
+		(*deps)[depIdx++] = NULL;		/* End of List */
 
-		resetPQExpBuffer(defqry);
-		resetPQExpBuffer(delqry);
+		ArchiveEntry(fout, lanoid, lanname,
+					 finfo[fidx].pronamespace->nspname, "",
+					 "PROCEDURAL LANGUAGE", deps,
+					 defqry->data, delqry->data, NULL, NULL, NULL);
 	}
 
 	PQclear(res);
@@ -3558,179 +3185,199 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs,
 /*
  * dumpFuncs
  *	  writes out to fout the queries to recreate all the user-defined functions
- *
  */
 void
-dumpFuncs(Archive *fout, FuncInfo *finfo, int numFuncs,
-		  TypeInfo *tinfo, int numTypes)
+dumpFuncs(Archive *fout, FuncInfo *finfo, int numFuncs)
 {
 	int			i;
 
 	for (i = 0; i < numFuncs; i++)
-		dumpOneFunc(fout, finfo, i, tinfo, numTypes);
+	{
+		/* Dump only funcs in dumpable namespaces */
+		if (!finfo[i].pronamespace->dump)
+			continue;
+
+		dumpOneFunc(fout, &finfo[i]);
+	}
 }
 
 /*
  * dumpOneFunc:
- *	  dump out only one function,  the index of which is given in the third
- *	argument
- *
+ *	  dump out only one function
  */
-
 static void
-dumpOneFunc(Archive *fout, FuncInfo *finfo, int i,
-			TypeInfo *tinfo, int numTypes)
+dumpOneFunc(Archive *fout, FuncInfo *finfo)
 {
+	PQExpBuffer query = createPQExpBuffer();
 	PQExpBuffer q = createPQExpBuffer();
 	PQExpBuffer fn = createPQExpBuffer();
 	PQExpBuffer delqry = createPQExpBuffer();
-	PQExpBuffer fnlist = createPQExpBuffer();
 	PQExpBuffer asPart = createPQExpBuffer();
-	char	   *func_lang = NULL;
-	PGresult   *res;
-	int			nlangs;
+	PGresult   *res = NULL;
+	int			ntups;
 	int			j;
-	int			i_lanname;
-	char		query[256];
-
+	char	   *proretset;
+	char	   *prosrc;
+	char	   *probin;
+	char	   *provolatile;
+	char	   *proimplicit;
+	char	   *proisstrict;
+	char	   *lanname;
 	char	   *listSep;
 	char	   *listSepComma = ",";
 	char	   *listSepNone = "";
 	char	   *rettypename;
 
-	if (finfo[i].dumped)
+	if (finfo->dumped)
 		goto done;
 
-	finfo[i].dumped = 1;
+	finfo->dumped = true;
 
-	/* becomeUser(fout, finfo[i].usename); */
+	/* Set proper schema search path so type references list correctly */
+	selectSourceSchema(finfo->pronamespace->nspname);
+
+	/* Fetch function-specific details */
+	if (g_fout->remoteVersion >= 70300)
+	{
+		appendPQExpBuffer(query,
+						  "SELECT proretset, prosrc, probin, "
+						  "provolatile, proimplicit, proisstrict, "
+						  "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
+						  "FROM pg_proc "
+						  "WHERE oid = '%s'::oid",
+						  finfo->oid);
+	}
+	else if (g_fout->remoteVersion >= 70100)
+	{
+		appendPQExpBuffer(query,
+						  "SELECT proretset, prosrc, probin, "
+						  "case when proiscachable then 'i' else 'v' end as provolatile, "
+						  "'f'::boolean as proimplicit, "
+						  "proisstrict, "
+						  "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
+						  "FROM pg_proc "
+						  "WHERE oid = '%s'::oid",
+						  finfo->oid);
+	}
+	else
+	{
+		appendPQExpBuffer(query,
+						  "SELECT proretset, prosrc, probin, "
+						  "case when proiscachable then 'i' else 'v' end as provolatile, "
+						  "'f'::boolean as proimplicit, "
+						  "'f'::boolean as proisstrict, "
+						  "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
+						  "FROM pg_proc "
+						  "WHERE oid = '%s'::oid",
+						  finfo->oid);
+	}
 
-	sprintf(query, "SELECT lanname FROM pg_language WHERE oid = '%u'::oid",
-			finfo[i].lang);
-	res = PQexec(g_conn, query);
+	res = PQexec(g_conn, query->data);
 	if (!res ||
 		PQresultStatus(res) != PGRES_TUPLES_OK)
 	{
-		write_msg(NULL, "query to get name of procedural language failed: %s", PQerrorMessage(g_conn));
+		write_msg(NULL, "query to obtain function information for %s failed: %s",
+				  finfo->proname, PQerrorMessage(g_conn));
 		exit_nicely();
 	}
-	nlangs = PQntuples(res);
 
-	if (nlangs != 1)
+	/* Expecting a single result only */
+	ntups = PQntuples(res);
+	if (ntups != 1)
 	{
-		write_msg(NULL, "procedural language for function %s not found\n", finfo[i].proname);
+		write_msg(NULL, "Got %d rows instead of one from: %s",
+				  ntups, query->data);
 		exit_nicely();
 	}
 
-	i_lanname = PQfnumber(res, "lanname");
+	proretset = PQgetvalue(res, 0, PQfnumber(res, "proretset"));
+	prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc"));
+	probin = PQgetvalue(res, 0, PQfnumber(res, "probin"));
+	provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
+	proimplicit = PQgetvalue(res, 0, PQfnumber(res, "proimplicit"));
+	proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
+	lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
 
 	/*
 	 * See backend/commands/define.c for details of how the 'AS' clause is
 	 * used.
 	 */
-	if (strcmp(finfo[i].probin, "-") != 0)
+	if (strcmp(probin, "-") != 0)
 	{
 		appendPQExpBuffer(asPart, "AS ");
-		formatStringLiteral(asPart, finfo[i].probin, CONV_ALL);
-		if (strcmp(finfo[i].prosrc, "-") != 0)
+		formatStringLiteral(asPart, probin, CONV_ALL);
+		if (strcmp(prosrc, "-") != 0)
 		{
 			appendPQExpBuffer(asPart, ", ");
-			formatStringLiteral(asPart, finfo[i].prosrc, PASS_LFTAB);
+			formatStringLiteral(asPart, prosrc, PASS_LFTAB);
 		}
 	}
 	else
 	{
-		if (strcmp(finfo[i].prosrc, "-") != 0)
+		if (strcmp(prosrc, "-") != 0)
 		{
 			appendPQExpBuffer(asPart, "AS ");
-			formatStringLiteral(asPart, finfo[i].prosrc, PASS_LFTAB);
+			formatStringLiteral(asPart, prosrc, PASS_LFTAB);
 		}
 	}
 
-	func_lang = strdup(PQgetvalue(res, 0, i_lanname));
-
-	PQclear(res);
-
-	resetPQExpBuffer(fn);
-	appendPQExpBuffer(fn, "%s (", fmtId(finfo[i].proname, force_quotes));
-	for (j = 0; j < finfo[i].nargs; j++)
+	appendPQExpBuffer(fn, "%s (", fmtId(finfo->proname, force_quotes));
+	for (j = 0; j < finfo->nargs; j++)
 	{
 		char	   *typname;
 
-		typname = findTypeByOid(tinfo, numTypes, finfo[i].argtypes[j], zeroAsOpaque);
-		if (typname == NULL)
-		{
-			write_msg(NULL, "WARNING: function \"%s\" not dumped\n",
-					  finfo[i].proname);
-
-			write_msg(NULL, "reason: data type name of argument %d (oid %s) not found\n",
-					  j, finfo[i].argtypes[j]);
-			goto done;
-		}
-
+		typname = getFormattedTypeName(finfo->argtypes[j], zeroAsOpaque);
 		appendPQExpBuffer(fn, "%s%s",
 						  (j > 0) ? "," : "",
 						  typname);
-		appendPQExpBuffer(fnlist, "%s%s",
-						  (j > 0) ? "," : "",
-						  typname);
+		free(typname);
 	}
 	appendPQExpBuffer(fn, ")");
 
-	resetPQExpBuffer(delqry);
 	appendPQExpBuffer(delqry, "DROP FUNCTION %s;\n", fn->data);
 
-	rettypename = findTypeByOid(tinfo, numTypes, finfo[i].prorettype, zeroAsOpaque);
-
-	if (rettypename == NULL)
-	{
-		write_msg(NULL, "WARNING: function \"%s\" not dumped\n",
-				  finfo[i].proname);
-
-		write_msg(NULL, "reason: name of return data type (oid %s) not found\n",
-				  finfo[i].prorettype);
-		goto done;
-	}
+	rettypename = getFormattedTypeName(finfo->prorettype, zeroAsOpaque);
 
-	resetPQExpBuffer(q);
 	appendPQExpBuffer(q, "CREATE FUNCTION %s ", fn->data);
 	appendPQExpBuffer(q, "RETURNS %s%s %s LANGUAGE ",
-					  (finfo[i].retset) ? "SETOF " : "",
+					  (proretset[0] == 't') ? "SETOF " : "",
 					  rettypename,
 					  asPart->data);
-	formatStringLiteral(q, func_lang, CONV_ALL);
+	formatStringLiteral(q, lanname, CONV_ALL);
+
+	free(rettypename);
 
-	if (finfo[i].provolatile != PROVOLATILE_VOLATILE ||
-		finfo[i].isimplicit ||
-		finfo[i].isstrict)		/* OR in new attrs here */
+	if (provolatile[0] != PROVOLATILE_VOLATILE ||
+		proimplicit[0] == 't' ||
+		proisstrict[0] == 't')	/* OR in new attrs here */
 	{
 		appendPQExpBuffer(q, " WITH (");
 		listSep = listSepNone;
 
-		if (finfo[i].provolatile == PROVOLATILE_IMMUTABLE)
+		if (provolatile[0] == PROVOLATILE_IMMUTABLE)
 		{
 			appendPQExpBuffer(q, "%s isImmutable", listSep);
 			listSep = listSepComma;
 		}
-		else if (finfo[i].provolatile == PROVOLATILE_STABLE)
+		else if (provolatile[0] == PROVOLATILE_STABLE)
 		{
 			appendPQExpBuffer(q, "%s isStable", listSep);
 			listSep = listSepComma;
 		}
-		else if (finfo[i].provolatile != PROVOLATILE_VOLATILE)
+		else if (provolatile[0] != PROVOLATILE_VOLATILE)
 		{
 			write_msg(NULL, "Unexpected provolatile value for function %s\n",
-					  finfo[i].proname);
+					  finfo->proname);
 			exit_nicely();
 		}
 
-		if (finfo[i].isimplicit)
+		if (proimplicit[0] == 't')
 		{
 			appendPQExpBuffer(q, "%s implicitCoercion", listSep);
 			listSep = listSepComma;
 		}
 
-		if (finfo[i].isstrict)
+		if (proisstrict[0] == 't')
 		{
 			appendPQExpBuffer(q, "%s isStrict", listSep);
 			listSep = listSepComma;
@@ -3741,331 +3388,608 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo, int i,
 
 	appendPQExpBuffer(q, ";\n");
 
-	ArchiveEntry(fout, finfo[i].oid, fn->data, "FUNCTION", NULL, q->data, delqry->data,
-				 "", finfo[i].usename, NULL, NULL);
+	ArchiveEntry(fout, finfo->oid, fn->data, finfo->pronamespace->nspname,
+				 finfo->usename, "FUNCTION", NULL,
+				 q->data, delqry->data,
+				 NULL, NULL, NULL);
 
 	/*** 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, "pg_proc", 0, NULL);
+	appendPQExpBuffer(q, "FUNCTION %s ", fn->data);
+	dumpComment(fout, q->data,
+				finfo->pronamespace->nspname, finfo->usename,
+				finfo->oid, "pg_proc", 0, NULL);
 
 done:
+	PQclear(res);
+
+	destroyPQExpBuffer(query);
 	destroyPQExpBuffer(q);
 	destroyPQExpBuffer(fn);
 	destroyPQExpBuffer(delqry);
-	destroyPQExpBuffer(fnlist);
 	destroyPQExpBuffer(asPart);
-	free(func_lang);
 }
 
 /*
  * dumpOprs
  *	  writes out to fout the queries to recreate all the user-defined operators
- *
  */
 void
-dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators,
-		 TypeInfo *tinfo, int numTypes)
+dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators)
 {
 	int			i;
-	PQExpBuffer q = createPQExpBuffer();
-	PQExpBuffer delq = createPQExpBuffer();
-	PQExpBuffer leftarg = createPQExpBuffer();
-	PQExpBuffer rightarg = createPQExpBuffer();
-	PQExpBuffer commutator = createPQExpBuffer();
-	PQExpBuffer negator = createPQExpBuffer();
-	PQExpBuffer restrictor = createPQExpBuffer();
-	PQExpBuffer join = createPQExpBuffer();
-	PQExpBuffer sort1 = createPQExpBuffer();
-	PQExpBuffer sort2 = createPQExpBuffer();
 
 	for (i = 0; i < numOperators; i++)
 	{
-		char	   *name;
-
-		resetPQExpBuffer(leftarg);
-		resetPQExpBuffer(rightarg);
-		resetPQExpBuffer(commutator);
-		resetPQExpBuffer(negator);
-		resetPQExpBuffer(restrictor);
-		resetPQExpBuffer(join);
-		resetPQExpBuffer(sort1);
-		resetPQExpBuffer(sort2);
-
-		/* skip all the builtin oids */
-		if (atooid(oprinfo[i].oid) <= g_last_builtin_oid)
+		/* Dump only operators in dumpable namespaces */
+		if (!oprinfo[i].oprnamespace->dump)
 			continue;
 
 		/*
-		 * some operator are invalid because they were the result of user
+		 * some operators are invalid because they were the result of user
 		 * defining operators before commutators exist
 		 */
-		if (strcmp(oprinfo[i].oprcode, "-") == 0)
+		if (strcmp(oprinfo[i].oprcode, "0") == 0)
 			continue;
 
-		/*
-		 * right unary means there's a left arg and left unary means
-		 * there's a right arg
-		 */
-		if (strcmp(oprinfo[i].oprkind, "r") == 0 ||
-			strcmp(oprinfo[i].oprkind, "b") == 0)
-		{
-			name = findTypeByOid(tinfo, numTypes,
-								 oprinfo[i].oprleft, zeroAsOpaque);
-			if (name == NULL)
-			{
-				write_msg(NULL, "WARNING: operator \"%s\" (oid %s) not dumped\n",
-						  oprinfo[i].oprname, oprinfo[i].oid);
-				write_msg(NULL, "reason: oprleft (oid %s) not found\n",
-						  oprinfo[i].oprleft);
-				continue;
-			}
-			appendPQExpBuffer(leftarg, ",\n\tLEFTARG = %s ", name);
-		}
+		/* OK, dump it */
+		dumpOneOpr(fout, &oprinfo[i],
+				   oprinfo, numOperators);
+	}
+}
 
-		if (strcmp(oprinfo[i].oprkind, "l") == 0 ||
-			strcmp(oprinfo[i].oprkind, "b") == 0)
-		{
-			name = findTypeByOid(tinfo, numTypes,
-								 oprinfo[i].oprright, zeroAsOpaque);
-			if (name == NULL)
-			{
-				write_msg(NULL, "WARNING: operator \"%s\" (oid %s) not dumped\n",
-						  oprinfo[i].oprname, oprinfo[i].oid);
-				write_msg(NULL, "reason: oprright (oid %s) not found\n",
-						  oprinfo[i].oprright);
-				continue;
-			}
-			appendPQExpBuffer(rightarg, ",\n\tRIGHTARG = %s ", name);
-		}
+/*
+ * dumpOneOpr
+ *	  write out a single operator definition
+ */
+static void
+dumpOneOpr(Archive *fout, OprInfo *oprinfo,
+		   OprInfo *g_oprinfo, int numOperators)
+{
+	PQExpBuffer query = createPQExpBuffer();
+	PQExpBuffer q = createPQExpBuffer();
+	PQExpBuffer delq = createPQExpBuffer();
+	PQExpBuffer oprid = createPQExpBuffer();
+	PQExpBuffer details = createPQExpBuffer();
+	const char *name;
+	PGresult   *res;
+	int			ntups;
+	int			i_oprkind;
+	int			i_oprcode;
+	int			i_oprleft;
+	int			i_oprright;
+	int			i_oprcom;
+	int			i_oprnegate;
+	int			i_oprrest;
+	int			i_oprjoin;
+	int			i_oprcanhash;
+	int			i_oprlsortop;
+	int			i_oprrsortop;
+	int			i_oprltcmpop;
+	int			i_oprgtcmpop;
+	char	   *oprkind;
+	char	   *oprcode;
+	char	   *oprleft;
+	char	   *oprright;
+	char	   *oprcom;
+	char	   *oprnegate;
+	char	   *oprrest;
+	char	   *oprjoin;
+	char	   *oprcanhash;
+	char	   *oprlsortop;
+	char	   *oprrsortop;
+	char	   *oprltcmpop;
+	char	   *oprgtcmpop;
+
+	/* Make sure we are in proper schema so regoperator works correctly */
+	selectSourceSchema(oprinfo->oprnamespace->nspname);
+
+	if (g_fout->remoteVersion >= 70300)
+	{
+		appendPQExpBuffer(query, "SELECT oprkind, oprcode::regprocedure, "
+						  "oprleft::regtype, oprright::regtype, "
+						  "oprcom::regoperator, oprnegate::regoperator, "
+						  "oprrest::regprocedure, oprjoin::regprocedure, "
+						  "oprcanhash, "
+						  "oprlsortop::regoperator, oprrsortop::regoperator, "
+						  "oprltcmpop::regoperator, oprgtcmpop::regoperator "
+						  "from pg_operator "
+						  "where oid = '%s'::oid",
+						  oprinfo->oid);
+	}
+	else if (g_fout->remoteVersion >= 70100)
+	{
+		appendPQExpBuffer(query, "SELECT oprkind, oprcode, "
+						  "CASE WHEN oprleft = 0 THEN '-' "
+						  "ELSE format_type(oprleft, NULL) END as oprleft, "
+						  "CASE WHEN oprright = 0 THEN '-' "
+						  "ELSE format_type(oprright, NULL) END as oprright, "
+						  "oprcom, oprnegate, oprrest, oprjoin, "
+						  "oprcanhash, oprlsortop, oprrsortop, "
+						  "0 as oprltcmpop, 0 as oprgtcmpop "
+						  "from pg_operator "
+						  "where oid = '%s'::oid",
+						  oprinfo->oid);
+	}
+	else
+	{
+		appendPQExpBuffer(query, "SELECT oprkind, oprcode, "
+						  "CASE WHEN oprleft = 0 THEN '-'::name "
+						  "ELSE (select typname from pg_type where oid = oprleft) END as oprleft, "
+						  "CASE WHEN oprright = 0 THEN '-'::name "
+						  "ELSE (select typname from pg_type where oid = oprright) END as oprright, "
+						  "oprcom, oprnegate, oprrest, oprjoin, "
+						  "oprcanhash, oprlsortop, oprrsortop, "
+						  "0 as oprltcmpop, 0 as oprgtcmpop "
+						  "from pg_operator "
+						  "where oid = '%s'::oid",
+						  oprinfo->oid);
+	}
 
-		if (!(strcmp(oprinfo[i].oprcom, "0") == 0))
-		{
-			name = findOprByOid(oprinfo, numOperators, oprinfo[i].oprcom);
-			if (name == NULL)
-			{
-				write_msg(NULL, "WARNING: operator \"%s\" (oid %s) not dumped\n",
-						  oprinfo[i].oprname, oprinfo[i].oid);
-				write_msg(NULL, "reason: oprcom (oid %s) not found\n",
-						  oprinfo[i].oprcom);
-				continue;
-			}
-			appendPQExpBuffer(commutator, ",\n\tCOMMUTATOR = %s ", name);
-		}
+	res = PQexec(g_conn, query->data);
+	if (!res ||
+		PQresultStatus(res) != PGRES_TUPLES_OK)
+	{
+		write_msg(NULL, "query to obtain list of operators failed: %s", PQerrorMessage(g_conn));
+		exit_nicely();
+	}
 
-		if (!(strcmp(oprinfo[i].oprnegate, "0") == 0))
-		{
-			name = findOprByOid(oprinfo, numOperators, oprinfo[i].oprnegate);
-			if (name == NULL)
-			{
-				write_msg(NULL, "WARNING: operator \"%s\" (oid %s) not dumped\n",
-						  oprinfo[i].oprname, oprinfo[i].oid);
-				write_msg(NULL, "reason: oprnegate (oid %s) not found\n",
-						  oprinfo[i].oprnegate);
-				continue;
-			}
-			appendPQExpBuffer(negator, ",\n\tNEGATOR = %s ", name);
-		}
+	/* Expecting a single result only */
+	ntups = PQntuples(res);
+	if (ntups != 1)
+	{
+		write_msg(NULL, "Got %d rows instead of one from: %s",
+				  ntups, query->data);
+		exit_nicely();
+	}
+
+	i_oprkind = PQfnumber(res, "oprkind");
+	i_oprcode = PQfnumber(res, "oprcode");
+	i_oprleft = PQfnumber(res, "oprleft");
+	i_oprright = PQfnumber(res, "oprright");
+	i_oprcom = PQfnumber(res, "oprcom");
+	i_oprnegate = PQfnumber(res, "oprnegate");
+	i_oprrest = PQfnumber(res, "oprrest");
+	i_oprjoin = PQfnumber(res, "oprjoin");
+	i_oprcanhash = PQfnumber(res, "oprcanhash");
+	i_oprlsortop = PQfnumber(res, "oprlsortop");
+	i_oprrsortop = PQfnumber(res, "oprrsortop");
+	i_oprltcmpop = PQfnumber(res, "oprltcmpop");
+	i_oprgtcmpop = PQfnumber(res, "oprgtcmpop");
+
+	oprkind = PQgetvalue(res, 0, i_oprkind);
+	oprcode = PQgetvalue(res, 0, i_oprcode);
+	oprleft = PQgetvalue(res, 0, i_oprleft);
+	oprright = PQgetvalue(res, 0, i_oprright);
+	oprcom = PQgetvalue(res, 0, i_oprcom);
+	oprnegate = PQgetvalue(res, 0, i_oprnegate);
+	oprrest = PQgetvalue(res, 0, i_oprrest);
+	oprjoin = PQgetvalue(res, 0, i_oprjoin);
+	oprcanhash = PQgetvalue(res, 0, i_oprcanhash);
+	oprlsortop = PQgetvalue(res, 0, i_oprlsortop);
+	oprrsortop = PQgetvalue(res, 0, i_oprrsortop);
+	oprltcmpop = PQgetvalue(res, 0, i_oprltcmpop);
+	oprgtcmpop = PQgetvalue(res, 0, i_oprgtcmpop);
+
+	appendPQExpBuffer(details, "PROCEDURE = %s ",
+					  convertRegProcReference(oprcode));
+
+	appendPQExpBuffer(oprid, "%s (",
+					  oprinfo->oprname);
+
+	/*
+	 * right unary means there's a left arg and left unary means
+	 * there's a right arg
+	 */
+	if (strcmp(oprkind, "r") == 0 ||
+		strcmp(oprkind, "b") == 0)
+	{
+		if (g_fout->remoteVersion >= 70100)
+			name = oprleft;
+		else
+			name = fmtId(oprleft, force_quotes);
+		appendPQExpBuffer(details, ",\n\tLEFTARG = %s ", name);
+		appendPQExpBuffer(oprid, "%s", name);
+	}
+	else
+		appendPQExpBuffer(oprid, "NONE");
+
+	if (strcmp(oprkind, "l") == 0 ||
+		strcmp(oprkind, "b") == 0)
+	{
+		if (g_fout->remoteVersion >= 70100)
+			name = oprright;
+		else
+			name = fmtId(oprright, force_quotes);
+		appendPQExpBuffer(details, ",\n\tRIGHTARG = %s ", name);
+		appendPQExpBuffer(oprid, ", %s)", name);
+	}
+	else
+		appendPQExpBuffer(oprid, ", NONE)");
+
+	name = convertOperatorReference(oprcom, g_oprinfo, numOperators);
+	if (name)
+		appendPQExpBuffer(details, ",\n\tCOMMUTATOR = %s ", name);
+
+	name = convertOperatorReference(oprnegate, g_oprinfo, numOperators);
+	if (name)
+		appendPQExpBuffer(details, ",\n\tNEGATOR = %s ", name);
+
+	if (strcmp(oprcanhash, "t") == 0)
+		appendPQExpBuffer(details, ",\n\tHASHES");
+
+	name = convertRegProcReference(oprrest);
+	if (name)
+		appendPQExpBuffer(details, ",\n\tRESTRICT = %s ", name);
+
+	name = convertRegProcReference(oprjoin);
+	if (name)
+		appendPQExpBuffer(details, ",\n\tJOIN = %s ", name);
+
+	name = convertOperatorReference(oprlsortop, g_oprinfo, numOperators);
+	if (name)
+		appendPQExpBuffer(details, ",\n\tSORT1 = %s ", name);
+
+	name = convertOperatorReference(oprrsortop, g_oprinfo, numOperators);
+	if (name)
+		appendPQExpBuffer(details, ",\n\tSORT2 = %s ", name);
 
-		if (!(strcmp(oprinfo[i].oprrest, "-") == 0))
-			appendPQExpBuffer(restrictor, ",\n\tRESTRICT = %s ", oprinfo[i].oprrest);
+	name = convertOperatorReference(oprltcmpop, g_oprinfo, numOperators);
+	if (name)
+		appendPQExpBuffer(details, ",\n\tLTCMP = %s ", name);
 
-		if (!(strcmp(oprinfo[i].oprjoin, "-") == 0))
-			appendPQExpBuffer(join, ",\n\tJOIN = %s ", oprinfo[i].oprjoin);
+	name = convertOperatorReference(oprgtcmpop, g_oprinfo, numOperators);
+	if (name)
+		appendPQExpBuffer(details, ",\n\tGTCMP = %s ", name);
 
-		if (!(strcmp(oprinfo[i].oprlsortop, "0") == 0))
+	appendPQExpBuffer(delq, "DROP OPERATOR %s;\n",
+					  oprid->data);
+
+	appendPQExpBuffer(q, "CREATE OPERATOR %s (%s);\n",
+					  oprinfo->oprname, details->data);
+
+	ArchiveEntry(fout, oprinfo->oid, oprinfo->oprname,
+				 oprinfo->oprnamespace->nspname, oprinfo->usename,
+				 "OPERATOR", NULL,
+				 q->data, delq->data,
+				 NULL, NULL, NULL);
+
+	/*
+	 * Note: no need to dump operator comment; we expect that the comment
+	 * is attached to the underlying function instead.  (If the function
+	 * isn't getting dumped ... you lose.)
+	 */
+
+	PQclear(res);
+
+	destroyPQExpBuffer(query);
+	destroyPQExpBuffer(q);
+	destroyPQExpBuffer(delq);
+	destroyPQExpBuffer(oprid);
+	destroyPQExpBuffer(details);
+}
+
+/*
+ * Convert a function reference obtained from pg_operator
+ *
+ * Returns what to print, or NULL if function references is InvalidOid
+ *
+ * In 7.3 the input is a REGPROCEDURE display; we have to strip the
+ * argument-types part.  In prior versions, the input is a REGPROC display.
+ */
+static const char *
+convertRegProcReference(const char *proc)
+{
+	/* In all cases "-" means a null reference */
+	if (strcmp(proc, "-") == 0)
+		return NULL;
+
+	if (g_fout->remoteVersion >= 70300)
+	{
+		char   *name;
+		char   *paren;
+		bool	inquote;
+
+		name = strdup(proc);
+		/* find non-double-quoted left paren */
+		inquote = false;
+		for (paren = name; *paren; paren++)
 		{
-			name = findOprByOid(oprinfo, numOperators, oprinfo[i].oprlsortop);
-			if (name == NULL)
+			if (*paren == '(' && !inquote)
 			{
-				write_msg(NULL, "WARNING: operator \"%s\" (oid %s) not dumped\n",
-						  oprinfo[i].oprname, oprinfo[i].oid);
-				write_msg(NULL, "reason: oprlsortop (oid %s) not found\n",
-						  oprinfo[i].oprlsortop);
-				continue;
+				*paren = '\0';
+				break;
 			}
-			appendPQExpBuffer(sort1, ",\n\tSORT1 = %s ", name);
+			if (*paren == '"')
+				inquote = !inquote;
 		}
+		return name;
+	}
+
+	/* REGPROC before 7.3 does not quote its result */
+	return fmtId(proc, false);
+}
+
+/*
+ * Convert an operator cross-reference obtained from pg_operator
+ *
+ * Returns what to print, or NULL to print nothing
+ *
+ * In 7.3 the input is a REGOPERATOR display; we have to strip the
+ * argument-types part.  In prior versions, the input is just a
+ * numeric OID, which we search our operator list for.
+ */
+static const char *
+convertOperatorReference(const char *opr,
+						 OprInfo *g_oprinfo, int numOperators)
+{
+	char   *name;
+
+	/* In all cases "0" means a null reference */
+	if (strcmp(opr, "0") == 0)
+		return NULL;
+
+	if (g_fout->remoteVersion >= 70300)
+	{
+		char   *paren;
+		bool	inquote;
 
-		if (!(strcmp(oprinfo[i].oprrsortop, "0") == 0))
+		name = strdup(opr);
+		/* find non-double-quoted left paren */
+		inquote = false;
+		for (paren = name; *paren; paren++)
 		{
-			name = findOprByOid(oprinfo, numOperators, oprinfo[i].oprrsortop);
-			if (name == NULL)
+			if (*paren == '(' && !inquote)
 			{
-				write_msg(NULL, "WARNING: operator \"%s\" (oid %s) not dumped\n",
-						  oprinfo[i].oprname, oprinfo[i].oid);
-				write_msg(NULL, "reason: oprrsortop (oid %s) not found\n",
-						  oprinfo[i].oprrsortop);
-				continue;
+				*paren = '\0';
+				break;
 			}
-			appendPQExpBuffer(sort2, ",\n\tSORT2 = %s ", name);
+			if (*paren == '"')
+				inquote = !inquote;
 		}
-
-		resetPQExpBuffer(delq);
-		appendPQExpBuffer(delq, "DROP OPERATOR %s (%s",
-						  oprinfo[i].oprname,
-					   findTypeByOid(tinfo, numTypes, oprinfo[i].oprleft,
-									 zeroAsNone));
-		appendPQExpBuffer(delq, ", %s);\n",
-					  findTypeByOid(tinfo, numTypes, oprinfo[i].oprright,
-									zeroAsNone));
-
-		resetPQExpBuffer(q);
-		appendPQExpBuffer(q,
-						  "CREATE OPERATOR %s "
-						  "(PROCEDURE = %s %s%s%s%s%s%s%s%s%s);\n",
-						  oprinfo[i].oprname,
-						  oprinfo[i].oprcode,
-						  leftarg->data,
-						  rightarg->data,
-						  commutator->data,
-						  negator->data,
-						  restrictor->data,
-		  (strcmp(oprinfo[i].oprcanhash, "t") == 0) ? ",\n\tHASHES" : "",
-						  join->data,
-						  sort1->data,
-						  sort2->data);
-
-		ArchiveEntry(fout, oprinfo[i].oid, oprinfo[i].oprname, "OPERATOR", NULL,
-				q->data, delq->data, "", oprinfo[i].usename, NULL, NULL);
+		return name;
 	}
 
-	destroyPQExpBuffer(q);
-	destroyPQExpBuffer(delq);
-	destroyPQExpBuffer(leftarg);
-	destroyPQExpBuffer(rightarg);
-	destroyPQExpBuffer(commutator);
-	destroyPQExpBuffer(negator);
-	destroyPQExpBuffer(restrictor);
-	destroyPQExpBuffer(join);
-	destroyPQExpBuffer(sort1);
-	destroyPQExpBuffer(sort2);
+	name = findOprByOid(g_oprinfo, numOperators, opr);
+	if (name == NULL)
+		write_msg(NULL, "WARNING: cannot find operator with OID %s\n",
+				  opr);
+	return name;
 }
 
 /*
  * dumpAggs
  *	  writes out to fout the queries to create all the user-defined aggregates
- *
  */
 void
-dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs,
-		 TypeInfo *tinfo, int numTypes)
+dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs)
 {
 	int			i;
+
+	for (i = 0; i < numAggs; i++)
+	{
+		/* Dump only aggs in dumpable namespaces */
+		if (!agginfo[i].aggnamespace->dump)
+			continue;
+
+		dumpOneAgg(fout, &agginfo[i]);
+	}
+}
+
+/*
+ * dumpOneAgg
+ *	  write out a single aggregate definition
+ */
+static void
+dumpOneAgg(Archive *fout, AggInfo *agginfo)
+{
+	PQExpBuffer query = createPQExpBuffer();
 	PQExpBuffer q = createPQExpBuffer();
 	PQExpBuffer delq = createPQExpBuffer();
 	PQExpBuffer aggSig = createPQExpBuffer();
 	PQExpBuffer details = createPQExpBuffer();
+	PGresult   *res;
+	int			ntups;
+	int			i_aggtransfn;
+	int			i_aggfinalfn;
+	int			i_aggtranstype;
+	int			i_aggbasetype;
+	int			i_agginitval;
+	int			i_convertok;
+	const char *aggtransfn;
+	const char *aggfinalfn;
+	const char *aggtranstype;
+	const char *aggbasetype;
+	const char *agginitval;
+	bool		convertok;
+	bool		anybasetype;
+
+	/* Make sure we are in proper schema */
+	selectSourceSchema(agginfo->aggnamespace->nspname);
+
+	/* Get aggregate-specific details */
+	if (g_fout->remoteVersion >= 70300)
+	{
+		appendPQExpBuffer(query, "SELECT aggtransfn, "
+						  "aggfinalfn, aggtranstype::regtype, "
+						  "proargtypes[0]::regtype as aggbasetype, "
+						  "agginitval, "
+						  "'t'::boolean as convertok "
+						  "from pg_aggregate a, pg_proc p "
+						  "where a.aggfnoid = p.oid "
+						  "and p.oid = '%s'::oid",
+						  agginfo->oid);
+	}
+	else if (g_fout->remoteVersion >= 70100)
+	{
+		appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
+						  "format_type(aggtranstype, NULL) as aggtranstype, "
+						  "CASE WHEN aggbasetype = 0 THEN '-' "
+						  "ELSE format_type(aggbasetype, NULL) END as aggbasetype, "
+						  "agginitval, 't'::boolean as convertok "
+						  "from pg_aggregate "
+						  "where oid = '%s'::oid",
+						  agginfo->oid);
+	}
+	else
+	{
+		appendPQExpBuffer(query, "SELECT aggtransfn1 as aggtransfn, "
+						  "aggfinalfn, "
+						  "(select typname from pg_type where oid = aggtranstype1) as aggtranstype, "
+						  "CASE WHEN aggbasetype = 0 THEN '-'::name "
+						  "ELSE (select typname from pg_type where oid = aggbasetype) END as aggbasetype, "
+						  "agginitval1 as agginitval, "
+						  "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) as convertok "
+						  "from pg_aggregate "
+						  "where oid = '%s'::oid",
+						  agginfo->oid);
+	}
 
-	for (i = 0; i < numAggs; i++)
+	res = PQexec(g_conn, query->data);
+	if (!res ||
+		PQresultStatus(res) != PGRES_TUPLES_OK)
 	{
-		char	   *name;
+		write_msg(NULL, "query to obtain list of aggregate functions failed: %s",
+				  PQerrorMessage(g_conn));
+		exit_nicely();
+	}
 
-		resetPQExpBuffer(details);
+	/* Expecting a single result only */
+	ntups = PQntuples(res);
+	if (ntups != 1)
+	{
+		write_msg(NULL, "Got %d rows instead of one from: %s",
+				  ntups, query->data);
+		exit_nicely();
+	}
 
-		/* skip all the builtin oids */
-		if (oidle(atooid(agginfo[i].oid), g_last_builtin_oid))
-			continue;
+	i_aggtransfn = PQfnumber(res, "aggtransfn");
+	i_aggfinalfn = PQfnumber(res, "aggfinalfn");
+	i_aggtranstype = PQfnumber(res, "aggtranstype");
+	i_aggbasetype = PQfnumber(res, "aggbasetype");
+	i_agginitval = PQfnumber(res, "agginitval");
+	i_convertok = PQfnumber(res, "convertok");
 
-		resetPQExpBuffer(aggSig);
-		appendPQExpBuffer(aggSig, "%s(%s)", agginfo[i].aggname,
-						  findTypeByOid(tinfo, numTypes,
-										agginfo[i].aggbasetype,
-										zeroAsStar + useBaseTypeName));
+	aggtransfn = PQgetvalue(res, 0, i_aggtransfn);
+	aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
+	aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
+	aggbasetype = PQgetvalue(res, 0, i_aggbasetype);
+	agginitval = PQgetvalue(res, 0, i_agginitval);
+	convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't');
 
-		if (!agginfo[i].convertok)
-		{
-			write_msg(NULL, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
-					  aggSig->data);
+	anybasetype = (strcmp(aggbasetype, "-") == 0);
 
-			resetPQExpBuffer(q);
-			appendPQExpBuffer(q, "-- WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
-							  aggSig->data);
-			ArchiveEntry(fout, agginfo[i].oid, aggSig->data, "WARNING", NULL,
-			 q->data, "" /* Del */ , "", agginfo[i].usename, NULL, NULL);
-			continue;
-		}
+	appendPQExpBuffer(aggSig, "%s",
+					  fmtId(agginfo->aggname, force_quotes));
 
-		name = findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype,
-							 zeroAsAny + useBaseTypeName);
-		if (name == NULL)
-		{
-			write_msg(NULL, "WARNING: aggregate function \"%s\" (oid %s) not dumped\n",
-					  agginfo[i].aggname, agginfo[i].oid);
-			write_msg(NULL, "reason: aggbasetype (oid %s) not found\n",
-					  agginfo[i].aggbasetype);
+	/* If using regtype or format_type, name is already quoted */
+	if (g_fout->remoteVersion >= 70100)
+	{
+		if (anybasetype)
+			appendPQExpBuffer(aggSig, "(*)");
+		else
+			appendPQExpBuffer(aggSig, "(%s)", aggbasetype);
+	}
+	else
+	{
+		if (anybasetype)
+			appendPQExpBuffer(aggSig, "(*)");
+		else
+			appendPQExpBuffer(aggSig, "(%s)",
+							  fmtId(aggbasetype, force_quotes));
+	}
 
-			resetPQExpBuffer(q);
-			appendPQExpBuffer(q, "-- WARNING: aggregate function \"%s\" (oid %s) not dumped\n", agginfo[i].aggname, agginfo[i].oid);
-			appendPQExpBuffer(q, "-- reason: aggbasetype (oid %s) not found\n", agginfo[i].aggbasetype);
-			ArchiveEntry(fout, agginfo[i].oid, aggSig->data, "WARNING", NULL,
-			 q->data, "" /* Del */ , "", agginfo[i].usename, NULL, NULL);
-			continue;
-		}
-		appendPQExpBuffer(details, "BASETYPE = %s, ", name);
+	if (!convertok)
+	{
+		write_msg(NULL, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
+				  aggSig->data);
+
+		appendPQExpBuffer(q, "-- WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
+						  aggSig->data);
+		ArchiveEntry(fout, agginfo->oid, aggSig->data,
+					 agginfo->aggnamespace->nspname, agginfo->usename,
+					 "WARNING", NULL,
+					 q->data, "" /* Del */ ,
+					 NULL, NULL, NULL);
+		return;
+	}
 
-		name = findTypeByOid(tinfo, numTypes, agginfo[i].aggtranstype,
-							 zeroAsOpaque + useBaseTypeName);
-		if (name == NULL)
-		{
-			write_msg(NULL, "WARNING: aggregate function \"%s\" (oid %s) not dumped\n",
-					  agginfo[i].aggname, agginfo[i].oid);
-			write_msg(NULL, "reason: aggtranstype (oid %s) not found\n",
-					  agginfo[i].aggtranstype);
+	if (g_fout->remoteVersion >= 70300)
+	{
+		/* If using 7.3's regproc or regtype, data is already quoted */
+		appendPQExpBuffer(details, "BASETYPE = %s, SFUNC = %s, STYPE = %s",
+						  anybasetype ? "'any'" : aggbasetype,
+						  aggtransfn,
+						  aggtranstype);
+	}
+	else if (g_fout->remoteVersion >= 70100)
+	{
+		/* format_type quotes, regproc does not */
+		appendPQExpBuffer(details, "BASETYPE = %s, SFUNC = %s, STYPE = %s",
+						  anybasetype ? "'any'" : aggbasetype,
+						  fmtId(aggtransfn, force_quotes),
+						  aggtranstype);
+	}
+	else
+	{
+		/* need quotes all around */
+		appendPQExpBuffer(details, "BASETYPE = %s, ",
+						  anybasetype ? "'any'" :
+						  fmtId(aggbasetype, force_quotes));
+		appendPQExpBuffer(details, "SFUNC = %s, ",
+						  fmtId(aggtransfn, force_quotes));
+		appendPQExpBuffer(details, "STYPE = %s",
+						  fmtId(aggtranstype, force_quotes));
+	}
 
-			resetPQExpBuffer(q);
-			appendPQExpBuffer(q, "-- WARNING: aggregate function \"%s\" (oid %s) not dumped\n", agginfo[i].aggname, agginfo[i].oid);
-			appendPQExpBuffer(q, "-- reason: aggtranstype (oid %s) not found\n", agginfo[i].aggtranstype);
-			ArchiveEntry(fout, agginfo[i].oid, aggSig->data, "WARNING", NULL,
-			 q->data, "" /* Del */ , "", agginfo[i].usename, NULL, NULL);
-			continue;
-		}
-		appendPQExpBuffer(details,
-						  "SFUNC = %s, STYPE = %s",
-						  agginfo[i].aggtransfn, name);
+	if (!PQgetisnull(res, 0, i_agginitval))
+	{
+		appendPQExpBuffer(details, ", INITCOND = ");
+		formatStringLiteral(details, agginitval, CONV_ALL);
+	}
 
-		if (agginfo[i].agginitval)
-		{
-			appendPQExpBuffer(details, ", INITCOND = ");
-			formatStringLiteral(details, agginfo[i].agginitval, CONV_ALL);
-		}
+	if (strcmp(aggfinalfn, "-") != 0)
+	{
+		appendPQExpBuffer(details, ", FINALFUNC = %s",
+						  aggfinalfn);
+	}
 
-		if (!(strcmp(agginfo[i].aggfinalfn, "-") == 0))
-			appendPQExpBuffer(details, ", FINALFUNC = %s",
-							  agginfo[i].aggfinalfn);
+	appendPQExpBuffer(delq, "DROP AGGREGATE %s;\n", aggSig->data);
 
-		resetPQExpBuffer(delq);
-		appendPQExpBuffer(delq, "DROP AGGREGATE %s;\n", aggSig->data);
+	appendPQExpBuffer(q, "CREATE AGGREGATE %s ( %s );\n",
+					  fmtId(agginfo->aggname, force_quotes),
+					  details->data);
 
-		resetPQExpBuffer(q);
-		appendPQExpBuffer(q, "CREATE AGGREGATE %s ( %s );\n",
-						  agginfo[i].aggname,
-						  details->data);
+	ArchiveEntry(fout, agginfo->oid, aggSig->data,
+				 agginfo->aggnamespace->nspname, agginfo->usename,
+				 "AGGREGATE", NULL,
+				 q->data, delq->data,
+				 NULL, NULL, NULL);
 
-		ArchiveEntry(fout, agginfo[i].oid, aggSig->data, "AGGREGATE", NULL,
-				q->data, delq->data, "", agginfo[i].usename, NULL, NULL);
+	/*** Dump Aggregate Comments ***/
 
-		/*** Dump Aggregate Comments ***/
+	resetPQExpBuffer(q);
+	appendPQExpBuffer(q, "AGGREGATE %s", aggSig->data);
+	if (g_fout->remoteVersion >= 70300)
+		dumpComment(fout, q->data,
+					agginfo->aggnamespace->nspname, agginfo->usename,
+					agginfo->oid, "pg_proc", 0, NULL);
+	else
+		dumpComment(fout, q->data,
+					agginfo->aggnamespace->nspname, agginfo->usename,
+					agginfo->oid, "pg_aggregate", 0, NULL);
 
-		resetPQExpBuffer(q);
-		appendPQExpBuffer(q, "AGGREGATE %s", aggSig->data);
-		if (g_fout->remoteVersion < 70300)
-			dumpComment(fout, q->data, agginfo[i].oid, "pg_aggregate",
-						0, NULL);
-		else
-			dumpComment(fout, q->data, agginfo[i].oid, "pg_proc",
-						0, NULL);
-	}
+	PQclear(res);
 
+	destroyPQExpBuffer(query);
 	destroyPQExpBuffer(q);
 	destroyPQExpBuffer(delq);
 	destroyPQExpBuffer(aggSig);
 	destroyPQExpBuffer(details);
 }
 
+
 /*
  * These are some support functions to fix the acl problem of pg_dump
  *
@@ -4237,310 +4161,345 @@ dumpACL(Archive *fout, TableInfo *tbinfo)
 
 	free(aclbuf);
 
-	if (tbinfo->viewdef != NULL)
+	if (tbinfo->viewoid != NULL)
 		objoid = tbinfo->viewoid;
 	else
 		objoid = tbinfo->oid;
 
-	ArchiveEntry(fout, objoid, tbinfo->relname, "ACL",
-				 NULL, sql->data, "", "", "", NULL, NULL);
+	ArchiveEntry(fout, objoid, tbinfo->relname,
+				 tbinfo->relnamespace->nspname,
+				 tbinfo->usename, "ACL", NULL,
+				 sql->data, "", NULL, NULL, NULL);
 
 	destroyPQExpBuffer(sql);
 }
 
-static void
-_dumpTableAttr70(TableInfo *tblinfo, int i, int j, PQExpBuffer q)
+/*
+ * dumpTables:
+ *	  write out to fout the declarations (not data) of all user-defined tables
+ */
+void
+dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
+		   const bool aclsSkip, const bool schemaOnly, const bool dataOnly)
 {
-	int32		tmp_typmod;
-	int			precision;
-	int			scale;
+	int			i;
 
-	/* Show lengths on bpchar and varchar */
-	if (!strcmp(tblinfo[i].typnames[j], "bpchar"))
+	/* Dump sequences first, in case they are referenced in table defn's */
+	for (i = 0; i < numTables; i++)
 	{
-		int			len = (tblinfo[i].atttypmod[j] - VARHDRSZ);
+		TableInfo	   *tbinfo = &tblinfo[i];
 
-		appendPQExpBuffer(q, "character");
-		if (len > 1)
-			appendPQExpBuffer(q, "(%d)",
-							  tblinfo[i].atttypmod[j] - VARHDRSZ);
-	}
-	else if (!strcmp(tblinfo[i].typnames[j], "varchar"))
-	{
-		appendPQExpBuffer(q, "character varying");
-		if (tblinfo[i].atttypmod[j] != -1)
+		if (tbinfo->relkind != RELKIND_SEQUENCE)
+			continue;
+		if (tbinfo->dump)
 		{
-			appendPQExpBuffer(q, "(%d)",
-							  tblinfo[i].atttypmod[j] - VARHDRSZ);
+			dumpOneSequence(fout, tbinfo, schemaOnly, dataOnly);
+			if (!dataOnly && !aclsSkip)
+				dumpACL(fout, tbinfo);
 		}
 	}
-	else if (!strcmp(tblinfo[i].typnames[j], "numeric"))
+
+	if (!dataOnly)
 	{
-		appendPQExpBuffer(q, "numeric");
-		if (tblinfo[i].atttypmod[j] != -1)
+		for (i = 0; i < numTables; i++)
 		{
-			tmp_typmod = tblinfo[i].atttypmod[j] - VARHDRSZ;
-			precision = (tmp_typmod >> 16) & 0xffff;
-			scale = tmp_typmod & 0xffff;
-			appendPQExpBuffer(q, "(%d,%d)",
-							  precision, scale);
-		}
-	}
+			TableInfo	   *tbinfo = &tblinfo[i];
 
-	/*
-	 * char is an internal single-byte data type; Let's make sure we force
-	 * it through with quotes. - thomas 1998-12-13
-	 */
-	else if (!strcmp(tblinfo[i].typnames[j], "char"))
-	{
-		appendPQExpBuffer(q, "%s",
-						  fmtId(tblinfo[i].typnames[j], true));
-	}
-	else
-	{
-		appendPQExpBuffer(q, "%s",
-						  fmtId(tblinfo[i].typnames[j], false));
+			if (tbinfo->relkind == RELKIND_SEQUENCE) /* already dumped */
+				continue;
+
+			if (tbinfo->dump)
+			{
+				dumpOneTable(fout, tbinfo, tblinfo);
+				if (!aclsSkip)
+					dumpACL(fout, tbinfo);
+			}
+		}
 	}
 }
 
 /*
- * dumpTables:
- *	  write out to fout all the user-define tables
+ * dumpOneTable
+ *	  write the declaration (not data) of one user-defined table or view
  */
-
-void
-dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
-		   const char *tablename, const bool aclsSkip,
-		   const bool schemaOnly, const bool dataOnly)
+static void
+dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
 {
-	int			i,
-				j,
-				k;
+	PQExpBuffer query = createPQExpBuffer();
 	PQExpBuffer q = createPQExpBuffer();
 	PQExpBuffer delq = createPQExpBuffer();
-	char	   *serialSeq = NULL;		/* implicit sequence name created
-										 * by SERIAL datatype */
-	const char *serialSeqSuffix = "_id_seq";	/* suffix for implicit
-												 * SERIAL sequences */
-	char	  **parentRels;		/* list of names of parent relations */
+	PGresult   *res;
 	int			numParents;
+	int		   *parentIndexes;
 	int			actual_atts;	/* number of attrs in this CREATE statment */
 	char	   *reltypename;
 	char	   *objoid;
 	const char *((*commentDeps)[]);
+	int			j,
+				k;
 
-	/* First - dump SEQUENCEs */
-	if (tablename && strlen(tablename) > 0)
-	{
-		/* XXX this code only works for serial columns named "id" */
-		/* We really need dependency analysis! */
-		serialSeq = malloc(strlen(tablename) + strlen(serialSeqSuffix) + 1);
-		strcpy(serialSeq, tablename);
-		strcat(serialSeq, serialSeqSuffix);
-	}
-	for (i = 0; i < numTables; i++)
-	{
-		if (tblinfo[i].relkind != RELKIND_SEQUENCE)
-			continue;
-		if (!tablename || (!strcmp(tblinfo[i].relname, tablename))
-			|| (serialSeq && !strcmp(tblinfo[i].relname, serialSeq)))
-		{
-			/* becomeUser(fout, tblinfo[i].usename); */
-			dumpSequence(fout, tblinfo[i], schemaOnly, dataOnly);
-			if (!aclsSkip)
-				dumpACL(fout, &tblinfo[i]);
-		}
-	}
-	if (serialSeq)
-		free(serialSeq);
+	/* Make sure we are in proper schema */
+	selectSourceSchema(tbinfo->relnamespace->nspname);
 
-	for (i = 0; i < numTables; i++)
+	/* Is it a table or a view? */
+	if (tbinfo->relkind == RELKIND_VIEW)
 	{
-		if (tblinfo[i].relkind == RELKIND_SEQUENCE)		/* already dumped */
-			continue;
+		char	   *viewdef;
 
-		if (!tablename || (!strcmp(tblinfo[i].relname, tablename)) || (strlen(tablename) == 0))
-		{
-
-			resetPQExpBuffer(delq);
-			resetPQExpBuffer(q);
+		reltypename = "VIEW";
 
-			/* Use the view definition if there is one */
-			if (tblinfo[i].viewdef != NULL)
-			{
-				reltypename = "VIEW";
-				objoid = tblinfo[i].viewoid;
-				appendPQExpBuffer(delq, "DROP VIEW %s;\n", fmtId(tblinfo[i].relname, force_quotes));
-				appendPQExpBuffer(q, "CREATE VIEW %s as %s\n", fmtId(tblinfo[i].relname, force_quotes), tblinfo[i].viewdef);
+		/* Fetch the view definition */
+		if (g_fout->remoteVersion >= 70300)
+		{
+			/* Beginning in 7.3, viewname is not unique; use OID */
+			appendPQExpBuffer(query, "SELECT pg_get_viewdef(ev_class) as viewdef, "
+							  "oid as view_oid"
+							  " from pg_rewrite where"
+							  " ev_class = '%s'::oid and"
+							  " rulename = '_RETURN';",
+							  tbinfo->oid);
+		}
+		else
+		{
+			appendPQExpBuffer(query, "SELECT definition as viewdef, "
+							  "(select oid from pg_rewrite where "
+							  " rulename=('_RET' || viewname)::name) as view_oid"
+							  " from pg_views where viewname = ");
+			formatStringLiteral(query, tbinfo->relname, CONV_ALL);
+			appendPQExpBuffer(query, ";");
+		}
 
-				/*
-				 * Views can have default values -- however, they must be
-				 * specified in an ALTER TABLE command after the view has
-				 * been created, not in the view definition itself.
-				 */
-				for (j = 0; j < tblinfo[i].numatts; j++)
-				{
-					if (tblinfo[i].adef_expr[j] != NULL && tblinfo[i].inhAttrDef[j] == 0) {
-						appendPQExpBuffer(q, "ALTER TABLE %s ", fmtId(tblinfo[i].relname, force_quotes));
-						appendPQExpBuffer(q, "ALTER COLUMN %s SET DEFAULT %s;\n",
-										  fmtId(tblinfo[i].attnames[j], force_quotes),
-										  tblinfo[i].adef_expr[j]);
-					}
-				}
+		res = PQexec(g_conn, query->data);
+		if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			write_msg(NULL, "query to obtain definition of view \"%s\" failed: %s",
+					  tbinfo->relname, PQerrorMessage(g_conn));
+			exit_nicely();
+		}
 
-				commentDeps = malloc(sizeof(char *) * 2);
-				(*commentDeps)[0] = strdup(objoid);
-				(*commentDeps)[1] = NULL;		/* end of list */
-			}
+		if (PQntuples(res) != 1)
+		{
+			if (PQntuples(res) < 1)
+				write_msg(NULL, "query to obtain definition of view \"%s\" returned no data\n",
+						  tbinfo->relname);
 			else
-			{
-				reltypename = "TABLE";
-				objoid = tblinfo[i].oid;
-				commentDeps = NULL;
-				parentRels = tblinfo[i].parentRels;
-				numParents = tblinfo[i].numParents;
-
-				appendPQExpBuffer(delq, "DROP TABLE %s;\n", fmtId(tblinfo[i].relname, force_quotes));
+				write_msg(NULL, "query to obtain definition of view \"%s\" returned more than one definition\n",
+						  tbinfo->relname);
+			exit_nicely();
+		}
 
-				appendPQExpBuffer(q, "CREATE TABLE %s (\n\t", fmtId(tblinfo[i].relname, force_quotes));
-				actual_atts = 0;
-				for (j = 0; j < tblinfo[i].numatts; j++)
-				{
-					/* Is this one of the table's own attrs ? */
-					if (tblinfo[i].inhAttrs[j] == 0)
-					{
-						/* Format properly if not first attr */
-						if (actual_atts > 0)
-							appendPQExpBuffer(q, ",\n\t");
+		if (PQgetisnull(res, 0, 1))
+		{
+			write_msg(NULL, "query to obtain definition of view \"%s\" returned NULL oid\n",
+					  tbinfo->relname);
+			exit_nicely();
+		}
 
-						/* Attr name & type */
-						appendPQExpBuffer(q, "%s ", fmtId(tblinfo[i].attnames[j], force_quotes));
+		viewdef = PQgetvalue(res, 0, 0);
 
-						if (g_fout->remoteVersion >= 70100)
-							appendPQExpBuffer(q, "%s", tblinfo[i].atttypedefns[j]);
-						else
-							_dumpTableAttr70(tblinfo, i, j, q);
+		if (strlen(viewdef) == 0)
+		{
+			write_msg(NULL, "definition of view \"%s\" appears to be empty (length zero)\n",
+					  tbinfo->relname);
+			exit_nicely();
+		}
 
-						/* Default value */
-						if (tblinfo[i].adef_expr[j] != NULL && tblinfo[i].inhAttrDef[j] == 0)
-							appendPQExpBuffer(q, " DEFAULT %s",
-											  tblinfo[i].adef_expr[j]);
+		/* We use the OID of the view rule as the object OID */
+		objoid = strdup(PQgetvalue(res, 0, 1));
+		/* Save it for use by dumpACL, too */
+		tbinfo->viewoid = objoid;
 
-						/* Not Null constraint */
-						if (tblinfo[i].notnull[j] && tblinfo[i].inhNotNull[j] == 0)
-							appendPQExpBuffer(q, " NOT NULL");
+		appendPQExpBuffer(delq, "DROP VIEW %s;\n",
+						  fmtId(tbinfo->relname, force_quotes));
+		appendPQExpBuffer(q, "CREATE VIEW %s AS %s\n",
+						  fmtId(tbinfo->relname, force_quotes), viewdef);
 
-						actual_atts++;
-					}
-				}
+		PQclear(res);
 
+		/*
+		 * Views can have default values -- however, they must be
+		 * specified in an ALTER TABLE command after the view has
+		 * been created, not in the view definition itself.
+		 */
+		for (j = 0; j < tbinfo->numatts; j++)
+		{
+			if (tbinfo->adef_expr[j] != NULL && !tbinfo->inhAttrDef[j])
+			{
+				appendPQExpBuffer(q, "ALTER TABLE %s ",
+								  fmtId(tbinfo->relname, force_quotes));
+				appendPQExpBuffer(q, "ALTER COLUMN %s SET DEFAULT %s;\n",
+								  fmtId(tbinfo->attnames[j], force_quotes),
+								  tbinfo->adef_expr[j]);
+			}
+		}
 
+		commentDeps = malloc(sizeof(char *) * 2);
+		(*commentDeps)[0] = strdup(objoid);
+		(*commentDeps)[1] = NULL;		/* end of list */
+	}
+	else
+	{
+		reltypename = "TABLE";
+		objoid = tbinfo->oid;
+		commentDeps = NULL;
+		numParents = tbinfo->numParents;
+		parentIndexes = tbinfo->parentIndexes;
 
-				/* Put the CONSTRAINTS inside the table def */
-				for (k = 0; k < tblinfo[i].ncheck; k++)
-				{
-					if (actual_atts + k > 0)
-						appendPQExpBuffer(q, ",\n\t");
+		appendPQExpBuffer(delq, "DROP TABLE %s;\n",
+						  fmtId(tbinfo->relname, force_quotes));
 
-					appendPQExpBuffer(q, "%s",
-									  tblinfo[i].check_expr[k]);
-				}
+		appendPQExpBuffer(q, "CREATE TABLE %s (\n\t",
+						  fmtId(tbinfo->relname, force_quotes));
+		actual_atts = 0;
+		for (j = 0; j < tbinfo->numatts; j++)
+		{
+			/* Is this one of the table's own attrs ? */
+			if (!tbinfo->inhAttrs[j])
+			{
+				/* Format properly if not first attr */
+				if (actual_atts > 0)
+					appendPQExpBuffer(q, ",\n\t");
 
-				/*
-				 * Primary Key: In versions of PostgreSQL prior to 7.2, we
-				 * needed to include the primary key in the table definition.
-				 * However, this is not ideal because it creates an index
-				 * on the table, which makes COPY slower. As of release 7.2,
-				 * we can add primary keys to a table after is has been created,
-				 * using ALTER TABLE ; see dumpIndexes() for more information.
-				 * Therefore, we ignore primary keys in this function.
-				 */
+				/* Attr name & type */
+				appendPQExpBuffer(q, "%s ",
+								  fmtId(tbinfo->attnames[j], force_quotes));
 
-				appendPQExpBuffer(q, "\n)");
+				/* If no format_type, fake it */
+				if (g_fout->remoteVersion >= 70100)
+					appendPQExpBuffer(q, "%s", tbinfo->atttypnames[j]);
+				else
+					appendPQExpBuffer(q, "%s",
+									  myFormatType(tbinfo->atttypnames[j],
+												   tbinfo->atttypmod[j]));
 
-				if (numParents > 0)
-				{
-					appendPQExpBuffer(q, "\nINHERITS (");
-					for (k = 0; k < numParents; k++)
-					{
-						appendPQExpBuffer(q, "%s%s",
-										  (k > 0) ? ", " : "",
-									 fmtId(parentRels[k], force_quotes));
-					}
-					appendPQExpBuffer(q, ")");
-				}
+				/* Default value */
+				if (tbinfo->adef_expr[j] != NULL && !tbinfo->inhAttrDef[j])
+					appendPQExpBuffer(q, " DEFAULT %s",
+									  tbinfo->adef_expr[j]);
 
-				if (!tblinfo[i].hasoids)
-					appendPQExpBuffer(q, " WITHOUT OIDS");
+				/* Not Null constraint */
+				if (tbinfo->notnull[j] && !tbinfo->inhNotNull[j])
+					appendPQExpBuffer(q, " NOT NULL");
 
-				appendPQExpBuffer(q, ";\n");
+				actual_atts++;
 			}
+		}
 
-			if (!dataOnly)
-			{
-
-				ArchiveEntry(fout, objoid, tblinfo[i].relname,
-							 reltypename, NULL, q->data, delq->data, "", tblinfo[i].usename,
-							 NULL, NULL);
+		/*
+		 * Add non-inherited CHECK constraints, if any. If a
+		 * constraint matches by name and condition with a constraint
+		 * belonging to a parent class (OR conditions match and both names
+		 * start with '$'), we assume it was inherited.
+		 */
+		if (tbinfo->ncheck > 0)
+		{
+			PGresult   *res2;
+			int			i_rcname,
+						i_rcsrc;
+			int			ntups2;
 
-				if (!aclsSkip)
-					dumpACL(fout, &tblinfo[i]);
+			if (g_verbose)
+				write_msg(NULL, "finding CHECK constraints for table %s\n",
+						  tbinfo->relname);
 
+			resetPQExpBuffer(query);
+			appendPQExpBuffer(query, "SELECT rcname, rcsrc from pg_relcheck "
+							  " where rcrelid = '%s'::oid "
+							  "   and not exists "
+							  "  (select 1 from pg_relcheck as c, "
+							  "    pg_inherits as i "
+							  "    where i.inhrelid = pg_relcheck.rcrelid "
+							  "      and (c.rcname = pg_relcheck.rcname "
+							  "          or (c.rcname[0] = '$' "
+							  "              and pg_relcheck.rcname[0] = '$')"
+							  "          )"
+							  "      and c.rcsrc = pg_relcheck.rcsrc "
+							  "      and c.rcrelid = i.inhparent) "
+							  " order by rcname ",
+							  tbinfo->oid);
+			res2 = PQexec(g_conn, query->data);
+			if (!res2 ||
+				PQresultStatus(res2) != PGRES_TUPLES_OK)
+			{
+				write_msg(NULL, "query to obtain check constraints failed: %s", PQerrorMessage(g_conn));
+				exit_nicely();
 			}
-
-			/* Dump Field Comments */
-
-			for (j = 0; j < tblinfo[i].numatts; j++)
+			ntups2 = PQntuples(res2);
+			if (ntups2 > tbinfo->ncheck)
 			{
-				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].oid,
-							"pg_class", j + 1, commentDeps);
+				write_msg(NULL, "expected %d check constraints on table \"%s\" but found %d\n",
+						  tbinfo->ncheck, tbinfo->relname, ntups2);
+				write_msg(NULL, "(The system catalogs might be corrupted.)\n");
+				exit_nicely();
 			}
 
-			/* Dump Table Comments */
+			i_rcname = PQfnumber(res2, "rcname");
+			i_rcsrc = PQfnumber(res2, "rcsrc");
 
-			resetPQExpBuffer(q);
-			appendPQExpBuffer(q, "%s %s", reltypename, fmtId(tblinfo[i].relname, force_quotes));
-			dumpComment(fout, q->data, tblinfo[i].oid,
-						"pg_class", 0, commentDeps);
+			for (j = 0; j < ntups2; j++)
+			{
+				const char *name = PQgetvalue(res2, j, i_rcname);
+				const char *expr = PQgetvalue(res2, j, i_rcsrc);
+
+				if (actual_atts + j > 0)
+					appendPQExpBuffer(q, ",\n\t");
 
+				if (name[0] != '$')
+					appendPQExpBuffer(q, "CONSTRAINT %s ",
+									  fmtId(name, force_quotes));
+				appendPQExpBuffer(q, "CHECK (%s)", expr);
+			}
+			PQclear(res2);
 		}
-	}
 
-	destroyPQExpBuffer(q);
-	destroyPQExpBuffer(delq);
-}
+		/*
+		 * Primary Key: In versions of PostgreSQL prior to 7.2, we
+		 * needed to include the primary key in the table definition.
+		 * However, this is not ideal because it creates an index
+		 * on the table, which makes COPY slower. As of release 7.2,
+		 * we can add primary keys to a table after it has been created,
+		 * using ALTER TABLE; see dumpIndexes() for more information.
+		 * Therefore, we ignore primary keys in this function.
+		 */
 
-static PQExpBuffer
-getPKconstraint(TableInfo *tblInfo, IndInfo *indInfo)
-{
-	PQExpBuffer pkBuf = createPQExpBuffer();
-	int			k;
+		appendPQExpBuffer(q, "\n)");
 
-	appendPQExpBuffer(pkBuf, "Constraint %s Primary Key (",
-					  tblInfo->primary_key_name);
+		if (numParents > 0)
+		{
+			appendPQExpBuffer(q, "\nINHERITS (");
+			for (k = 0; k < numParents; k++)
+			{
+				TableInfo  *parentRel = &g_tblinfo[parentIndexes[k]];
 
-	for (k = 0; k < indInfo->indnkeys; k++)
-	{
-		int			indkey;
-		const char *attname;
+				if (k > 0)
+					appendPQExpBuffer(q, ", ");
+				if (parentRel->relnamespace != tbinfo->relnamespace)
+					appendPQExpBuffer(q, "%s.",
+									  fmtId(parentRel->relnamespace->nspname,
+											force_quotes));
+				appendPQExpBuffer(q, "%s",
+								  fmtId(parentRel->relname, force_quotes));
+			}
+			appendPQExpBuffer(q, ")");
+		}
 
-		indkey = atoi(indInfo->indkey[k]);
-		if (indkey == InvalidAttrNumber)
-			break;
-		attname = getAttrName(indkey, tblInfo);
+		if (!tbinfo->hasoids)
+			appendPQExpBuffer(q, " WITHOUT OIDS");
 
-		appendPQExpBuffer(pkBuf, "%s%s",
-						  (k == 0) ? "" : ", ",
-						  fmtId(attname, force_quotes));
+		appendPQExpBuffer(q, ";\n");
 	}
 
-	appendPQExpBuffer(pkBuf, ")");
+	ArchiveEntry(fout, objoid, tbinfo->relname,
+				 tbinfo->relnamespace->nspname, tbinfo->usename,
+				 reltypename, NULL, q->data, delq->data,
+				 NULL, NULL, NULL);
 
-	return pkBuf;
+	/* Dump Table Comments */
+	dumpTableComment(fout, tbinfo, reltypename, commentDeps);
+
+	destroyPQExpBuffer(query);
+	destroyPQExpBuffer(q);
+	destroyPQExpBuffer(delq);
 }
 
 /*
@@ -4580,149 +4539,154 @@ getAttrName(int attrnum, TableInfo *tblInfo)
 
 /*
  * dumpIndexes:
- *	  write out to fout all the user-defined indexes
+ *	  write out to fout all the user-defined indexes for dumpable tables
  */
 void
-dumpIndexes(Archive *fout, IndInfo *indinfo, int numIndexes,
-			TableInfo *tblinfo, int numTables, const char *tablename)
+dumpIndexes(Archive *fout, TableInfo *tblinfo, int numTables)
 {
-	int			i;
-	int			tableInd;
+	int			i,
+				j;
+	PQExpBuffer query = createPQExpBuffer();
 	PQExpBuffer q = createPQExpBuffer();
 	PQExpBuffer delq = createPQExpBuffer();
-	PQExpBuffer id1 = createPQExpBuffer();
+	PGresult   *res;
+	int			ntups;
+	int			i_indexreloid;
+	int			i_indexrelname;
+	int			i_indexdef;
+	int			i_indisprimary;
+	int			i_indkey;
+	int			i_indnkeys;
 
-	for (i = 0; i < numIndexes; i++)
+	for (i = 0; i < numTables; i++)
 	{
-		if (tablename && tablename[0] &&
-			(strcmp(indinfo[i].indrelname, tablename) != 0))
-			continue;
-
-		tableInd = findTableByName(tblinfo, numTables,
-								   indinfo[i].indrelname);
-		if (tableInd < 0)
-		{
-			write_msg(NULL, "dumpIndexes(): failed sanity check, table %s was not found\n",
-					  indinfo[i].indrelname);
-			exit_nicely();
-		}
-
-		/* Handle PK indexes */
-		if (strcmp(indinfo[i].indisprimary, "t") == 0)
-		{
-			PQExpBuffer consDef = getPKconstraint(&tblinfo[tableInd], &indinfo[i]);
+		TableInfo  *tbinfo = &tblinfo[i];
 
-			resetPQExpBuffer(q);
-
-			appendPQExpBuffer(q, "Alter Table %s Add %s;",
-							  fmtId(tblinfo[tableInd].relname, force_quotes),
-							  consDef->data);
-
-			ArchiveEntry(fout, indinfo[i].indexreloid, tblinfo[tableInd].primary_key_name,
-						 "CONSTRAINT", NULL, q->data, "",
-						 "", tblinfo[tableInd].usename, NULL, NULL);
-
-			destroyPQExpBuffer(consDef);
-
-			/*
-			 * Don't need to do anything else for this system-generated
-			 * index
-			 */
+		/* Only plain tables have indexes */
+		if (tbinfo->relkind != RELKIND_RELATION || !tbinfo->hasindex)
 			continue;
-		}
 
-		resetPQExpBuffer(id1);
-		appendPQExpBuffer(id1, fmtId(indinfo[i].indexrelname, force_quotes));
-
-		resetPQExpBuffer(q);
-		appendPQExpBuffer(q, "%s;\n", indinfo[i].indexdef);
-
-		resetPQExpBuffer(delq);
-		appendPQExpBuffer(delq, "DROP INDEX %s;\n", id1->data);
-
-		/*
-		 * We make the index belong to the owner of its table, which is
-		 * not necessarily right but should answer 99% of the time. Would
-		 * have to add owner name to IndInfo to do it right.
-		 */
-		ArchiveEntry(fout, indinfo[i].indexreloid, id1->data,
-					 "INDEX", NULL, q->data, delq->data,
-					 "", tblinfo[tableInd].usename, NULL, NULL);
+		if (!tbinfo->dump)
+			continue;
 
-		/* Dump Index Comments */
-		resetPQExpBuffer(q);
-		appendPQExpBuffer(q, "INDEX %s", id1->data);
-		dumpComment(fout, q->data, indinfo[i].indexreloid,
-					"pg_class", 0, NULL);
-	}
+		/* Make sure we are in proper schema so indexdef is right */
+		selectSourceSchema(tbinfo->relnamespace->nspname);
 
-	destroyPQExpBuffer(q);
-	destroyPQExpBuffer(delq);
-	destroyPQExpBuffer(id1);
-}
+		resetPQExpBuffer(query);
+		appendPQExpBuffer(query,
+						  "SELECT i.indexrelid as indexreloid, "
+						  "t.relname as indexrelname, "
+						  "pg_get_indexdef(i.indexrelid) as indexdef, "
+						  "i.indisprimary, i.indkey, "
+						  "t.relnatts as indnkeys "
+						  "FROM pg_index i, pg_class t "
+						  "WHERE t.oid = i.indexrelid "
+						  "AND i.indrelid = '%s'::oid "
+						  "ORDER BY indexrelname",
+						  tbinfo->oid);
 
-/*
- * dumpTuples
- *	  prints out the tuples in ASCII representation. The output is a valid
- *	  input to COPY FROM stdin.
- *
- *	  We only need to do this for POSTGRES 4.2 databases since the
- *	  COPY TO statment doesn't escape newlines properly. It's been fixed
- *	  in PostgreSQL.
- *
- * the attrmap passed in tells how to map the attributes copied in to the
- * attributes copied out
- */
-#ifdef NOT_USED
-void
-dumpTuples(PGresult *res, FILE *fout, int *attrmap)
-{
-	int			j,
-				k;
-	int			m,
-				n;
-	char	  **outVals = NULL; /* values to copy out */
+		res = PQexec(g_conn, query->data);
+		if (!res ||
+			PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			write_msg(NULL, "query to obtain list of indexes failed: %s", PQerrorMessage(g_conn));
+			exit_nicely();
+		}
 
-	n = PQntuples(res);
-	m = PQnfields(res);
+		ntups = PQntuples(res);
 
-	if (m > 0)
-	{
-		/*
-		 * Print out the tuples but only print tuples with at least 1
-		 * field.
-		 */
-		outVals = (char **) malloc(m * sizeof(char *));
+		i_indexreloid = PQfnumber(res, "indexreloid");
+		i_indexrelname = PQfnumber(res, "indexrelname");
+		i_indexdef = PQfnumber(res, "indexdef");
+		i_indisprimary = PQfnumber(res, "indisprimary");
+		i_indkey = PQfnumber(res, "indkey");
+		i_indnkeys = PQfnumber(res, "indnkeys");
 
-		for (j = 0; j < n; j++)
+		for (j = 0; j < ntups; j++)
 		{
-			for (k = 0; k < m; k++)
-				outVals[attrmap[k]] = PQgetvalue(res, j, k);
-			for (k = 0; k < m; k++)
+			const char *indexreloid = PQgetvalue(res, j, i_indexreloid);
+			const char *indexrelname = PQgetvalue(res, j, i_indexrelname);
+			const char *indexdef = PQgetvalue(res, j, i_indexdef);
+			const char *indisprimary = PQgetvalue(res, j, i_indisprimary);
+
+			resetPQExpBuffer(q);
+			resetPQExpBuffer(delq);
+
+			if (strcmp(indisprimary, "t") == 0)
 			{
-				char	   *pval = outVals[k];
+				/* Handle PK indexes specially */
+				int indnkeys = atoi(PQgetvalue(res, j, i_indnkeys));
+				char **indkeys = (char **) malloc(indnkeys * sizeof(char *));
+				int			k;
+
+				parseNumericArray(PQgetvalue(res, j, i_indkey),
+								  indkeys, indnkeys);
 
-				if (k != 0)
-					fputc('\t', fout);	/* delimiter for attribute */
+				appendPQExpBuffer(q, "ALTER TABLE %s ADD ",
+								  fmtId(tbinfo->relname, force_quotes));
+				appendPQExpBuffer(q, "CONSTRAINT %s PRIMARY KEY (",
+								  fmtId(indexrelname, force_quotes));
 
-				if (pval)
+				for (k = 0; k < indnkeys; k++)
 				{
-					while (*pval != '\0')
-					{
-						/* escape tabs, newlines and backslashes */
-						if (*pval == '\t' || *pval == '\n' || *pval == '\\')
-							fputc('\\', fout);
-						fputc(*pval, fout);
-						pval++;
-					}
+					int			indkey = atoi(indkeys[k]);
+					const char *attname;
+
+					if (indkey == InvalidAttrNumber)
+						break;
+					attname = getAttrName(indkey, tbinfo);
+
+					appendPQExpBuffer(q, "%s%s",
+									  (k == 0) ? "" : ", ",
+									  fmtId(attname, force_quotes));
 				}
+
+				appendPQExpBuffer(q, ");\n");
+
+				ArchiveEntry(fout, indexreloid,
+							 indexrelname,
+							 tbinfo->relnamespace->nspname,
+							 tbinfo->usename,
+							 "CONSTRAINT", NULL,
+							 q->data, "",
+							 NULL, NULL, NULL);
+
+				free(indkeys);
+			}
+			else
+			{
+				/* Plain secondary index */
+				appendPQExpBuffer(q, "%s;\n", indexdef);
+
+				appendPQExpBuffer(delq, "DROP INDEX %s;\n",
+								  fmtId(indexrelname, force_quotes));
+
+				ArchiveEntry(fout, indexreloid,
+							 indexrelname,
+							 tbinfo->relnamespace->nspname,
+							 tbinfo->usename,
+							 "INDEX", NULL,
+							 q->data, delq->data,
+							 NULL, NULL, NULL);
 			}
-			fputc('\n', fout);	/* delimiter for a tuple */
+
+			/* Dump Index Comments */
+			resetPQExpBuffer(q);
+			appendPQExpBuffer(q, "INDEX %s",
+							  fmtId(indexrelname, force_quotes));
+			dumpComment(fout, q->data,
+						tbinfo->relnamespace->nspname,
+						tbinfo->usename,
+						indexreloid, "pg_class", 0, NULL);
 		}
-		free(outVals);
+
+		PQclear(res);
 	}
+
+	destroyPQExpBuffer(query);
+	destroyPQExpBuffer(q);
+	destroyPQExpBuffer(delq);
 }
-#endif
 
 /*
  * setMaxOid -
@@ -4776,7 +4740,10 @@ setMaxOid(Archive *fout)
 			 "DROP TABLE pgdump_oid;\n",
 			 max_oid);
 
-	ArchiveEntry(fout, "0", "Max OID", "<Init>", NULL, sql, "", "", "", NULL, NULL);
+	ArchiveEntry(fout, "0", "Max OID", NULL, "",
+				 "<Init>", NULL,
+				 sql, "",
+				 NULL, NULL, NULL);
 }
 
 /*
@@ -4860,7 +4827,8 @@ findLastBuiltinOid_V70(void)
 }
 
 static void
-dumpSequence(Archive *fout, TableInfo tbinfo, const bool schemaOnly, const bool dataOnly)
+dumpOneSequence(Archive *fout, TableInfo *tbinfo,
+				const bool schemaOnly, const bool dataOnly)
 {
 	PGresult   *res;
 	char	   *last,
@@ -4873,31 +4841,34 @@ dumpSequence(Archive *fout, TableInfo tbinfo, const bool schemaOnly, const bool
 	PQExpBuffer query = createPQExpBuffer();
 	PQExpBuffer delqry = createPQExpBuffer();
 
+	/* Make sure we are in proper schema */
+	selectSourceSchema(tbinfo->relnamespace->nspname);
+
 	appendPQExpBuffer(query,
 			"SELECT sequence_name, last_value, increment_by, max_value, "
 				  "min_value, cache_value, is_cycled, is_called from %s",
-					  fmtId(tbinfo.relname, force_quotes));
+					  fmtId(tbinfo->relname, force_quotes));
 
 	res = PQexec(g_conn, query->data);
 	if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
 	{
-		write_msg(NULL, "query to get data of sequence \"%s\" failed: %s", tbinfo.relname, PQerrorMessage(g_conn));
+		write_msg(NULL, "query to get data of sequence \"%s\" failed: %s", tbinfo->relname, PQerrorMessage(g_conn));
 		exit_nicely();
 	}
 
 	if (PQntuples(res) != 1)
 	{
 		write_msg(NULL, "query to get data of sequence \"%s\" returned %d rows (expected 1)\n",
-				  tbinfo.relname, PQntuples(res));
+				  tbinfo->relname, PQntuples(res));
 		exit_nicely();
 	}
 
 	/* Disable this check: it fails if sequence has been renamed */
 #ifdef NOT_USED
-	if (strcmp(PQgetvalue(res, 0, 0), tbinfo.relname) != 0)
+	if (strcmp(PQgetvalue(res, 0, 0), tbinfo->relname) != 0)
 	{
 		write_msg(NULL, "query to get data of sequence \"%s\" returned name \"%s\"\n",
-				  tbinfo.relname, PQgetvalue(res, 0, 0));
+				  tbinfo->relname, PQgetvalue(res, 0, 0));
 		exit_nicely();
 	}
 #endif
@@ -4923,33 +4894,37 @@ dumpSequence(Archive *fout, TableInfo tbinfo, const bool schemaOnly, const bool
 	{
 		resetPQExpBuffer(delqry);
 		appendPQExpBuffer(delqry, "DROP SEQUENCE %s;\n",
-						  fmtId(tbinfo.relname, force_quotes));
+						  fmtId(tbinfo->relname, force_quotes));
 
 		resetPQExpBuffer(query);
 		appendPQExpBuffer(query,
 						  "CREATE SEQUENCE %s start %s increment %s "
 						  "maxvalue %s minvalue %s cache %s%s;\n",
-						  fmtId(tbinfo.relname, force_quotes),
+						  fmtId(tbinfo->relname, force_quotes),
 						  (called ? minv : last),
 						  incby, maxv, minv, cache,
 						  (cycled ? " cycle" : ""));
 
-		ArchiveEntry(fout, tbinfo.oid, tbinfo.relname, "SEQUENCE", NULL,
-					 query->data, delqry->data, "", tbinfo.usename,
-					 NULL, NULL);
+		ArchiveEntry(fout, tbinfo->oid, tbinfo->relname,
+					 tbinfo->relnamespace->nspname, tbinfo->usename,
+					 "SEQUENCE", NULL,
+					 query->data, delqry->data,
+					 NULL, NULL, NULL);
 	}
 
 	if (!schemaOnly)
 	{
 		resetPQExpBuffer(query);
 		appendPQExpBuffer(query, "SELECT setval (");
-		formatStringLiteral(query, fmtId(tbinfo.relname, force_quotes), CONV_ALL);
+		formatStringLiteral(query, fmtId(tbinfo->relname, force_quotes), CONV_ALL);
 		appendPQExpBuffer(query, ", %s, %s);\n",
 						  last, (called ? "true" : "false"));
 
-		ArchiveEntry(fout, tbinfo.oid, tbinfo.relname, "SEQUENCE SET", NULL,
-					 query->data, "" /* Del */ , "", tbinfo.usename,
-					 NULL, NULL);
+		ArchiveEntry(fout, tbinfo->oid, tbinfo->relname,
+					 tbinfo->relnamespace->nspname, tbinfo->usename,
+					 "SEQUENCE SET", NULL,
+					 query->data, "" /* Del */ ,
+					 NULL, NULL, NULL);
 	}
 
 	if (!dataOnly)
@@ -4957,9 +4932,10 @@ dumpSequence(Archive *fout, TableInfo tbinfo, const bool schemaOnly, const bool
 		/* Dump Sequence Comments */
 
 		resetPQExpBuffer(query);
-		appendPQExpBuffer(query, "SEQUENCE %s", fmtId(tbinfo.relname, force_quotes));
-		dumpComment(fout, query->data, tbinfo.oid,
-					"pg_class", 0, NULL);
+		appendPQExpBuffer(query, "SEQUENCE %s", fmtId(tbinfo->relname, force_quotes));
+		dumpComment(fout, query->data,
+					tbinfo->relnamespace->nspname, tbinfo->usename,
+					tbinfo->oid, "pg_class", 0, NULL);
 	}
 
 	PQclear(res);
@@ -4970,45 +4946,286 @@ dumpSequence(Archive *fout, TableInfo tbinfo, const bool schemaOnly, const bool
 
 
 static void
-dumpTriggers(Archive *fout, const char *tablename,
-			 TableInfo *tblinfo, int numTables)
+dumpTriggers(Archive *fout, TableInfo *tblinfo, int numTables)
 {
 	int			i,
 				j;
-
-	if (g_verbose)
-		write_msg(NULL, "dumping out triggers\n");
+	PQExpBuffer query = createPQExpBuffer();
+	PQExpBuffer delqry = createPQExpBuffer();
+	PGresult   *res;
+	int			i_tgoid,
+				i_tgname,
+				i_tgfname,
+				i_tgtype,
+				i_tgnargs,
+				i_tgargs,
+				i_tgisconstraint,
+				i_tgconstrname,
+				i_tgdeferrable,
+				i_tgconstrrelid,
+				i_tgconstrrelname,
+				i_tginitdeferred;
+	int			ntups;
 
 	for (i = 0; i < numTables; i++)
 	{
-		if (tablename && (strcmp(tblinfo[i].relname, tablename) != 0) && (strlen(tablename) > 0))
+		TableInfo	   *tbinfo = &tblinfo[i];
+
+		if (tbinfo->ntrig == 0 || !tbinfo->dump)
 			continue;
 
-		for (j = 0; j < tblinfo[i].ntrig; j++)
+		if (g_verbose)
+			write_msg(NULL, "dumping triggers for table %s\n",
+					  tbinfo->relname);
+
+		/* select table schema to ensure regproc name is qualified if needed */
+		selectSourceSchema(tbinfo->relnamespace->nspname);
+
+		resetPQExpBuffer(query);
+		if (g_fout->remoteVersion >= 70300)
+		{
+			appendPQExpBuffer(query,
+							  "SELECT tgname, tgfoid::regproc as tgfname, "
+							  "tgtype, tgnargs, tgargs, "
+							  "tgisconstraint, tgconstrname, tgdeferrable, "
+							  "tgconstrrelid, tginitdeferred, oid, "
+							  "tgconstrrelid::regclass as tgconstrrelname "
+							  "from pg_trigger "
+							  "where tgrelid = '%s'::oid",
+							  tbinfo->oid);
+		}
+		else
+		{
+			appendPQExpBuffer(query,
+							  "SELECT tgname, tgfoid::regproc as tgfname, "
+							  "tgtype, tgnargs, tgargs, "
+							  "tgisconstraint, tgconstrname, tgdeferrable, "
+							  "tgconstrrelid, tginitdeferred, oid, "
+							  "(select relname from pg_class where oid = tgconstrrelid) "
+							  "		as tgconstrrelname "
+							  "from pg_trigger "
+							  "where tgrelid = '%s'::oid",
+							  tbinfo->oid);
+		}
+		res = PQexec(g_conn, query->data);
+		if (!res ||
+			PQresultStatus(res) != PGRES_TUPLES_OK)
+		{
+			write_msg(NULL, "query to obtain list of triggers failed: %s", PQerrorMessage(g_conn));
+			exit_nicely();
+		}
+		ntups = PQntuples(res);
+		if (ntups != tbinfo->ntrig)
+		{
+			write_msg(NULL, "expected %d triggers on table \"%s\" but found %d\n",
+					  tbinfo->ntrig, tbinfo->relname, ntups);
+			exit_nicely();
+		}
+		i_tgname = PQfnumber(res, "tgname");
+		i_tgfname = PQfnumber(res, "tgfname");
+		i_tgtype = PQfnumber(res, "tgtype");
+		i_tgnargs = PQfnumber(res, "tgnargs");
+		i_tgargs = PQfnumber(res, "tgargs");
+		i_tgoid = PQfnumber(res, "oid");
+		i_tgisconstraint = PQfnumber(res, "tgisconstraint");
+		i_tgconstrname = PQfnumber(res, "tgconstrname");
+		i_tgdeferrable = PQfnumber(res, "tgdeferrable");
+		i_tgconstrrelid = PQfnumber(res, "tgconstrrelid");
+		i_tgconstrrelname = PQfnumber(res, "tgconstrrelname");
+		i_tginitdeferred = PQfnumber(res, "tginitdeferred");
+
+		for (j = 0; j < ntups; j++)
 		{
-			ArchiveEntry(fout, tblinfo[i].triggers[j].oid, tblinfo[i].triggers[j].tgname,
-				   "TRIGGER", NULL, tblinfo[i].triggers[j].tgsrc, "", "",
-						 tblinfo[i].usename, NULL, NULL);
-			dumpComment(fout, tblinfo[i].triggers[j].tgcomment, tblinfo[i].triggers[j].oid,
-						"pg_trigger", 0, NULL);
+			const char *tgoid = PQgetvalue(res, j, i_tgoid);
+			char	   *tgname = PQgetvalue(res, j, i_tgname);
+			const char *tgfname = PQgetvalue(res, j, i_tgfname);
+			int2		tgtype = atoi(PQgetvalue(res, j, i_tgtype));
+			int			tgnargs = atoi(PQgetvalue(res, j, i_tgnargs));
+			const char *tgargs = PQgetvalue(res, j, i_tgargs);
+			int			tgisconstraint;
+			int			tgdeferrable;
+			int			tginitdeferred;
+			char	   *tgconstrrelid;
+			const char *p;
+			int			findx;
+
+			if (strcmp(PQgetvalue(res, j, i_tgisconstraint), "f") == 0)
+				tgisconstraint = 0;
+			else
+				tgisconstraint = 1;
+
+			if (strcmp(PQgetvalue(res, j, i_tgdeferrable), "f") == 0)
+				tgdeferrable = 0;
+			else
+				tgdeferrable = 1;
+
+			if (strcmp(PQgetvalue(res, j, i_tginitdeferred), "f") == 0)
+				tginitdeferred = 0;
+			else
+				tginitdeferred = 1;
+
+			resetPQExpBuffer(delqry);
+			appendPQExpBuffer(delqry, "DROP TRIGGER %s ",
+							  fmtId(tgname, force_quotes));
+			appendPQExpBuffer(delqry, "ON %s;\n",
+							  fmtId(tbinfo->relname, force_quotes));
+
+			resetPQExpBuffer(query);
+			if (tgisconstraint)
+			{
+				appendPQExpBuffer(query, "CREATE CONSTRAINT TRIGGER ");
+				appendPQExpBuffer(query, fmtId(PQgetvalue(res, j, i_tgconstrname), force_quotes));
+			}
+			else
+			{
+				appendPQExpBuffer(query, "CREATE TRIGGER ");
+				appendPQExpBuffer(query, fmtId(tgname, force_quotes));
+			}
+			appendPQExpBufferChar(query, ' ');
+			/* Trigger type */
+			findx = 0;
+			if (TRIGGER_FOR_BEFORE(tgtype))
+				appendPQExpBuffer(query, "BEFORE");
+			else
+				appendPQExpBuffer(query, "AFTER");
+			if (TRIGGER_FOR_INSERT(tgtype))
+			{
+				appendPQExpBuffer(query, " INSERT");
+				findx++;
+			}
+			if (TRIGGER_FOR_DELETE(tgtype))
+			{
+				if (findx > 0)
+					appendPQExpBuffer(query, " OR DELETE");
+				else
+					appendPQExpBuffer(query, " DELETE");
+				findx++;
+			}
+			if (TRIGGER_FOR_UPDATE(tgtype))
+			{
+				if (findx > 0)
+					appendPQExpBuffer(query, " OR UPDATE");
+				else
+					appendPQExpBuffer(query, " UPDATE");
+			}
+			appendPQExpBuffer(query, " ON %s ",
+							  fmtId(tbinfo->relname, force_quotes));
+
+			if (tgisconstraint)
+			{
+				tgconstrrelid = PQgetvalue(res, j, i_tgconstrrelid);
+
+				if (strcmp(tgconstrrelid, "0") != 0)
+				{
+
+					if (PQgetisnull(res, j, i_tgconstrrelname))
+					{
+						write_msg(NULL, "query produced NULL referenced table name for foreign key trigger \"%s\" on table \"%s\" (oid of table: %s)\n",
+								  tgname, tbinfo->relname, tgconstrrelid);
+						exit_nicely();
+					}
+
+					/* If we are using regclass, name is already quoted */
+					if (g_fout->remoteVersion >= 70300)
+						appendPQExpBuffer(query, " FROM %s",
+										  PQgetvalue(res, j, i_tgconstrrelname));
+					else
+						appendPQExpBuffer(query, " FROM %s",
+										  fmtId(PQgetvalue(res, j, i_tgconstrrelname), force_quotes));
+				}
+				if (!tgdeferrable)
+					appendPQExpBuffer(query, " NOT");
+				appendPQExpBuffer(query, " DEFERRABLE INITIALLY ");
+				if (tginitdeferred)
+					appendPQExpBuffer(query, "DEFERRED");
+				else
+					appendPQExpBuffer(query, "IMMEDIATE");
+
+			}
+
+			appendPQExpBuffer(query, " FOR EACH ROW");
+			/* In 7.3, result of regproc is already quoted */
+			if (g_fout->remoteVersion >= 70300)
+				appendPQExpBuffer(query, " EXECUTE PROCEDURE %s (",
+								  tgfname);
+			else
+				appendPQExpBuffer(query, " EXECUTE PROCEDURE %s (",
+								  fmtId(tgfname, force_quotes));
+			for (findx = 0; findx < tgnargs; findx++)
+			{
+				const char *s;
+
+				for (p = tgargs;;)
+				{
+					p = strchr(p, '\\');
+					if (p == NULL)
+					{
+						write_msg(NULL, "bad argument string (%s) for trigger \"%s\" on table \"%s\"\n",
+								  PQgetvalue(res, j, i_tgargs),
+								  tgname,
+								  tbinfo->relname);
+						exit_nicely();
+					}
+					p++;
+					if (*p == '\\')
+					{
+						p++;
+						continue;
+					}
+					if (p[0] == '0' && p[1] == '0' && p[2] == '0')
+						break;
+				}
+				p--;
+				appendPQExpBufferChar(query, '\'');
+				for (s = tgargs; s < p;)
+				{
+					if (*s == '\'')
+						appendPQExpBufferChar(query, '\\');
+					appendPQExpBufferChar(query, *s++);
+				}
+				appendPQExpBufferChar(query, '\'');
+				appendPQExpBuffer(query, (findx < tgnargs - 1) ? ", " : "");
+				tgargs = p + 4;
+			}
+			appendPQExpBuffer(query, ");\n");
+
+			ArchiveEntry(fout, tgoid,
+						 tgname,
+						 tbinfo->relnamespace->nspname,
+						 tbinfo->usename,
+						 "TRIGGER", NULL,
+						 query->data, delqry->data,
+						 NULL, NULL, NULL);
+
+			resetPQExpBuffer(query);
+			appendPQExpBuffer(query, "TRIGGER %s ",
+							  fmtId(tgname, force_quotes));
+			appendPQExpBuffer(query, "ON %s",
+							  fmtId(tbinfo->relname, force_quotes));
+
+			dumpComment(fout, query->data,
+						tbinfo->relnamespace->nspname, tbinfo->usename,
+						tgoid, "pg_trigger", 0, NULL);
 		}
+
+		PQclear(res);
 	}
+
+	destroyPQExpBuffer(query);
+	destroyPQExpBuffer(delqry);
 }
 
 
 static void
-dumpRules(Archive *fout, const char *tablename,
-		  TableInfo *tblinfo, int numTables)
+dumpRules(Archive *fout, TableInfo *tblinfo, int numTables)
 {
 	PGresult   *res;
 	int			nrules;
 	int			i,
 				t;
 	PQExpBuffer query = createPQExpBuffer();
-
 	int			i_definition;
 	int			i_oid;
-	int			i_owner;
 	int			i_rulename;
 
 	if (g_verbose)
@@ -5019,9 +5236,14 @@ dumpRules(Archive *fout, const char *tablename,
 	 */
 	for (t = 0; t < numTables; t++)
 	{
-		if (tablename && (strcmp(tblinfo[t].relname, tablename) != 0) && (strlen(tablename) > 0))
+		TableInfo	   *tbinfo = &tblinfo[t];
+
+		if (!tbinfo->hasrules || !tbinfo->dump)
 			continue;
 
+		/* Make sure we are in proper schema */
+		selectSourceSchema(tbinfo->relnamespace->nspname);
+
 		/*
 		 * Get all rules defined for this table, except view select rules
 		 */
@@ -5034,11 +5256,10 @@ dumpRules(Archive *fout, const char *tablename,
 			 * rules (pjw 15-Sep-2000).
 			 */
 			appendPQExpBuffer(query, "SELECT definition,"
-							  "   (select usename from pg_user where pg_class.relowner = usesysid) AS viewowner, "
 							  "   pg_rewrite.oid, pg_rewrite.rulename "
 							  "FROM pg_rewrite, pg_class, pg_rules "
 							  "WHERE pg_class.relname = ");
-			formatStringLiteral(query, tblinfo[t].relname, CONV_ALL);
+			formatStringLiteral(query, tbinfo->relname, CONV_ALL);
 			appendPQExpBuffer(query,
 							  "    AND pg_rewrite.ev_class = pg_class.oid "
 							  "    AND pg_rules.tablename = pg_class.relname "
@@ -5047,15 +5268,14 @@ dumpRules(Archive *fout, const char *tablename,
 		}
 		else
 		{
-			appendPQExpBuffer(query, "SELECT pg_get_ruledef(pg_rewrite.oid) AS definition,"
-							  " (select usename from pg_user where pg_class.relowner = usesysid) AS viewowner, "
-							  " pg_rewrite.oid, pg_rewrite.rulename "
-							  "FROM pg_rewrite, pg_class "
-							  "WHERE pg_class.oid = '%s'::oid "
-							  " AND pg_rewrite.ev_class = pg_class.oid "
-							  " AND pg_rewrite.rulename != '_RETURN' "
-							  "ORDER BY pg_rewrite.oid",
-							  tblinfo[t].oid);
+			appendPQExpBuffer(query,
+							  "SELECT pg_get_ruledef(oid) AS definition,"
+							  " oid, rulename "
+							  "FROM pg_rewrite "
+							  "WHERE ev_class = '%s'::oid "
+							  "AND rulename != '_RETURN' "
+							  "ORDER BY oid",
+							  tbinfo->oid);
 		}
 
 		res = PQexec(g_conn, query->data);
@@ -5063,13 +5283,12 @@ dumpRules(Archive *fout, const char *tablename,
 			PQresultStatus(res) != PGRES_TUPLES_OK)
 		{
 			write_msg(NULL, "query to get rules associated with table \"%s\" failed: %s",
-					  tblinfo[t].relname, PQerrorMessage(g_conn));
+					  tbinfo->relname, PQerrorMessage(g_conn));
 			exit_nicely();
 		}
 
 		nrules = PQntuples(res);
 		i_definition = PQfnumber(res, "definition");
-		i_owner = PQfnumber(res, "viewowner");
 		i_oid = PQfnumber(res, "oid");
 		i_rulename = PQfnumber(res, "rulename");
 
@@ -5079,17 +5298,24 @@ dumpRules(Archive *fout, const char *tablename,
 
 		for (i = 0; i < nrules; i++)
 		{
-			ArchiveEntry(fout, PQgetvalue(res, i, i_oid), PQgetvalue(res, i, i_rulename),
-						 "RULE", NULL, PQgetvalue(res, i, i_definition),
-						 "", "", PQgetvalue(res, i, i_owner), NULL, NULL);
+			ArchiveEntry(fout, PQgetvalue(res, i, i_oid),
+						 PQgetvalue(res, i, i_rulename),
+						 tbinfo->relnamespace->nspname,
+						 tbinfo->usename,
+						 "RULE", NULL,
+						 PQgetvalue(res, i, i_definition),
+						 "",	/* Del */
+						 NULL, NULL, NULL);
 
 			/* Dump rule comments */
 
 			resetPQExpBuffer(query);
 			appendPQExpBuffer(query, "RULE %s", fmtId(PQgetvalue(res, i, i_rulename), force_quotes));
-			appendPQExpBuffer(query, " ON %s", fmtId(tblinfo[t].relname, force_quotes));
-			dumpComment(fout, query->data, PQgetvalue(res, i, i_oid),
-						"pg_rewrite", 0, NULL);
+			appendPQExpBuffer(query, " ON %s", fmtId(tbinfo->relname, force_quotes));
+			dumpComment(fout, query->data,
+						tbinfo->relnamespace->nspname,
+						tbinfo->usename,
+						PQgetvalue(res, i, i_oid), "pg_rewrite", 0, NULL);
 
 		}
 
@@ -5098,3 +5324,206 @@ dumpRules(Archive *fout, const char *tablename,
 
 	destroyPQExpBuffer(query);
 }
+
+/*
+ * selectSourceSchema - make the specified schema the active search path
+ * in the source database.
+ *
+ * NB: pg_catalog is implicitly searched before the specified schema;
+ * so system names are never qualified, and user names are only qualified
+ * if they are cross-schema references or duplicate system names.
+ */
+static void
+selectSourceSchema(const char *schemaName)
+{
+	static char	   *curSchemaName = NULL;
+	PQExpBuffer query;
+	PGresult   *res;
+
+	/* Not relevant if fetching from pre-7.3 DB */
+	if (g_fout->remoteVersion < 70300)
+		return;
+	/* Ignore null schema names */
+	if (schemaName == NULL || *schemaName == '\0')
+		return;
+	/* Optimize away repeated selection of same schema */
+	if (curSchemaName && strcmp(curSchemaName, schemaName) == 0)
+		return;
+
+	query = createPQExpBuffer();
+	appendPQExpBuffer(query, "SET search_path = %s",
+					  fmtId(schemaName, force_quotes));
+	res = PQexec(g_conn, query->data);
+	if (!res ||
+		PQresultStatus(res) != PGRES_COMMAND_OK)
+	{
+		write_msg(NULL, "query to set search_path failed: %s",
+				  PQerrorMessage(g_conn));
+		exit_nicely();
+	}
+	PQclear(res);
+	destroyPQExpBuffer(query);
+
+	if (curSchemaName)
+		free(curSchemaName);
+	curSchemaName = strdup(schemaName);
+}
+
+/*
+ * getFormattedTypeName - retrieve a nicely-formatted type name for the
+ * given type name.
+ *
+ * NB: in 7.3 and up the result may depend on the currently-selected
+ * schema; this is why we don't try to cache the names.
+ */
+static char *
+getFormattedTypeName(const char *oid, OidOptions opts)
+{
+	char	   *result;
+	PQExpBuffer query;
+	PGresult   *res;
+	int			ntups;
+
+	if (atooid(oid) == 0)
+	{
+		if ((opts & zeroAsOpaque) != 0)
+			return strdup(g_opaque_type);
+		else if ((opts & zeroAsAny) != 0)
+			return strdup("'any'");
+		else if ((opts & zeroAsStar) != 0)
+			return strdup("*");
+		else if ((opts & zeroAsNone) != 0)
+			return strdup("NONE");
+	}
+
+	query = createPQExpBuffer();
+	if (g_fout->remoteVersion >= 70100)
+	{
+		appendPQExpBuffer(query, "SELECT format_type('%s'::oid, NULL)",
+						  oid);
+	}
+	else
+	{
+		appendPQExpBuffer(query, "SELECT typname "
+						  "FROM pg_type "
+						  "WHERE oid = '%s'::oid",
+						  oid);
+	}
+
+	res = PQexec(g_conn, query->data);
+	if (!res ||
+		PQresultStatus(res) != PGRES_TUPLES_OK)
+	{
+		write_msg(NULL, "query to obtain type name for %s failed: %s",
+				  oid, PQerrorMessage(g_conn));
+		exit_nicely();
+	}
+
+	/* Expecting a single result only */
+	ntups = PQntuples(res);
+	if (ntups != 1)
+	{
+		write_msg(NULL, "Got %d rows instead of one from: %s",
+				  ntups, query->data);
+		exit_nicely();
+	}
+
+	result = strdup(PQgetvalue(res, 0, 0));
+
+	PQclear(res);
+	destroyPQExpBuffer(query);
+
+	return result;
+}
+
+/*
+ * myFormatType --- local implementation of format_type for use with 7.0.
+ */
+static char *
+myFormatType(const char *typname, int32 typmod)
+{
+	char	   *result;
+	PQExpBuffer buf = createPQExpBuffer();
+
+	/* Show lengths on bpchar and varchar */
+	if (!strcmp(typname, "bpchar"))
+	{
+		int			len = (typmod - VARHDRSZ);
+
+		appendPQExpBuffer(buf, "character");
+		if (len > 1)
+			appendPQExpBuffer(buf, "(%d)",
+							  typmod - VARHDRSZ);
+	}
+	else if (!strcmp(typname, "varchar"))
+	{
+		appendPQExpBuffer(buf, "character varying");
+		if (typmod != -1)
+			appendPQExpBuffer(buf, "(%d)",
+							  typmod - VARHDRSZ);
+	}
+	else if (!strcmp(typname, "numeric"))
+	{
+		appendPQExpBuffer(buf, "numeric");
+		if (typmod != -1)
+		{
+			int32		tmp_typmod;
+			int			precision;
+			int			scale;
+
+			tmp_typmod = typmod - VARHDRSZ;
+			precision = (tmp_typmod >> 16) & 0xffff;
+			scale = tmp_typmod & 0xffff;
+			appendPQExpBuffer(buf, "(%d,%d)",
+							  precision, scale);
+		}
+	}
+
+	/*
+	 * char is an internal single-byte data type; Let's make sure we force
+	 * it through with quotes. - thomas 1998-12-13
+	 */
+	else if (!strcmp(typname, "char"))
+	{
+		appendPQExpBuffer(buf, "%s",
+						  fmtId(typname, true));
+	}
+	else
+	{
+		appendPQExpBuffer(buf, "%s",
+						  fmtId(typname, false));
+	}
+
+	result = strdup(buf->data);
+	destroyPQExpBuffer(buf);
+
+	return result;
+}
+
+/*
+ * fmtQualifiedId - convert a qualified name to the proper format for
+ * the source database.
+ *
+ * Like fmtId, use the result before calling again.
+ */
+static const char *
+fmtQualifiedId(const char *schema, const char *id)
+{
+	static PQExpBuffer id_return = NULL;
+
+	if (id_return)				/* first time through? */
+		resetPQExpBuffer(id_return);
+	else
+		id_return = createPQExpBuffer();
+
+	/* Suppress schema name if fetching from pre-7.3 DB */
+	if (g_fout->remoteVersion >= 70300 && schema && *schema)
+	{
+		appendPQExpBuffer(id_return, "%s.",
+						  fmtId(schema, force_quotes));
+	}
+	appendPQExpBuffer(id_return, "%s",
+					  fmtId(id, force_quotes));
+
+	return id_return->data;
+}
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 580dacf66df..1cf7a02e304 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -1,27 +1,12 @@
 /*-------------------------------------------------------------------------
  *
  * pg_dump.h
- *	  header file for the pg_dump utility
+ *	  Common header file for the pg_dump utility
  *
  * 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.84 2002/04/24 22:39:49 petere Exp $
- *
- * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
- *
- *	 - Fixed dumpTable output to output lengths for char and varchar types!
- *	 - Added single. quote to twin single quote expansion for 'insert' string
- *	   mode.
- *
- * Modifications - 6/1/97 - igor@sba.miami.edu
- * - Added extern's for the functions that clear allocated memory
- *	 in pg_dump.c
- *
- * Modifications - 14-Sep-2000 - pjw@rhyme.com.au
- *	-	Added typedefn fields to typeinfo and relinfo
- *	-	Added enum for findTypeByOid to allow special handling of
- *		'0' OID.
+ * $Id: pg_dump.h,v 1.85 2002/05/10 22:36:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,171 +17,133 @@
 #include "pg_backup.h"
 #include "pqexpbuffer.h"
 
-/* The data structures used to store system catalog information */
+/*
+ * The data structures used to store system catalog information
+ *
+ * NOTE: the structures described here live for the entire pg_dump run;
+ * and in most cases we make a struct for every object we can find in the
+ * catalogs, not only those we are actually going to dump.  Hence, it's
+ * best to store a minimal amount of per-object info in these structs,
+ * and retrieve additional per-object info when and if we dump a specific
+ * object.  In particular, try to avoid retrieving expensive-to-compute
+ * information until it's known to be needed.
+ */
+
+typedef struct _namespaceInfo
+{
+	char	   *oid;
+	char	   *nspname;
+	char	   *usename;		/* name of owner, or empty string */
+	char	   *nspacl;
+	bool		dump;			/* true if need to dump definition */
+} NamespaceInfo;
 
 typedef struct _typeInfo
 {
 	char	   *oid;
-	char	   *typowner;
-	char	   *typname;
-	char	   *typlen;
-	char	   *typprtlen;
-	char	   *typinput;
-	char	   *typoutput;
-	char	   *typreceive;
-	char	   *typsend;
-	char	   *typelem;
-	char	   *typdelim;
-	char	   *typdefault;
-	char	   *typrelid;
-	char	   *typalign;
-	char	   *typstorage;
-	char	   *usename;
-	char	   *typedefn;
-	char	   *typtype;
-	int			passedbyvalue;
-	int			isArray;
-	int			isDefined;
+	char	   *typname;		/* name as seen in catalog */
+	/* Note: format_type might produce something different than typname */
+	NamespaceInfo *typnamespace;	/* link to containing namespace */
+	char	   *usename;		/* name of owner, or empty string */
+	char	   *typelem;		/* OID */
+	char	   *typrelid;		/* OID */
+	char		typtype;		/* 'b', 'c', etc */
+	bool		isArray;		/* true if user-defined array type */
+	bool		isDefined;		/* true if typisdefined */
 } TypeInfo;
 
 typedef struct _funcInfo
 {
 	char	   *oid;
 	char	   *proname;
-	char	   *proowner;
+	NamespaceInfo *pronamespace;	/* link to containing namespace */
+	char	   *usename;		/* name of owner, or empty string */
 	Oid			lang;
 	int			nargs;
-	char	   **argtypes;
-	char	   *prorettype;
-	int			retset;			/* 1 if the function returns a set, else 0 */
-	char	   *prosrc;
-	char	   *probin;
-	char	   *usename;
-	char		provolatile;	/* Attr */
-	bool		isimplicit;		/* Attr */
-	bool		isstrict;		/* Attr */
-	int			dumped;			/* 1 if already dumped */
+	char	   **argtypes;		/* OIDs */
+	char	   *prorettype;		/* OID */
+	bool		dumped;			/* true if already dumped */
 } FuncInfo;
 
-typedef struct _trigInfo
+typedef struct _aggInfo
 {
 	char	   *oid;
-	char	   *tgname;
-	char	   *tgsrc;
-	char	   *tgdel;
-	char	   *tgcomment;
-} TrigInfo;
+	char	   *aggname;
+	NamespaceInfo *aggnamespace;	/* link to containing namespace */
+	char	   *usename;
+} AggInfo;
+
+typedef struct _oprInfo
+{
+	char	   *oid;
+	char	   *oprname;
+	NamespaceInfo *oprnamespace;	/* link to containing namespace */
+	char	   *usename;
+	char	   *oprcode;		/* as OID, not regproc name */
+} OprInfo;
 
 typedef struct _tableInfo
 {
+	/*
+	 * These fields are collected for every table in the database.
+	 */
 	char	   *oid;
 	char	   *relname;
+	NamespaceInfo *relnamespace;	/* link to containing namespace */
+	char	   *usename;		/* name of owner, or empty string */
 	char	   *relacl;
-	char	   *viewdef;
-	char	   *viewoid;		/* OID of view - should be >= oid of table
-								 * important because views may be
-								 * constructed manually from rules, and
-								 * rule may ref things created after the
-								 * base table was created. */
 	char		relkind;
 	bool		hasindex;		/* does it have any indexes? */
+	bool		hasrules;		/* does it have any rules? */
 	bool		hasoids;		/* does it have OIDs? */
+	int			ncheck;			/* # of CHECK expressions */
+	int			ntrig;			/* # of triggers */
+
+	bool		interesting;	/* true if need to collect more data */
+	bool		dump;			/* true if we want to dump it */
+
+	/*
+	 * These fields are computed only if we decide the table is interesting
+	 * (it's either a table to dump, or a direct parent of a dumpable table).
+	 */
 	int			numatts;		/* number of attributes */
-	int		   *inhAttrs;		/* an array of flags, one for each
-								 * attribute if the value is 1, then this
-								 * attribute is an inherited attribute */
-	int		   *inhAttrDef;		/* Flags indicating if attrdef is
-								 * inherited */
-	int		   *inhNotNull;		/* Flags indicating if NOT NULL in
-								 * inherited */
 	char	  **attnames;		/* the attribute names */
-	char	  **atttypedefns;	/* formatted column type definitions */
-	char	  **typnames;		/* fill out attributes */
-	bool	   *notnull;		/* Not null constraints of an attribute */
+	char	  **atttypnames;	/* attribute type names */
+	int		   *atttypmod;		/* type-specific type modifiers */
+	/*
+	 * Note: we need to store per-attribute notnull and default stuff for
+	 * all interesting tables so that we can tell which constraints were
+	 * inherited.
+	 */
+	bool	   *notnull;		/* Not null constraints on attributes */
 	char	  **adef_expr;		/* DEFAULT expressions */
-	int			numParents;		/* number of (immediate) parent
-								 * supertables */
-	char	  **parentRels;		/* names of parent relations, NULL if
-								 * numParents == 0 */
-	char	  **out_attnames;	/* the attribute names, in the order they
-								 * would be in, when the table is created
-								 * in the target query language. this is
-								 * needed because the SQL tables will not
-								 * have the same order of attributes as
-								 * the POSTQUEL tables */
-	int		   *atttypmod;		/* type-specific type modifier */
-	char	   *usename;
-	int			ncheck;			/* # of CHECK expressions */
-	char	  **check_expr;		/* [CONSTRAINT name] CHECK expressions */
-	int			ntrig;			/* # of triggers */
-	TrigInfo   *triggers;		/* Triggers on the table */
-	char	   *pkIndexOid;		/* Primary Key index OID */
-	char	   *primary_key_name;		/* PRIMARY KEY name, if any */
+	bool	   *inhAttrs;		/* true if each attribute is inherited */
+	bool	   *inhAttrDef;		/* true if attr's default is inherited */
+	bool	   *inhNotNull;		/* true if NOT NULL is inherited */
+
+	/*
+	 * Stuff computed only for dumpable tables.
+	 */
+	int			numParents;		/* number of (immediate) parent tables */
+	int		   *parentIndexes;	/* TableInfo indexes of immediate parents */
+
+	char	   *viewoid;		/* OID of view - should be >= oid of table
+								 * important because views may be
+								 * constructed manually from rules, and
+								 * rule may ref things created after the
+								 * base table was created. */
 } TableInfo;
 
 typedef struct _inhInfo
 {
-	char	   *inhrelid;
-	char	   *inhparent;
+	char	   *inhrelid;		/* OID of a child table */
+	char	   *inhparent;		/* OID of its parent */
 } InhInfo;
 
-typedef struct _indInfo
-{
-	char	   *indexreloid;	/* oid of the index itself */
-	char	   *indreloid;		/* oid of the table the index is on */
-	char	   *indexrelname;	/* name of the index itself */
-	char	   *indrelname;		/* name of the indexed table */
-	char	   *indexdef;		/* index definitional command */
-	char	   *indisprimary;	/* is this a PK index? */
-	int			indnkeys;		/* number of keys in index */
-	char	  **indkey;			/* attribute numbers of the key
-								 * attributes */
-} IndInfo;
-
-typedef struct _aggInfo
-{
-	char	   *oid;
-	char	   *aggname;
-	char	   *aggtransfn;
-	char	   *aggfinalfn;
-	char	   *aggtranstype;
-	char	   *aggbasetype;
-	char	   *agginitval;
-	char	   *usename;
-	int			convertok;		/* Flag to indicate of version convertsion
-								 * is OK */
-} AggInfo;
-
-typedef struct _oprInfo
-{
-	char	   *oid;
-	char	   *oprname;
-	char	   *oprkind;		/*----------
-								 *	b = binary,
-								 *	l = left unary
-								 *	r = right unary
-								 *----------
-								 */
-	char	   *oprcode;		/* operator function name */
-	char	   *oprleft;		/* left operand type */
-	char	   *oprright;		/* right operand type */
-	char	   *oprcom;			/* oid of the commutator operator */
-	char	   *oprnegate;		/* oid of the negator operator */
-	char	   *oprrest;		/* name of the function to calculate
-								 * operator restriction selectivity */
-	char	   *oprjoin;		/* name of the function to calculate
-								 * operator join selectivity */
-	char	   *oprcanhash;		/* can we use hash join strategy ? */
-	char	   *oprlsortop;		/* oid's of the left and right sort
-								 * operators */
-	char	   *oprrsortop;
-	char	   *usename;
-} OprInfo;
 
 /* global decls */
 extern bool force_quotes;		/* double-quotes for identifiers flag */
 extern bool g_verbose;			/* verbose flag */
-extern Oid	g_last_builtin_oid; /* value of the last builtin oid */
 extern Archive *g_fout;			/* the script file */
 
 /* placeholders for comment starting and ending delimiters */
@@ -212,73 +159,55 @@ extern char g_opaque_type[10];	/* name for the opaque type */
 */
 /*
  *	common utility functions
-*/
+ */
 
 extern TableInfo *dumpSchema(Archive *fout,
 		   int *numTablesPtr,
-		   const char *tablename,
-		   const bool acls,
-		   const bool oids,
+		   const bool aclsSkip,
 		   const bool schemaOnly,
 		   const bool dataOnly);
-extern void dumpSchemaIdx(Archive *fout,
-			  const char *tablename,
-			  TableInfo *tblinfo,
-			  int numTables);
 
 typedef enum _OidOptions
 {
 	zeroAsOpaque = 1,
 	zeroAsAny = 2,
 	zeroAsStar = 4,
-	zeroAsNone = 8,
-	useBaseTypeName = 1024
+	zeroAsNone = 8
 } OidOptions;
 
-extern char *findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid, OidOptions opts);
+extern int	findTableByOid(TableInfo *tbinfo, int numTables, const char *oid);
 extern char *findOprByOid(OprInfo *oprinfo, int numOprs, const char *oid);
-extern int	findFuncByName(FuncInfo *finfo, int numFuncs, const char *name);
-extern int	findTableByName(TableInfo *tbinfo, int numTables, const char *relname);
+extern int	findFuncByOid(FuncInfo *finfo, int numFuncs, const char *oid);
 
 extern void check_conn_and_db(void);
+extern void exit_nicely(void);
+
 extern void parseNumericArray(const char *str, char **array, int arraysize);
 
 /*
  * version specific routines
  */
+extern NamespaceInfo *getNamespaces(int *numNamespaces);
 extern TypeInfo *getTypes(int *numTypes);
 extern FuncInfo *getFuncs(int *numFuncs);
 extern AggInfo *getAggregates(int *numAggregates);
-
-extern void clearAggInfo(AggInfo *, int);
-extern void clearFuncInfo(FuncInfo *, int);
-extern void clearInhInfo(InhInfo *, int);
-extern void clearIndInfo(IndInfo *, int);
-extern void clearOprInfo(OprInfo *, int);
-extern void clearTypeInfo(TypeInfo *, int);
-
 extern OprInfo *getOperators(int *numOperators);
-extern TableInfo *getTables(int *numTables, FuncInfo *finfo, int numFuncs,
-							const char* tablename);
+extern TableInfo *getTables(int *numTables);
 extern InhInfo *getInherits(int *numInherits);
+
 extern void getTableAttrs(TableInfo *tbinfo, int numTables);
-extern IndInfo *getIndexes(int *numIndexes);
 extern void dumpDBComment(Archive *outfile);
+extern void dumpNamespaces(Archive *fout,
+						   NamespaceInfo *nsinfo, int numNamespaces);
 extern void dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
 		  TypeInfo *tinfo, int numTypes);
-extern void dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs,
-			  TypeInfo *tinfo, int numTypes);
-extern void dumpFuncs(Archive *fout, FuncInfo *finfo, int numFuncs,
-		  TypeInfo *tinfo, int numTypes);
-extern void dumpAggs(Archive *fout, AggInfo *agginfo, int numAggregates,
-		 TypeInfo *tinfo, int numTypes);
-extern void dumpOprs(Archive *fout, OprInfo *agginfo, int numOperators,
-		 TypeInfo *tinfo, int numTypes);
-extern void dumpTables(Archive *fout, TableInfo *tbinfo, int numTables,
-		   const char *tablename, const bool acls,
-		   const bool schemaOnly, const bool dataOnly);
-extern void dumpIndexes(Archive *fout, IndInfo *indinfo, int numIndexes,
-			TableInfo *tbinfo, int numTables, const char *tablename);
-extern void exit_nicely(void);
+extern void dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs);
+extern void dumpFuncs(Archive *fout, FuncInfo *finfo, int numFuncs);
+extern void dumpAggs(Archive *fout, AggInfo *agginfo, int numAggregates);
+extern void dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators);
+extern void dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
+					   const bool aclsSkip,
+					   const bool schemaOnly, const bool dataOnly);
+extern void dumpIndexes(Archive *fout, TableInfo *tbinfo, int numTables);
 
 #endif   /* PG_DUMP_H */
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
index e6747fd53f7..9d2af919aca 100644
--- a/src/bin/pg_dump/pg_restore.c
+++ b/src/bin/pg_dump/pg_restore.c
@@ -34,22 +34,7 @@
  *
  *
  * IDENTIFICATION
- *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.33 2002/01/18 19:17:05 momjian Exp $
- *
- * Modifications - 28-Jun-2000 - pjw@rhyme.com.au
- *
- *		Initial version. Command processing taken from original pg_dump.
- *
- * Modifications - 28-Jul-2000 - pjw@rhyme.com.au (1.45)
- *
- *		Added --create, --no-owner, --superuser, --no-reconnect (pg_dump & pg_restore)
- *		Added code to dump 'Create Schema' statement (pg_dump)
- *		Don't bother to disable/enable triggers if we don't have a superuser (pg_restore)
- *		Cleaned up code for reconnecting to database.
- *		Force a reconnect as superuser before enabling/disabling triggers.
- *
- * Modifications - 6-Mar-2001 - pjw@rhyme.com.au
- *		Change -U option to -L to allow -U to specify username in future.
+ *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.34 2002/05/10 22:36:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -94,6 +79,7 @@ main(int argc, char **argv)
 	extern int	optind;
 	extern char *optarg;
 	static int	use_setsessauth = 0;
+	static int	disable_triggers = 0;
 
 #ifdef HAVE_GETOPT_LONG
 	struct option cmdopts[] = {
@@ -130,6 +116,8 @@ main(int argc, char **argv)
 		 * letter, but are available as '-X long-name'
 		 */
 		{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
+		{"disable-triggers", no_argument, &disable_triggers, 1},
+
 		{NULL, 0, NULL, 0}
 	};
 #endif   /* HAVE_GETOPT_LONG */
@@ -281,6 +269,8 @@ main(int argc, char **argv)
 			case 'X':
 				if (strcmp(optarg, "use-set-session-authorization") == 0)
 					use_setsessauth = 1;
+				else if (strcmp(optarg, "disable-triggers") == 0)
+					disable_triggers = 1;
 				else
 				{
 					fprintf(stderr,
@@ -309,6 +299,7 @@ main(int argc, char **argv)
 		fileSpec = NULL;
 
 	opts->use_setsessauth = use_setsessauth;
+	opts->disable_triggers = disable_triggers;
 
 	if (opts->formatName)
 	{
@@ -385,74 +376,77 @@ usage(const char *progname)
 		   progname, progname);
 #ifdef HAVE_GETOPT_LONG
 	puts(gettext(
-		  "  -a, --data-only          restore only the data, no schema\n"
-	   "  -c, --clean              clean (drop) schema prior to create\n"
-	 "  -C, --create             issue commands to create the database\n"
-				 "  -d, --dbname=NAME        output database name\n"
-				 "  -f, --file=FILENAME      output file name\n"
-				 "  -F, --format={c|t}       specify backup file format\n"
-				 "  -h, --host=HOSTNAME      server host name\n"
-				 "  -i, --index=NAME         restore named index\n"
-	   "  -l, --list               print summarized TOC of the archive\n"
-				 "  -L, --use-list=FILENAME  use specified table of contents for ordering\n"
-				 "                           output from this file\n"
-			"  -N, --orig-order         restore in original dump order\n"
-				 "  -o, --oid-order          restore in OID order\n"
-	 "  -O, --no-owner           do not reconnect to database to match\n"
-				 "                           object owner\n"
-				 "  -p, --port=PORT          server port number\n"
-				 "  -P, --function=NAME      restore named function\n"
-				 "  -r, --rearrange          rearrange output to put indexes etc. at end\n"
-				 "  -R, --no-reconnect       disallow ALL reconnections to the database\n"
-		  "  -s, --schema-only        restore only the schema, no data\n"
-				 "  -S, --superuser=NAME     specify the superuser user name to use for\n"
-				 "                           disabling triggers\n"
-				 "  -t, --table=NAME         restore named table\n"
-				 "  -T, --trigger=NAME       restore named trigger\n"
+		"  -a, --data-only          restore only the data, no schema\n"
+		"  -c, --clean              clean (drop) schema prior to create\n"
+		"  -C, --create             issue commands to create the database\n"
+		"  -d, --dbname=NAME        output database name\n"
+		"  -f, --file=FILENAME      output file name\n"
+		"  -F, --format={c|t}       specify backup file format\n"
+		"  -h, --host=HOSTNAME      server host name\n"
+		"  -i, --index=NAME         restore named index\n"
+		"  -l, --list               print summarized TOC of the archive\n"
+		"  -L, --use-list=FILENAME  use specified table of contents for ordering\n"
+		"                           output from this file\n"
+		"  -N, --orig-order         restore in original dump order\n"
+		"  -o, --oid-order          restore in OID order\n"
+		"  -O, --no-owner           do not reconnect to database to match\n"
+		"                           object owner\n"
+		"  -p, --port=PORT          server port number\n"
+		"  -P, --function=NAME      restore named function\n"
+		"  -r, --rearrange          rearrange output to put indexes etc. at end\n"
+		"  -R, --no-reconnect       disallow ALL reconnections to the database\n"
+		"  -s, --schema-only        restore only the schema, no data\n"
+		"  -S, --superuser=NAME     specify the superuser user name to use for\n"
+		"                           disabling triggers\n"
+		"  -t, --table=NAME         restore named table\n"
+		"  -T, --trigger=NAME       restore named trigger\n"
 		"  -U, --username=NAME      connect as specified database user\n"
-				 "  -v, --verbose            verbose mode\n"
-				 "  -W, --password           force password prompt (should happen automatically)\n"
-				 "  -x, --no-privileges      skip restoration of access privileges (grant/revoke)\n"
-				 "  -X use-set-session-authorization, --use-set-session-authorization\n"
-				 "                           use SET SESSION AUTHORIZATION commands instead\n"
-			  "                           of reconnecting, if possible\n"
-				 ));
+		"  -v, --verbose            verbose mode\n"
+		"  -W, --password           force password prompt (should happen automatically)\n"
+		"  -x, --no-privileges      skip restoration of access privileges (grant/revoke)\n"
+		"  -X use-set-session-authorization, --use-set-session-authorization\n"
+		"                           use SET SESSION AUTHORIZATION commands instead\n"
+		"                           of reconnecting, if possible\n"
+		"  -X disable-triggers, --disable-triggers\n"
+		"                           disable triggers during data-only restore\n"
+		));
 
 #else							/* not HAVE_GETOPT_LONG */
 
 	puts(gettext(
-		  "  -a                       restore only the data, no schema\n"
-	   "  -c                       clean (drop) schema prior to create\n"
-	 "  -C                       issue commands to create the database\n"
-				 "  -d NAME                  output database name\n"
-				 "  -f FILENAME              output file name\n"
-				 "  -F {c|t}                 specify backup file format\n"
-				 "  -h HOSTNAME              server host name\n"
-				 "  -i NAME                  restore named index\n"
-	   "  -l                       print summarized TOC of the archive\n"
-				 "  -L FILENAME              use specified table of contents for ordering\n"
-				 "                           output from this file\n"
-			"  -N                       restore in original dump order\n"
-				 "  -o                       restore in OID order\n"
-	 "  -O                       do not reconnect to database to match\n"
-				 "                           object owner\n"
-				 "  -p PORT                  server port number\n"
-				 "  -P NAME                  restore named function\n"
-				 "  -r                       rearrange output to put indexes etc. at end\n"
-				 "  -R                       disallow ALL reconnections to the database\n"
-		  "  -s                       restore only the schema, no data\n"
-				 "  -S NAME                  specify the superuser user name to use for\n"
-				 "                           disabling triggers\n"
-				 "  -t NAME                  restore named table\n"
-				 "  -T NAME                  restore named trigger\n"
+		"  -a                       restore only the data, no schema\n"
+		"  -c                       clean (drop) schema prior to create\n"
+		"  -C                       issue commands to create the database\n"
+		"  -d NAME                  output database name\n"
+		"  -f FILENAME              output file name\n"
+		"  -F {c|t}                 specify backup file format\n"
+		"  -h HOSTNAME              server host name\n"
+		"  -i NAME                  restore named index\n"
+		"  -l                       print summarized TOC of the archive\n"
+		"  -L FILENAME              use specified table of contents for ordering\n"
+		"                           output from this file\n"
+		"  -N                       restore in original dump order\n"
+		"  -o                       restore in OID order\n"
+		"  -O                       do not reconnect to database to match\n"
+		"                           object owner\n"
+		"  -p PORT                  server port number\n"
+		"  -P NAME                  restore named function\n"
+		"  -r                       rearrange output to put indexes etc. at end\n"
+		"  -R                       disallow ALL reconnections to the database\n"
+		"  -s                       restore only the schema, no data\n"
+		"  -S NAME                  specify the superuser user name to use for\n"
+		"                           disabling triggers\n"
+		"  -t NAME                  restore named table\n"
+		"  -T NAME                  restore named trigger\n"
 		"  -U NAME                  connect as specified database user\n"
-				 "  -v                       verbose mode\n"
-				 "  -W                       force password prompt (should happen automatically)\n"
-				 "  -x                       skip restoration of access privileges (grant/revoke)\n"
-				 "  -X use-set-session-authorization\n"
-				 "                           use SET SESSION AUTHORIZATION commands instead\n"
-			  "                           of reconnecting, if possible\n"
-				 ));
+		"  -v                       verbose mode\n"
+		"  -W                       force password prompt (should happen automatically)\n"
+		"  -x                       skip restoration of access privileges (grant/revoke)\n"
+		"  -X use-set-session-authorization\n"
+		"                           use SET SESSION AUTHORIZATION commands instead\n"
+		"                           of reconnecting, if possible\n"
+		"  -X disable-triggers      disable triggers during data-only restore\n"
+		));
 #endif
 	puts(gettext("If no input file name is supplied, then standard input is used.\n"));
 	puts(gettext("Report bugs to <pgsql-bugs@postgresql.org>."));
-- 
GitLab