]> granicus.if.org Git - postgresql/blobdiff - src/bin/pg_dump/pg_dump.c
Fix all known problems with pg_dump's handling of serial sequences
[postgresql] / src / bin / pg_dump / pg_dump.c
index 501cf59f1e47d6def0558ceb70890e63bb079d41..78a653fb48c0e40cff40aa819d48e0f82deed8bd 100644 (file)
@@ -4,7 +4,7 @@
  *       pg_dump is a utility for dumping out a postgres database
  *       into a script file.
  *
- * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *     pg_dump will read the system catalogs in a database and dump out a
@@ -12,7 +12,7 @@
  *     by PostgreSQL
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.349 2003/09/23 22:48:53 tgl Exp $
+ *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.447 2006/08/21 00:57:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,6 +25,7 @@
 #include "postgres.h"
 
 #include <unistd.h>
+
 #include <ctype.h>
 #ifdef ENABLE_NLS
 #include <locale.h>
 
 #include "getopt_long.h"
 
-#ifndef HAVE_OPTRESET
+#ifndef HAVE_INT_OPTRESET
 int                    optreset;
 #endif
 
-#include "access/attnum.h"
+
+
 #include "access/htup.h"
 #include "catalog/pg_class.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_type.h"
-
 #include "commands/sequence.h"
-
-#include "libpq-fe.h"
 #include "libpq/libpq-fs.h"
+#include "mb/pg_wchar.h"
 
-#include "pg_dump.h"
-#include "pg_backup.h"
 #include "pg_backup_archiver.h"
 #include "dumputils.h"
 
-#define _(x) gettext((x))
-
-typedef struct _dumpContext
-{
-       TableInfo  *tblinfo;
-       int                     tblidx;
-       bool            oids;
-} DumpContext;
-
-static void help(const char *progname);
-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 dumpOneCompositeType(Archive *fout, TypeInfo *tinfo);
-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 dumpTableACL(Archive *fout, TableInfo *tbinfo);
-static void dumpFuncACL(Archive *fout, FuncInfo *finfo);
-static void dumpAggACL(Archive *fout, AggInfo *finfo);
-static void dumpACL(Archive *fout, const char *type, const char *name,
-               const char *tag, const char *nspname,
-               const char *owner, const char *acl, const char *objoid);
-
-static void dumpConstraints(Archive *fout, TableInfo *tblinfo, int numTables);
-static void dumpTriggers(Archive *fout, TableInfo *tblinfo, int numTables);
-static void dumpRules(Archive *fout, TableInfo *tblinfo, int numTables);
-static char *format_function_signature(FuncInfo *finfo, bool honor_quotes);
-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 dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo);
-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 int     dumpBlobs(Archive *AH, char *, void *);
-static int     dumpDatabase(Archive *AH);
-static const char *getAttrName(int attrnum, TableInfo *tblInfo);
-static const char *fmtCopyColumnList(const TableInfo *ti);
-
 extern char *optarg;
 extern int     optind,
                        opterr;
 
+
+typedef struct
+{
+       const char *descr;                      /* comment for an object */
+       Oid                     classoid;               /* object class (catalog OID) */
+       Oid                     objoid;                 /* object OID */
+       int                     objsubid;               /* subobject (table column #) */
+} CommentItem;
+
+
 /* global decls */
 bool           g_verbose;                      /* User wants verbose narration of our
                                                                 * activities. */
@@ -129,17 +79,31 @@ Archive    *g_fout;                                /* the script file */
 PGconn    *g_conn;                             /* the database connection */
 
 /* various user-settable parameters */
-bool           dumpData;                       /* dump data using proper insert strings */
+bool           dumpInserts;            /* dump data using proper insert strings */
 bool           attrNames;                      /* put attr names into insert strings */
 bool           schemaOnly;
 bool           dataOnly;
 bool           aclsSkip;
 
+/* subquery used to convert user ID (eg, datdba) to user name */
+static const char *username_subquery;
+
 /* 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 */
-static char *selectSchemaName = NULL;  /* name of a single schema to dump */
+/* select and exclude tables and schemas */
+typedef struct objnameArg
+{
+       struct objnameArg *next;
+       char *name;                     /* name of the relation */
+       bool is_include;        /* include/exclude? */
+} objnameArg;
+
+objnameArg *schemaList = NULL; /* List of schemas to include/exclude */
+objnameArg *tableList = NULL; /* List of tables to include/exclude */
+
+char *matchingSchemas = NULL; /* Final list of schemas to dump by oid */
+char *matchingTables = NULL; /* Final list of tables to dump by oid */
 
 char           g_opaque_type[10];      /* name for the opaque type */
 
@@ -147,14 +111,89 @@ char              g_opaque_type[10];      /* name for the opaque type */
 char           g_comment_start[10];
 char           g_comment_end[10];
 
+static const CatalogId nilCatalogId = {0, 0};
+
 /* these are to avoid passing around info for findNamespace() */
 static NamespaceInfo *g_namespaces;
 static int     g_numNamespaces;
 
+/* flag to turn on/off dollar quoting */
+static int     disable_dollar_quoting = 0;
+
+
+static void help(const char *progname);
+static NamespaceInfo *findNamespace(Oid nsoid, Oid objoid);
+static void dumpTableData(Archive *fout, TableDataInfo *tdinfo);
+static void dumpComment(Archive *fout, const char *target,
+                       const char *namespace, const char *owner,
+                       CatalogId catalogId, int subid, DumpId dumpId);
+static int findComments(Archive *fout, Oid classoid, Oid objoid,
+                        CommentItem **items);
+static int     collectComments(Archive *fout, CommentItem **items);
+static void dumpDumpableObject(Archive *fout, DumpableObject *dobj);
+static void dumpNamespace(Archive *fout, NamespaceInfo *nspinfo);
+static void dumpType(Archive *fout, TypeInfo *tinfo);
+static void dumpBaseType(Archive *fout, TypeInfo *tinfo);
+static void dumpDomain(Archive *fout, TypeInfo *tinfo);
+static void dumpCompositeType(Archive *fout, TypeInfo *tinfo);
+static void dumpShellType(Archive *fout, ShellTypeInfo *stinfo);
+static void dumpProcLang(Archive *fout, ProcLangInfo *plang);
+static void dumpFunc(Archive *fout, FuncInfo *finfo);
+static void dumpCast(Archive *fout, CastInfo *cast);
+static void dumpOpr(Archive *fout, OprInfo *oprinfo);
+static void dumpOpclass(Archive *fout, OpclassInfo *opcinfo);
+static void dumpConversion(Archive *fout, ConvInfo *convinfo);
+static void dumpRule(Archive *fout, RuleInfo *rinfo);
+static void dumpAgg(Archive *fout, AggInfo *agginfo);
+static void dumpTrigger(Archive *fout, TriggerInfo *tginfo);
+static void dumpTable(Archive *fout, TableInfo *tbinfo);
+static void dumpTableSchema(Archive *fout, TableInfo *tbinfo);
+static void dumpAttrDef(Archive *fout, AttrDefInfo *adinfo);
+static void dumpSequence(Archive *fout, TableInfo *tbinfo);
+static void dumpIndex(Archive *fout, IndxInfo *indxinfo);
+static void dumpConstraint(Archive *fout, ConstraintInfo *coninfo);
+static void dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo);
+
+static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
+               const char *type, const char *name,
+               const char *tag, const char *nspname, const char *owner,
+               const char *acls);
+
+static void getDependencies(void);
+static void getDomainConstraints(TypeInfo *tinfo);
+static void getTableData(TableInfo *tblinfo, int numTables, bool oids);
+static char *format_function_arguments(FuncInfo *finfo, int nallargs,
+                                                 char **allargtypes,
+                                                 char **argmodes,
+                                                 char **argnames);
+static char *format_function_signature(FuncInfo *finfo, bool honor_quotes);
+static const char *convertRegProcReference(const char *proc);
+static const char *convertOperatorReference(const char *opr);
+static Oid     findLastBuiltinOid_V71(const char *);
+static Oid     findLastBuiltinOid_V70(void);
+static void selectSourceSchema(const char *schemaName);
+static char *getFormattedTypeName(Oid oid, OidOptions opts);
+static char *myFormatType(const char *typname, int32 typmod);
+static const char *fmtQualifiedId(const char *schema, const char *id);
+static bool hasBlobs(Archive *AH);
+static int     dumpBlobs(Archive *AH, void *arg);
+static int     dumpBlobComments(Archive *AH, void *arg);
+static void dumpDatabase(Archive *AH);
+static void dumpEncoding(Archive *AH);
+static void dumpStdStrings(Archive *AH);
+static const char *getAttrName(int attrnum, TableInfo *tblInfo);
+static const char *fmtCopyColumnList(const TableInfo *ti);
+static void do_sql_command(PGconn *conn, const char *query);
+static void check_sql_result(PGresult *res, PGconn *conn, const char *query,
+                                ExecStatusType expected);
+
 
 int
 main(int argc, char **argv)
 {
+       PQExpBuffer query = createPQExpBuffer();
+       PGresult   *res;
+       objnameArg *this_obj_name, *schemaList_tail = NULL, *tableList_tail = NULL;
        int                     c;
        const char *filename = NULL;
        const char *format = "p";
@@ -162,17 +201,22 @@ main(int argc, char **argv)
        const char *pghost = NULL;
        const char *pgport = NULL;
        const char *username = NULL;
+       const char *dumpencoding = NULL;
+       const char *std_strings;
        bool            oids = false;
-       PGresult   *res;
        TableInfo  *tblinfo;
        int                     numTables;
+       DumpableObject **dobjs;
+       int                     numObjs;
+       int                     i;
+       bool            switch_include_exclude;
        bool            force_password = false;
        int                     compressLevel = -1;
        bool            ignore_version = false;
        int                     plainText = 0;
        int                     outputClean = 0;
        int                     outputCreate = 0;
-       int                     outputBlobs = 0;
+       bool            outputBlobs = true;
        int                     outputNoOwner = 0;
        static int      use_setsessauth = 0;
        static int      disable_triggers = 0;
@@ -197,34 +241,34 @@ main(int argc, char **argv)
                {"no-owner", no_argument, NULL, 'O'},
                {"port", required_argument, NULL, 'p'},
                {"schema", required_argument, NULL, 'n'},
+               {"exclude-schema", required_argument, NULL, 'N'},
                {"schema-only", no_argument, NULL, 's'},
                {"superuser", required_argument, NULL, 'S'},
                {"table", required_argument, NULL, 't'},
+               {"exclude-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'},
+               {"encoding", required_argument, NULL, 'E'},
                {"help", no_argument, NULL, '?'},
                {"version", no_argument, NULL, 'V'},
 
                /*
-                * the following options don't have an equivalent short option
-                * letter, but are available as '-X long-name'
+                * 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-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
                {"disable-triggers", no_argument, &disable_triggers, 1},
+               {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
 
                {NULL, 0, NULL, 0}
        };
        int                     optindex;
 
-#ifdef ENABLE_NLS
-       setlocale(LC_ALL, "");
-       bindtextdomain("pg_dump", LOCALEDIR);
-       textdomain("pg_dump");
-#endif
+       set_pglocale_pgservice(argv[0], "pg_dump");
 
        g_verbose = false;
 
@@ -232,16 +276,13 @@ main(int argc, char **argv)
        g_comment_end[0] = '\0';
        strcpy(g_opaque_type, "opaque");
 
-       dataOnly = schemaOnly = dumpData = attrNames = false;
+       dataOnly = schemaOnly = dumpInserts = attrNames = false;
 
        progname = get_progname(argv[0]);
 
        /* Set default options based on progname */
        if (strcmp(progname, "pg_backup") == 0)
-       {
                format = "c";
-               outputBlobs = true;
-       }
 
        if (argc > 1)
        {
@@ -257,7 +298,7 @@ main(int argc, char **argv)
                }
        }
 
-       while ((c = getopt_long(argc, argv, "abcCdDf:F:h:in:oOp:RsS:t:uU:vWxX:Z:",
+       while ((c = getopt_long(argc, argv, "abcCdDE:f:F:h:in:N:oOp:RsS:t:T:uU:vWxX:Z:",
                                                        long_options, &optindex)) != -1)
        {
                switch (c)
@@ -267,11 +308,10 @@ main(int argc, char **argv)
                                break;
 
                        case 'b':                       /* Dump blobs */
-                               outputBlobs = true;
+                               /* this is now default, so just ignore the switch */
                                break;
 
-                       case 'c':                       /* clean (i.e., drop) schema prior to
-                                                                * create */
+                       case 'c':                       /* clean (i.e., drop) schema prior to create */
                                outputClean = 1;
                                break;
 
@@ -280,15 +320,19 @@ main(int argc, char **argv)
                                break;
 
                        case 'd':                       /* dump data as proper insert strings */
-                               dumpData = true;
+                               dumpInserts = true;
                                break;
 
                        case 'D':                       /* dump data as proper insert strings with
                                                                 * attr names */
-                               dumpData = true;
+                               dumpInserts = true;
                                attrNames = true;
                                break;
 
+                       case 'E':                       /* Dump encoding */
+                               dumpencoding = optarg;
+                               break;
+
                        case 'f':
                                filename = optarg;
                                break;
@@ -305,8 +349,42 @@ main(int argc, char **argv)
                                ignore_version = true;
                                break;
 
-                       case 'n':                       /* Dump data for this schema only */
-                               selectSchemaName = strdup(optarg);
+                       case 'n':               /* Include schemas */
+                       case 'N':               /* Exclude schemas */
+                       case 't':               /* Include tables */
+                       case 'T':               /* Exclude tables */
+
+                               if (strlen(optarg) < 1)
+                               {
+                                       fprintf(stderr, _("%s: invalid -%c option\n"), progname, c);
+                                       exit(1);
+                               }
+
+                               {
+                                       /* Create a struct for this name */
+                                       objnameArg *new_obj_name = (objnameArg *)
+                                                                                               malloc(sizeof(objnameArg));
+
+                                       new_obj_name->next = NULL;
+                                       new_obj_name->name = strdup(optarg);
+                                       new_obj_name->is_include = islower(c) ? true : false;
+
+                                       /* add new entry to the proper list */
+                                       if (tolower(c) == 'n')
+                                       {
+                                               if (!schemaList_tail)
+                                                       schemaList_tail = schemaList = new_obj_name;
+                                               else
+                                                       schemaList_tail = schemaList_tail->next = new_obj_name;
+                                       }
+                                       else
+                                       {
+                                               if (!tableList_tail)
+                                                       tableList_tail = tableList = new_obj_name;
+                                               else
+                                                       tableList_tail = tableList_tail->next = new_obj_name;
+                                       }
+                               }
                                break;
 
                        case 'o':                       /* Dump oids */
@@ -327,17 +405,13 @@ main(int argc, char **argv)
 
                        case 's':                       /* dump schema only */
                                schemaOnly = true;
+                               outputBlobs = false;
                                break;
 
-                       case 'S':                       /* Username for superuser in plain text
-                                                                * output */
+                       case 'S':                       /* Username for superuser in plain text output */
                                outputSuperuser = strdup(optarg);
                                break;
 
-                       case 't':                       /* Dump data for this table only */
-                               selectTableName = strdup(optarg);
-                               break;
-
                        case 'u':
                                force_password = true;
                                username = simple_prompt("User name: ", 100, true);
@@ -360,17 +434,19 @@ main(int argc, char **argv)
                                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'.
+                                * 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)
-                                       /* no-op, still allowed for compatibility */ ;
+                               if (strcmp(optarg, "disable-dollar-quoting") == 0)
+                                       disable_dollar_quoting = 1;
                                else if (strcmp(optarg, "disable-triggers") == 0)
                                        disable_triggers = 1;
+                               else if (strcmp(optarg, "use-set-session-authorization") == 0)
+                                       use_setsessauth = 1;
                                else
                                {
                                        fprintf(stderr,
@@ -420,34 +496,16 @@ main(int argc, char **argv)
                exit(1);
        }
 
-       if (outputBlobs && selectTableName != NULL)
-       {
-               write_msg(NULL, "large-object output not supported for a single table\n");
-               write_msg(NULL, "use a full dump instead\n");
-               exit(1);
-       }
-
-       if (outputBlobs && selectSchemaName != NULL)
-       {
-               write_msg(NULL, "large-object output not supported for a single schema\n");
-               write_msg(NULL, "use a full dump instead\n");
-               exit(1);
-       }
+       if (matchingTables != NULL || matchingSchemas != NULL)
+               outputBlobs = false;
 
-       if (dumpData == true && oids == true)
+       if (dumpInserts == true && oids == true)
        {
                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 (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);
-       }
-
        /* open the output file */
        switch (format[0])
        {
@@ -495,46 +553,56 @@ main(int argc, char **argv)
        }
 
        /*
-        * Open the database using the Archiver, so it knows about it. Errors
-        * mean death.
+        * Open the database using the Archiver, so it knows about it. Errors mean
+        * death.
         */
        g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport,
                                                         username, force_password, ignore_version);
 
+       /* Set the client encoding if requested */
+       if (dumpencoding)
+       {
+               if (PQsetClientEncoding(g_conn, dumpencoding) < 0)
+               {
+                       write_msg(NULL, "invalid client encoding \"%s\" specified\n",
+                                         dumpencoding);
+                       exit(1);
+               }
+       }
+
        /*
-        * Start serializable transaction to dump consistent data.
+        * Get the active encoding and the standard_conforming_strings setting,
+        * so we know how to escape strings.
         */
-       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);
+       g_fout->encoding = PQclientEncoding(g_conn);
 
-       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));
-       PQclear(res);
+       std_strings = PQparameterStatus(g_conn, "standard_conforming_strings");
+       g_fout->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
 
        /* Set the datestyle to ISO to ensure the dump's portability */
-       res = PQexec(g_conn, "SET DATESTYLE = ISO");
-       if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
-               exit_horribly(g_fout, NULL, "could not set datestyle to ISO: %s",
-                                         PQerrorMessage(g_conn));
-       PQclear(res);
+       do_sql_command(g_conn, "SET DATESTYLE = ISO");
+
+       /*
+        * Start serializable transaction to dump consistent data.
+        */
+       do_sql_command(g_conn, "BEGIN");
+
+       do_sql_command(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
+
+       /* Select the appropriate subquery to convert user IDs to names */
+       if (g_fout->remoteVersion >= 80100)
+               username_subquery = "SELECT rolname FROM pg_catalog.pg_roles WHERE oid =";
+       else if (g_fout->remoteVersion >= 70300)
+               username_subquery = "SELECT usename FROM pg_catalog.pg_user WHERE usesysid =";
+       else
+               username_subquery = "SELECT usename FROM pg_user WHERE usesysid =";
 
        /*
         * If supported, set extra_float_digits so that we can dump float data
         * exactly (given correctly implemented float I/O code, anyway)
         */
        if (g_fout->remoteVersion >= 70400)
-       {
-               res = PQexec(g_conn, "SET extra_float_digits TO 2");
-               if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
-                       exit_horribly(g_fout, NULL, "could not set extra_float_digits: %s",
-                                                 PQerrorMessage(g_conn));
-               PQclear(res);
-       }
+               do_sql_command(g_conn, "SET extra_float_digits TO 2");
 
        /* Find the last built-in OID, if needed */
        if (g_fout->remoteVersion < 70300)
@@ -547,34 +615,232 @@ main(int argc, char **argv)
                        write_msg(NULL, "last built-in OID is %u\n", g_last_builtin_oid);
        }
 
-       /* Dump the database definition */
-       if (!dataOnly)
-               dumpDatabase(g_fout);
 
-       if (oids == true)
-               setMaxOid(g_fout);
+       if (schemaList != NULL && g_fout->remoteVersion < 70300)
+       {
+               write_msg(NULL, "Postgres must be at least version 7.3 to use schema switches\n");
+               exit_nicely();
+       }
+
+       /* Check schema selection flags */
+       resetPQExpBuffer(query);
+       switch_include_exclude = true;
 
-       tblinfo = dumpSchema(g_fout, &numTables, aclsSkip, schemaOnly, dataOnly);
+       for (this_obj_name = schemaList; this_obj_name; this_obj_name = this_obj_name->next)
+       {
+               if (switch_include_exclude)
+               {
+                       /* Special case for when -N is the first argument */
+                       if (this_obj_name == schemaList && !this_obj_name->is_include)
+                               appendPQExpBuffer(query,
+                                       "SELECT oid FROM pg_catalog.pg_namespace "
+                                       "WHERE nspname NOT LIKE 'pg_%%' AND "
+                                       "      nspname != 'information_schema' EXCEPT\n");
+       
+                       appendPQExpBuffer(query, "SELECT oid FROM pg_catalog.pg_namespace WHERE");
+               }
+       
+               appendPQExpBuffer(query, "%s nspname %c ", switch_include_exclude ? "" : " OR",
+                                                       /* any meta-characters? */
+                                                       strpbrk(this_obj_name->name,"([{\\.?+") == NULL ? '=' : '~');
+               appendStringLiteralAH(query, this_obj_name->name, g_fout);
+       
+               if (this_obj_name->next && this_obj_name->next->is_include == this_obj_name->is_include)
+                       switch_include_exclude = false;
+               else
+               {
+                       switch_include_exclude = true;
+       
+                       /* Add the joiner if needed */
+                       if (this_obj_name->next)
+                               appendPQExpBuffer(query, "\n%s\n",
+                                                                 this_obj_name->next->is_include ? "UNION" : "EXCEPT");
+               }
+       }
 
-       if (!schemaOnly)
-               dumpClasses(tblinfo, numTables, g_fout, oids);
+       /* Construct OID list of matching schemas */
+       if (schemaList)
+       {
+               int len;
+               
+               res = PQexec(g_conn, query->data);
+               check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+               if (PQntuples(res) == 0)
+               {
+                       write_msg(NULL, "No matching schemas were found\n");
+                       exit_nicely();
+               }
+
+               for (i = 0, len = strlen(" "); i < PQntuples(res); i++)
+                       len += strlen(PQgetvalue(res, i, 0)) + 1;
+
+               /*
+                *      Need to use comma separators so it can be used by IN.  zero
+                *      is a dummy placeholder.  Format is " oid oid oid ".
+                */
+               matchingSchemas = malloc(len + 1);
+               strcpy(matchingSchemas, " ");
+               for (i = 0; i < PQntuples(res); i++)
+               {
+                       strcat(matchingSchemas, PQgetvalue(res, i, 0));
+                       strcat(matchingSchemas, " ");
+               }
+       }
+
+       /* Check table selection flags */
+       resetPQExpBuffer(query);
+       switch_include_exclude = true;
+
+       for (this_obj_name = tableList; this_obj_name; this_obj_name = this_obj_name->next)
+       {
+               if (switch_include_exclude)
+               {
+                       /* Special case for when -T is the first argument */
+                       if (this_obj_name == tableList && !this_obj_name->is_include && !strlen(query->data))
+                               appendPQExpBuffer(query,
+                                       "SELECT pg_class.oid FROM pg_catalog.pg_class, pg_catalog.pg_namespace "
+                                       "WHERE relkind='r' AND "
+                                       "      relnamespace = pg_namespace.oid AND "
+                                       "      nspname NOT LIKE 'pg_%%' AND "
+                                       "      nspname != 'information_schema' EXCEPT\n");
+       
+                       appendPQExpBuffer(query, "SELECT oid FROM pg_catalog.pg_class WHERE relkind='r' AND (");
+               }
+       
+               appendPQExpBuffer(query, "%srelname %c ", switch_include_exclude ? "" : " OR ",
+                                                       /* any meta-characters? */
+                                                       strpbrk(this_obj_name->name,"([{\\.?+") == NULL ? '=' : '~');
+               appendStringLiteralAH(query, this_obj_name->name, g_fout);
+       
+               if (this_obj_name->next && this_obj_name->next->is_include == this_obj_name->is_include)
+                       switch_include_exclude = false;
+               else
+               {
+                       switch_include_exclude = true;
+                       appendPQExpBuffer(query, ")");
+               
+                       /* Add the joiner if needed */
+                       if (this_obj_name->next)
+                               appendPQExpBuffer(query, "\n%s\n", this_obj_name->next->is_include ?
+                                                                 "UNION" : "EXCEPT");
+               }
+       }
+
+       /* Construct OID list of matching tables */
+       if (tableList)
+       {
+               int len;
+               
+               /* Restrict by schema? */
+               if (matchingSchemas != NULL)
+               {
+                       char *matchingSchemas_commas = strdup(matchingSchemas), *p;
+
+                       /* Construct "IN" SQL string by adding commas, " oid, oid, oid " */
+                       for (p = matchingSchemas_commas; *p; p++)
+                       {
+                               /* No commas for first/last characters */
+                               if (*p == ' ' && p != matchingSchemas_commas && *(p+1))
+                                       *p = ',';
+                       }
+
+                       appendPQExpBuffer(query,
+                                                         "\nINTERSECT\nSELECT oid FROM pg_catalog.pg_class WHERE relkind='r' AND relnamespace IN (%s)\n",
+                                                         matchingSchemas_commas);
+               }
+
+               res = PQexec(g_conn, query->data);
+               check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+               if (PQntuples(res) == 0)
+               {
+                       write_msg(NULL, "No matching tables were found\n");
+                       exit_nicely();
+               }
+
+               for (i = 0, len = strlen(" "); i < PQntuples(res); i++)
+                       len += strlen(PQgetvalue(res, i, 0)) + 1;
+
+               matchingTables = malloc(len + 1);
+               strcpy(matchingTables, " ");
+               for (i = 0; i < PQntuples(res); i++)
+               {
+                       strcat(matchingTables, PQgetvalue(res, i, 0));
+                       strcat(matchingTables, " ");
+               }
+       }
+
+       destroyPQExpBuffer(query);
+
+       /*
+        * Now scan the database and create DumpableObject structs for all the
+        * objects we intend to dump.
+        */
+       tblinfo = getSchemaData(&numTables);
 
-       if (outputBlobs)
-               ArchiveEntry(g_fout, "0", "BLOBS", NULL, "",
-                                        "BLOBS", NULL, "", "", NULL, dumpBlobs, NULL);
+       if (!schemaOnly)
+               getTableData(tblinfo, numTables, oids);
 
-       if (!dataOnly)                          /* dump indexes and triggers at the end
-                                                                * for performance */
+       if (outputBlobs && hasBlobs(g_fout))
        {
-               dumpConstraints(g_fout, tblinfo, numTables);
-               dumpTriggers(g_fout, tblinfo, numTables);
-               dumpRules(g_fout, tblinfo, numTables);
+               /* Add placeholders to allow correct sorting of blobs */
+               DumpableObject *blobobj;
+
+               blobobj = (DumpableObject *) malloc(sizeof(DumpableObject));
+               blobobj->objType = DO_BLOBS;
+               blobobj->catId = nilCatalogId;
+               AssignDumpId(blobobj);
+               blobobj->name = strdup("BLOBS");
+
+               blobobj = (DumpableObject *) malloc(sizeof(DumpableObject));
+               blobobj->objType = DO_BLOB_COMMENTS;
+               blobobj->catId = nilCatalogId;
+               AssignDumpId(blobobj);
+               blobobj->name = strdup("BLOB COMMENTS");
        }
 
-       /* Now sort the output nicely: by OID within object types */
-       SortTocByOID(g_fout);
-       SortTocByObjectType(g_fout);
+       /*
+        * Collect dependency data to assist in ordering the objects.
+        */
+       getDependencies();
+
+       /*
+        * Sort the objects into a safe dump order (no forward references).
+        *
+        * In 7.3 or later, we can rely on dependency information to help us
+        * determine a safe order, so the initial sort is mostly for cosmetic
+        * purposes: we sort by name to ensure that logically identical schemas
+        * will dump identically.  Before 7.3 we don't have dependencies and we
+        * use OID ordering as an (unreliable) guide to creation order.
+        */
+       getDumpableObjects(&dobjs, &numObjs);
+
+       if (g_fout->remoteVersion >= 70300)
+               sortDumpableObjectsByTypeName(dobjs, numObjs);
+       else
+               sortDumpableObjectsByTypeOid(dobjs, numObjs);
+
+       sortDumpableObjects(dobjs, numObjs);
+
+       /*
+        * Create archive TOC entries for all the objects to be dumped, in a safe
+        * order.
+        */
+
+       /* First the special ENCODING and STDSTRINGS entries. */
+       dumpEncoding(g_fout);
+       dumpStdStrings(g_fout);
+
+       /* The database item is always next, unless we don't want it at all */
+       if (!dataOnly && matchingTables == NULL && matchingSchemas == NULL)
+               dumpDatabase(g_fout);
+
+       /* Now the rearrangeable objects. */
+       for (i = 0; i < numObjs; i++)
+               dumpDumpableObject(g_fout, dobjs[i]);
 
+       /*
+        * And finally we can do the actual output.
+        */
        if (plainText)
        {
                ropt = NewRestoreOptions();
@@ -585,14 +851,15 @@ main(int argc, char **argv)
                ropt->create = outputCreate;
                ropt->noOwner = outputNoOwner;
                ropt->disable_triggers = disable_triggers;
+               ropt->use_setsessauth = use_setsessauth;
+               ropt->dataOnly = dataOnly;
 
                if (compressLevel == -1)
                        ropt->compression = 0;
                else
                        ropt->compression = compressLevel;
 
-               ropt->suppressDumpWarnings = true;              /* We've already shown
-                                                                                                * them */
+               ropt->suppressDumpWarnings = true;              /* We've already shown them */
 
                RestoreArchive(g_fout, ropt);
        }
@@ -600,6 +867,7 @@ main(int argc, char **argv)
        CloseArchive(g_fout);
 
        PQfinish(g_conn);
+
        exit(0);
 }
 
@@ -622,23 +890,30 @@ help(const char *progname)
        printf(_("  --version                output version information, then exit\n"));
 
        printf(_("\nOptions controlling the output content:\n"));
-       printf(_("  -a, --data-only          dump only the data, not the schema\n"));
-       printf(_("  -b, --blobs              include large objects in dump\n"));
-       printf(_("  -c, --clean              clean (drop) schema prior to create\n"));
-       printf(_("  -C, --create             include commands to create database in dump\n"));
-       printf(_("  -d, --inserts            dump data as INSERT, rather than COPY, commands\n"));
-       printf(_("  -D, --column-inserts     dump data as INSERT commands with column names\n"));
-       printf(_("  -n, --schema=SCHEMA      dump the named schema only\n"));
-       printf(_("  -o, --oids               include OIDs in dump\n"));
-       printf(_("  -O, --no-owner           do not output commands to set object ownership\n"
-                        "                           in plain text format\n"));
-       printf(_("  -s, --schema-only        dump only the schema, no data\n"));
-       printf(_("  -S, --superuser=NAME     specify the superuser user name to use in\n"
-                        "                           plain text format\n"));
-       printf(_("  -t, --table=TABLE        dump the named table only\n"));
-       printf(_("  -x, --no-privileges      do not dump privileges (grant/revoke)\n"));
+       printf(_("  -a, --data-only             dump only the data, not the schema\n"));
+       printf(_("  -c, --clean                 clean (drop) schema prior to create\n"));
+       printf(_("  -C, --create                include commands to create database in dump\n"));
+       printf(_("  -d, --inserts               dump data as INSERT, rather than COPY, commands\n"));
+       printf(_("  -D, --column-inserts        dump data as INSERT commands with column names\n"));
+       printf(_("  -E, --encoding=ENCODING     dump the data in encoding ENCODING\n"));
+       printf(_("  -n, --schema=SCHEMA         dump the named schema only\n"));
+       printf(_("  -N, --exclude-schema=SCHEMA do NOT dump the named schema\n"));
+       printf(_("  -o, --oids                  include OIDs in dump\n"));
+       printf(_("  -O, --no-owner              skip restoration of object ownership\n"
+                        "                              in plain text format\n"));
+       printf(_("  -s, --schema-only           dump only the schema, no data\n"));
+       printf(_("  -S, --superuser=NAME        specify the superuser user name to use in\n"
+                        "                              plain text format\n"));
+       printf(_("  -t, --table=TABLE           dump the named table only\n"));
+       printf(_("  -T, --exclude-table=TABLE   do NOT dump the named table\n"));
+       printf(_("  -x, --no-privileges         do not dump privileges (grant/revoke)\n"));
+       printf(_("  -X disable-dollar-quoting, --disable-dollar-quoting\n"
+                        "                              disable dollar quoting, use SQL standard quoting\n"));
        printf(_("  -X disable-triggers, --disable-triggers\n"
-                        "                           disable triggers during data-only restore\n"));
+                        "                              disable triggers during data-only restore\n"));
+       printf(_("  -X use-set-session-authorization, --use-set-session-authorization\n"
+                        "                              use SESSION AUTHORIZATION commands instead of\n"
+                        "                              OWNER TO commands\n"));
 
        printf(_("\nConnection options:\n"));
        printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
@@ -668,24 +943,28 @@ static void
 selectDumpableNamespace(NamespaceInfo *nsinfo)
 {
        /*
-        * If a specific table is being dumped, do not dump any complete
-        * namespaces.  If a specific namespace is being dumped, dump just
-        * that namespace. Otherwise, dump all non-system namespaces.
+        * If specific tables are being dumped, do not dump any complete
+        * namespaces.  If specific namespaces are being dumped, dump just 
+        * those namespaces. Otherwise, dump all non-system namespaces.
         */
-       if (selectTableName != NULL)
-               nsinfo->dump = false;
-       else if (selectSchemaName != NULL)
+       nsinfo->dobj.dump = false;
+
+       if (matchingTables != NULL)
+               /* false */;
+       else if (matchingSchemas != NULL)
        {
-               if (strcmp(nsinfo->nspname, selectSchemaName) == 0)
-                       nsinfo->dump = true;
-               else
-                       nsinfo->dump = false;
+               char *search_oid = malloc(20);
+
+               sprintf(search_oid, " %d ", nsinfo->dobj.catId.oid);
+               if (strstr(matchingSchemas, search_oid) != NULL)
+                       nsinfo->dobj.dump = true;
+
+               free(search_oid);
        }
-       else if (strncmp(nsinfo->nspname, "pg_", 3) == 0 ||
-                        strcmp(nsinfo->nspname, "information_schema") == 0)
-               nsinfo->dump = false;
-       else
-               nsinfo->dump = true;
+       /* The server prevents users from creating pg_ schemas */
+       else if (strncmp(nsinfo->dobj.name, "pg_", 3) != 0 &&
+                        strcmp(nsinfo->dobj.name, "information_schema") != 0)
+               nsinfo->dobj.dump = true;
 }
 
 /*
@@ -697,44 +976,95 @@ 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.
+        * tablename has been specified, dump matching table name; else, do not
+        * dump.
         */
-       tbinfo->dump = false;
-       if (tbinfo->relnamespace->dump)
-               tbinfo->dump = true;
-       else if (selectTableName != NULL &&
-                        strcmp(tbinfo->relname, selectTableName) == 0)
-       {
-               /* If both -s and -t specified, must match both to dump */
-               if (selectSchemaName == NULL)
-                       tbinfo->dump = true;
-               else if (strcmp(tbinfo->relnamespace->nspname, selectSchemaName) == 0)
-                       tbinfo->dump = true;
+       tbinfo->dobj.dump = false;
+
+       if (matchingTables == NULL)
+       {
+               if (tbinfo->dobj.namespace->dobj.dump)
+                       tbinfo->dobj.dump = true;
+       }
+       else
+       {
+               char *search_oid = malloc(20);
+
+               sprintf(search_oid, " %d ", tbinfo->dobj.catId.oid);
+               if (strstr(matchingTables, search_oid) != NULL)
+                       tbinfo->dobj.dump = true;
+
+               free(search_oid);
        }
 }
 
+/*
+ * selectDumpableType: policy-setting subroutine
+ *             Mark a type as to be dumped or not
+ */
+static void
+selectDumpableType(TypeInfo *tinfo)
+{
+       /* Dump only types in dumpable namespaces */
+       if (!tinfo->dobj.namespace->dobj.dump)
+               tinfo->dobj.dump = false;
+
+       /* skip complex types, except for standalone composite types */
+       /* (note: this test should now be unnecessary) */
+       else if (OidIsValid(tinfo->typrelid) &&
+                        tinfo->typrelkind != RELKIND_COMPOSITE_TYPE)
+               tinfo->dobj.dump = false;
+
+       /* skip undefined placeholder types */
+       else if (!tinfo->isDefined)
+               tinfo->dobj.dump = false;
+
+       /* skip all array types that start w/ underscore */
+       else if ((tinfo->dobj.name[0] == '_') &&
+                        OidIsValid(tinfo->typelem))
+               tinfo->dobj.dump = false;
+
+       else
+               tinfo->dobj.dump = true;
+}
+
+/*
+ * selectDumpableObject: policy-setting subroutine
+ *             Mark a generic dumpable object as to be dumped or not
+ *
+ * Use this only for object types without a special-case routine above.
+ */
+static void
+selectDumpableObject(DumpableObject *dobj)
+{
+       /*
+        * Default policy is to dump if parent namespace is dumpable,
+        * or always for non-namespace-associated items.
+        */
+       if (dobj->namespace)
+               dobj->dump = dobj->namespace->dobj.dump;
+       else
+               dobj->dump = true;
+}
+
 /*
  *     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.
  */
 
-#define COPYBUFSIZ             8192
-
 static int
-dumpClasses_nodumpData(Archive *fout, char *oid, void *dctxv)
+dumpTableData_copy(Archive *fout, void *dcontext)
 {
-       const DumpContext *dctx = (DumpContext *) dctxv;
-       TableInfo  *tbinfo = &dctx->tblinfo[dctx->tblidx];
-       const char *classname = tbinfo->relname;
+       TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
+       TableInfo  *tbinfo = tdinfo->tdtable;
+       const char *classname = tbinfo->dobj.name;
        const bool      hasoids = tbinfo->hasoids;
-       const bool      oids = dctx->oids;
+       const bool      oids = tdinfo->oids;
        PQExpBuffer q = createPQExpBuffer();
        PGresult   *res;
        int                     ret;
-       bool            copydone;
-       char            copybuf[COPYBUFSIZ];
+       char       *copybuf;
        const char *column_list;
 
        if (g_verbose)
@@ -742,17 +1072,17 @@ dumpClasses_nodumpData(Archive *fout, char *oid, void *dctxv)
 
        /*
         * 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.
+        * 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);
+       selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
 
        /*
         * If possible, specify the column list explicitly so that we have no
-        * possibility of retrieving data in the wrong column order.  (The
-        * default column ordering of COPY will not be what we want in certain
-        * corner cases involving ADD COLUMN and inheritance.)
+        * possibility of retrieving data in the wrong column order.  (The default
+        * column ordering of COPY will not be what we want in certain corner
+        * cases involving ADD COLUMN and inheritance.)
         */
        if (g_fout->remoteVersion >= 70300)
                column_list = fmtCopyColumnList(tbinfo);
@@ -762,128 +1092,100 @@ dumpClasses_nodumpData(Archive *fout, char *oid, void *dctxv)
        if (oids && hasoids)
        {
                appendPQExpBuffer(q, "COPY %s %s WITH OIDS TO stdout;",
-                                                 fmtQualifiedId(tbinfo->relnamespace->nspname,
+                                                 fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
                                                                                 classname),
                                                  column_list);
        }
        else
        {
                appendPQExpBuffer(q, "COPY %s %s TO stdout;",
-                                                 fmtQualifiedId(tbinfo->relnamespace->nspname,
+                                                 fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
                                                                                 classname),
                                                  column_list);
        }
        res = PQexec(g_conn, q->data);
-       if (!res ||
-               PQresultStatus(res) == PGRES_FATAL_ERROR)
-       {
-               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 (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", q->data);
-               exit_nicely();
-       }
-
-       copydone = false;
+       check_sql_result(res, g_conn, q->data, PGRES_COPY_OUT);
+       PQclear(res);
 
-       while (!copydone)
+       for (;;)
        {
-               ret = PQgetline(g_conn, copybuf, COPYBUFSIZ);
+               ret = PQgetCopyData(g_conn, &copybuf, 0);
 
-               if (copybuf[0] == '\\' &&
-                       copybuf[1] == '.' &&
-                       copybuf[2] == '\0')
-               {
-                       copydone = true;        /* don't print this... */
-               }
-               else
+               if (ret < 0)
+                       break;                          /* done or error */
+
+               if (copybuf)
                {
-                       archputs(copybuf, fout);
-                       switch (ret)
-                       {
-                               case EOF:
-                                       copydone = true;
-                                       /* FALLTHROUGH */
-                               case 0:
-                                       archputc('\n', fout);
-                                       break;
-                               case 1:
-                                       break;
-                       }
+                       WriteData(fout, copybuf, ret);
+                       PQfreemem(copybuf);
                }
 
                /*
                 * 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.
+                * slowing down pg_dump when backing up large tables. Users with both
+                * slow & fast (multi-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:
+                * 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
+                * 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.
+                * 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.
+                * 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. Finally, call gettimeofday again to save the 'last sleep
-                * time'.
+                * This will return after the interval specified in the structure tvi.
+                * Finally, call gettimeofday again to save the 'last sleep time'.
                 */
        }
        archprintf(fout, "\\.\n\n\n");
 
-       ret = PQendcopy(g_conn);
-       if (ret != 0)
+       if (ret == -2)
        {
-               write_msg(NULL, "SQL command to dump the contents of table \"%s\" failed: PQendcopy() failed.\n", classname);
+               /* copy data transfer failed */
+               write_msg(NULL, "Dumping the contents of table \"%s\" failed: PQgetCopyData() 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();
        }
 
+       /* Check command status and return to normal libpq state */
+       res = PQgetResult(g_conn);
+       check_sql_result(res, g_conn, q->data, PGRES_COMMAND_OK);
        PQclear(res);
+
        destroyPQExpBuffer(q);
        return 1;
 }
 
 static int
-dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
+dumpTableData_insert(Archive *fout, void *dcontext)
 {
-       const DumpContext *dctx = (DumpContext *) dctxv;
-       TableInfo  *tbinfo = &dctx->tblinfo[dctx->tblidx];
-       const char *classname = tbinfo->relname;
+       TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
+       TableInfo  *tbinfo = tdinfo->tdtable;
+       const char *classname = tbinfo->dobj.name;
        PQExpBuffer q = createPQExpBuffer();
        PGresult   *res;
        int                     tuple;
@@ -892,53 +1194,39 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
 
        /*
         * 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.
+        * 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);
+       selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
 
        if (fout->remoteVersion >= 70100)
        {
                appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
                                                  "SELECT * FROM ONLY %s",
-                                                 fmtQualifiedId(tbinfo->relnamespace->nspname,
+                                                 fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
                                                                                 classname));
        }
        else
        {
                appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
                                                  "SELECT * FROM %s",
-                                                 fmtQualifiedId(tbinfo->relnamespace->nspname,
+                                                 fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
                                                                                 classname));
        }
 
        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();
-       }
+       check_sql_result(res, g_conn, q->data, PGRES_COMMAND_OK);
 
        do
        {
                PQclear(res);
 
                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();
-               }
-
-               nfields = PQnfields(res);
-               for (tuple = 0; tuple < PQntuples(res); tuple++)
+               check_sql_result(res, g_conn, "FETCH 100 FROM _pg_dump_cursor",
+                                                PGRES_TUPLES_OK);
+               nfields = PQnfields(res);
+               for (tuple = 0; tuple < PQntuples(res); tuple++)
                {
                        archprintf(fout, "INSERT INTO %s ", fmtId(classname));
                        if (nfields == 0)
@@ -955,10 +1243,10 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
                                {
                                        if (field > 0)
                                                appendPQExpBuffer(q, ", ");
-                                       appendPQExpBuffer(q, fmtId(PQfname(res, field)));
+                                       appendPQExpBufferStr(q, fmtId(PQfname(res, field)));
                                }
                                appendPQExpBuffer(q, ") ");
-                               archprintf(fout, "%s", q->data);
+                               archputs(q->data, fout);
                        }
                        archprintf(fout, "VALUES (");
                        for (field = 0; field < nfields; field++)
@@ -983,16 +1271,15 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
                                        case NUMERICOID:
                                                {
                                                        /*
-                                                        * These types are printed without quotes
-                                                        * unless they contain values that aren't
-                                                        * accepted by the scanner unquoted (e.g.,
-                                                        * 'NaN').      Note that strtod() and friends
-                                                        * might accept NaN, so we can't use that to
-                                                        * test.
+                                                        * These types are printed without quotes unless
+                                                        * they contain values that aren't accepted by the
+                                                        * scanner unquoted (e.g., 'NaN').      Note that
+                                                        * strtod() and friends might accept NaN, so we
+                                                        * can't use that to test.
                                                         *
                                                         * In reality we only need to defend against
-                                                        * infinity and NaN, so we need not get too
-                                                        * crazy about pattern matching here.
+                                                        * infinity and NaN, so we need not get too crazy
+                                                        * about pattern matching here.
                                                         */
                                                        const char *s = PQgetvalue(res, tuple, field);
 
@@ -1019,8 +1306,10 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
                                        default:
                                                /* All other types are printed as string literals. */
                                                resetPQExpBuffer(q);
-                                               appendStringLiteral(q, PQgetvalue(res, tuple, field), false);
-                                               archprintf(fout, "%s", q->data);
+                                               appendStringLiteralAH(q,
+                                                                                         PQgetvalue(res, tuple, field),
+                                                                                         fout);
+                                               archputs(q->data, fout);
                                                break;
                                }
                        }
@@ -1028,19 +1317,11 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
                }
        } while (PQntuples(res) > 0);
 
-       archprintf(fout, "\n\n");
        PQclear(res);
 
-       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);
+       archprintf(fout, "\n\n");
+
+       do_sql_command(g_conn, "CLOSE _pg_dump_cursor");
 
        destroyPQExpBuffer(q);
        return 1;
@@ -1048,70 +1329,90 @@ dumpClasses_dumpData(Archive *fout, char *oid, void *dctxv)
 
 
 /*
- * DumpClasses -
- *       dump the contents of all the classes.
+ * dumpTableData -
+ *       dump the contents of a single table
+ *
+ * Actually, this just makes an ArchiveEntry for the table contents.
  */
 static void
-dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
-                       const bool oids)
+dumpTableData(Archive *fout, TableDataInfo *tdinfo)
 {
+       TableInfo  *tbinfo = tdinfo->tdtable;
        PQExpBuffer copyBuf = createPQExpBuffer();
        DataDumperPtr dumpFn;
-       DumpContext *dumpCtx;
        char       *copyStmt;
+
+       if (!dumpInserts)
+       {
+               /* Dump/restore using COPY */
+               dumpFn = dumpTableData_copy;
+               /* must use 2 steps here 'cause fmtId is nonreentrant */
+               appendPQExpBuffer(copyBuf, "COPY %s ",
+                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(copyBuf, "%s %sFROM stdin;\n",
+                                                 fmtCopyColumnList(tbinfo),
+                                         (tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : "");
+               copyStmt = copyBuf->data;
+       }
+       else
+       {
+               /* Restore using INSERT */
+               dumpFn = dumpTableData_insert;
+               copyStmt = NULL;
+       }
+
+       ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
+                                tbinfo->dobj.name,
+                                tbinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                tbinfo->rolname, false,
+                                "TABLE DATA", "", "", copyStmt,
+                                tdinfo->dobj.dependencies, tdinfo->dobj.nDeps,
+                                dumpFn, tdinfo);
+
+       destroyPQExpBuffer(copyBuf);
+}
+
+/*
+ * getTableData -
+ *       set up dumpable objects representing the contents of tables
+ */
+static void
+getTableData(TableInfo *tblinfo, int numTables, bool oids)
+{
        int                     i;
 
        for (i = 0; i < numTables; i++)
        {
-               const char *classname = tblinfo[i].relname;
-
-               /* Skip VIEW relations */
+               /* Skip VIEWs (no data to dump) */
                if (tblinfo[i].relkind == RELKIND_VIEW)
                        continue;
-
-               if (tblinfo[i].relkind == RELKIND_SEQUENCE)             /* already dumped */
+               /* Skip SEQUENCEs (handled elsewhere) */
+               if (tblinfo[i].relkind == RELKIND_SEQUENCE)
                        continue;
 
-               if (tblinfo[i].dump)
+               if (tblinfo[i].dobj.dump)
                {
-                       if (g_verbose)
-                               write_msg(NULL, "preparing to dump the contents of table %s\n",
-                                                 classname);
+                       TableDataInfo *tdinfo;
 
-                       dumpCtx = (DumpContext *) malloc(sizeof(DumpContext));
-                       dumpCtx->tblinfo = (TableInfo *) tblinfo;
-                       dumpCtx->tblidx = i;
-                       dumpCtx->oids = oids;
+                       tdinfo = (TableDataInfo *) malloc(sizeof(TableDataInfo));
 
-                       if (!dumpData)
-                       {
-                               /* Dump/restore using COPY */
-                               dumpFn = dumpClasses_nodumpData;
-                               resetPQExpBuffer(copyBuf);
-                               /* must use 2 steps here 'cause fmtId is nonreentrant */
-                               appendPQExpBuffer(copyBuf, "COPY %s ",
-                                                                 fmtId(tblinfo[i].relname));
-                               appendPQExpBuffer(copyBuf, "%s %sFROM stdin;\n",
-                                                                 fmtCopyColumnList(&(tblinfo[i])),
-                                          (oids && tblinfo[i].hasoids) ? "WITH OIDS " : "");
-                               copyStmt = copyBuf->data;
-                       }
-                       else
-                       {
-                               /* Restore using INSERT */
-                               dumpFn = dumpClasses_dumpData;
-                               copyStmt = NULL;
-                       }
+                       tdinfo->dobj.objType = DO_TABLE_DATA;
 
-                       ArchiveEntry(fout, tblinfo[i].oid, tblinfo[i].relname,
-                                                tblinfo[i].relnamespace->nspname,
-                                                tblinfo[i].usename,
-                                                "TABLE DATA", NULL, "", "", copyStmt,
-                                                dumpFn, dumpCtx);
+                       /*
+                        * Note: use tableoid 0 so that this object won't be mistaken for
+                        * something that pg_depend entries apply to.
+                        */
+                       tdinfo->dobj.catId.tableoid = 0;
+                       tdinfo->dobj.catId.oid = tblinfo[i].dobj.catId.oid;
+                       AssignDumpId(&tdinfo->dobj);
+                       tdinfo->dobj.name = tblinfo[i].dobj.name;
+                       tdinfo->dobj.namespace = tblinfo[i].dobj.namespace;
+                       tdinfo->tdtable = &(tblinfo[i]);
+                       tdinfo->oids = oids;
+                       addObjectDependency(&tdinfo->dobj, tblinfo[i].dobj.dumpId);
                }
        }
-
-       destroyPQExpBuffer(copyBuf);
 }
 
 
@@ -1119,7 +1420,7 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
  * dumpDatabase:
  *     dump the database definition
  */
-static int
+static void
 dumpDatabase(Archive *AH)
 {
        PQExpBuffer dbQry = createPQExpBuffer();
@@ -1127,13 +1428,17 @@ dumpDatabase(Archive *AH)
        PQExpBuffer creaQry = createPQExpBuffer();
        PGresult   *res;
        int                     ntups;
-       int                     i_dba,
+       int                     i_tableoid,
+                               i_oid,
+                               i_dba,
                                i_encoding,
-                               i_datpath;
+                               i_tablespace;
+       CatalogId       dbCatId;
+       DumpId          dbDumpId;
        const char *datname,
                           *dba,
                           *encoding,
-                          *datpath;
+                          *tablespace;
 
        datname = PQdb(g_conn);
 
@@ -1144,22 +1449,58 @@ dumpDatabase(Archive *AH)
        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,"
-                                         " pg_encoding_to_char(encoding) as encoding,"
-                                         " datpath from pg_database"
-                                         " where datname = ");
-       appendStringLiteral(dbQry, datname, true);
-
-       res = PQexec(g_conn, dbQry->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
+       if (g_fout->remoteVersion >= 80200)
+       {
+               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+                                                 "(%s datdba) as dba, "
+                                                 "pg_encoding_to_char(encoding) as encoding, "
+                                                 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) as tablespace, "
+                                                 "shobj_description(oid, 'pg_database') as description "
+
+                                                 "FROM pg_database "
+                                                 "WHERE datname = ",
+                                                 username_subquery);
+               appendStringLiteralAH(dbQry, datname, AH);
+       }
+       else if (g_fout->remoteVersion >= 80000)
+       {
+               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+                                                 "(%s datdba) as dba, "
+                                                 "pg_encoding_to_char(encoding) as encoding, "
+                                                 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) as tablespace "
+                                                 "FROM pg_database "
+                                                 "WHERE datname = ",
+                                                 username_subquery);
+               appendStringLiteralAH(dbQry, datname, AH);
+       }
+       else if (g_fout->remoteVersion >= 70100)
        {
-               write_msg(NULL, "SQL command failed\n");
-               write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
-               write_msg(NULL, "The command was: %s\n", dbQry->data);
-               exit_nicely();
+               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+                                                 "(%s datdba) as dba, "
+                                                 "pg_encoding_to_char(encoding) as encoding, "
+                                                 "NULL as tablespace "
+                                                 "FROM pg_database "
+                                                 "WHERE datname = ",
+                                                 username_subquery);
+               appendStringLiteralAH(dbQry, datname, AH);
+       }
+       else
+       {
+               appendPQExpBuffer(dbQry, "SELECT "
+                                                 "(SELECT oid FROM pg_class WHERE relname = 'pg_database') AS tableoid, "
+                                                 "oid, "
+                                                 "(%s datdba) as dba, "
+                                                 "pg_encoding_to_char(encoding) as encoding, "
+                                                 "NULL as tablespace "
+                                                 "FROM pg_database "
+                                                 "WHERE datname = ",
+                                                 username_subquery);
+               appendStringLiteralAH(dbQry, datname, AH);
        }
 
+       res = PQexec(g_conn, dbQry->data);
+       check_sql_result(res, g_conn, dbQry->data, PGRES_TUPLES_OK);
+
        ntups = PQntuples(res);
 
        if (ntups <= 0)
@@ -1176,72 +1517,179 @@ dumpDatabase(Archive *AH)
                exit_nicely();
        }
 
+       i_tableoid = PQfnumber(res, "tableoid");
+       i_oid = PQfnumber(res, "oid");
        i_dba = PQfnumber(res, "dba");
        i_encoding = PQfnumber(res, "encoding");
-       i_datpath = PQfnumber(res, "datpath");
+       i_tablespace = PQfnumber(res, "tablespace");
+
+       dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid));
+       dbCatId.oid = atooid(PQgetvalue(res, 0, i_oid));
        dba = PQgetvalue(res, 0, i_dba);
        encoding = PQgetvalue(res, 0, i_encoding);
-       datpath = PQgetvalue(res, 0, i_datpath);
+       tablespace = PQgetvalue(res, 0, i_tablespace);
 
        appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0",
                                          fmtId(datname));
-       if (strlen(datpath) > 0)
-       {
-               appendPQExpBuffer(creaQry, " LOCATION = ");
-               appendStringLiteral(creaQry, datpath, true);
-       }
        if (strlen(encoding) > 0)
        {
                appendPQExpBuffer(creaQry, " ENCODING = ");
-               appendStringLiteral(creaQry, encoding, true);
+               appendStringLiteralAH(creaQry, encoding, AH);
        }
+       if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0)
+               appendPQExpBuffer(creaQry, " TABLESPACE = %s",
+                                                 fmtId(tablespace));
        appendPQExpBuffer(creaQry, ";\n");
 
        appendPQExpBuffer(delQry, "DROP DATABASE %s;\n",
                                          fmtId(datname));
 
-       ArchiveEntry(AH, "0",           /* OID */
+       dbDumpId = createDumpId();
+
+       ArchiveEntry(AH,
+                                dbCatId,               /* catalog ID */
+                                dbDumpId,              /* dump ID */
                                 datname,               /* Name */
                                 NULL,                  /* Namespace */
+                                NULL,                  /* Tablespace */
                                 dba,                   /* Owner */
+                                false,                 /* with oids */
                                 "DATABASE",    /* Desc */
-                                NULL,                  /* Deps */
                                 creaQry->data, /* Create */
                                 delQry->data,  /* Del */
                                 NULL,                  /* Copy */
+                                NULL,                  /* Deps */
+                                0,                             /* # Deps */
                                 NULL,                  /* Dumper */
                                 NULL);                 /* Dumper Arg */
 
+       /* Dump DB comment if any */
+       if (g_fout->remoteVersion >= 80200)
+       {
+               /* 8.2 keeps comments on shared objects in a shared table, so
+                * we cannot use the dumpComment used for other database objects.
+                */
+               char *comment = PQgetvalue(res, 0, PQfnumber(res, "description"));
+               if (comment && strlen(comment)) {
+                       resetPQExpBuffer(dbQry);
+                       appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
+                       appendStringLiteralAH(dbQry, comment, AH);
+                       appendPQExpBuffer(dbQry, ";\n");
+
+                       ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
+                                                       dba, false, "COMMENT", dbQry->data, "", NULL,
+                                                       &dbDumpId, 1, NULL, NULL);
+               }
+       } else {
+               resetPQExpBuffer(dbQry);
+               appendPQExpBuffer(dbQry, "DATABASE %s", fmtId(datname));
+               dumpComment(AH, dbQry->data, NULL, "",
+                               dbCatId, 0, dbDumpId);
+       }
+
        PQclear(res);
 
        destroyPQExpBuffer(dbQry);
        destroyPQExpBuffer(delQry);
        destroyPQExpBuffer(creaQry);
+}
 
-       return 1;
+
+/*
+ * dumpEncoding: put the correct encoding into the archive
+ */
+static void
+dumpEncoding(Archive *AH)
+{
+       const char *encname = pg_encoding_to_char(AH->encoding);
+       PQExpBuffer qry = createPQExpBuffer();
+
+       if (g_verbose)
+               write_msg(NULL, "saving encoding = %s\n", encname);
+
+       appendPQExpBuffer(qry, "SET client_encoding = ");
+       appendStringLiteralAH(qry, encname, AH);
+       appendPQExpBuffer(qry, ";\n");
+
+       ArchiveEntry(AH, nilCatalogId, createDumpId(),
+                                "ENCODING", NULL, NULL, "",
+                                false, "ENCODING", qry->data, "", NULL,
+                                NULL, 0,
+                                NULL, NULL);
+
+       destroyPQExpBuffer(qry);
 }
 
 
 /*
- * dumpBlobs:
- *     dump all blobs
- *
+ * dumpStdStrings: put the correct escape string behavior into the archive
+ */
+static void
+dumpStdStrings(Archive *AH)
+{
+       const char *stdstrings = AH->std_strings ? "on" : "off";
+       PQExpBuffer qry = createPQExpBuffer();
+
+       if (g_verbose)
+               write_msg(NULL, "saving standard_conforming_strings = %s\n",
+                                 stdstrings);
+
+       appendPQExpBuffer(qry, "SET standard_conforming_strings = '%s';\n",
+                                         stdstrings);
+
+       ArchiveEntry(AH, nilCatalogId, createDumpId(),
+                                "STDSTRINGS", NULL, NULL, "",
+                                false, "STDSTRINGS", qry->data, "", NULL,
+                                NULL, 0,
+                                NULL, NULL);
+
+       destroyPQExpBuffer(qry);
+}
+
+
+/*
+ * hasBlobs:
+ *     Test whether database contains any large objects
  */
+static bool
+hasBlobs(Archive *AH)
+{
+       bool            result;
+       const char *blobQry;
+       PGresult   *res;
 
-#define loBufSize 16384
-#define loFetchSize 1000
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       /* Check for BLOB OIDs */
+       if (AH->remoteVersion >= 70100)
+               blobQry = "SELECT loid FROM pg_largeobject LIMIT 1";
+       else
+               blobQry = "SELECT oid FROM pg_class WHERE relkind = 'l' LIMIT 1";
+
+       res = PQexec(g_conn, blobQry);
+       check_sql_result(res, g_conn, blobQry, PGRES_TUPLES_OK);
+
+       result = PQntuples(res) > 0;
+
+       PQclear(res);
+
+       return result;
+}
 
+/*
+ * dumpBlobs:
+ *     dump all blobs
+ */
 static int
-dumpBlobs(Archive *AH, char *junkOid, void *junkVal)
+dumpBlobs(Archive *AH, void *arg)
 {
-       PQExpBuffer oidQry = createPQExpBuffer();
-       PQExpBuffer oidFetchQry = createPQExpBuffer();
+       const char *blobQry;
+       const char *blobFetchQry;
        PGresult   *res;
+       char            buf[LOBBUFSIZE];
        int                     i;
-       int                     loFd;
-       char            buf[loBufSize];
        int                     cnt;
-       Oid                     blobOid;
 
        if (g_verbose)
                write_msg(NULL, "saving large objects\n");
@@ -1249,38 +1697,32 @@ dumpBlobs(Archive *AH, char *junkOid, void *junkVal)
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
 
-       /* Cursor to get all BLOB tables */
+       /* Cursor to get all BLOB OIDs */
        if (AH->remoteVersion >= 70100)
-               appendPQExpBuffer(oidQry, "Declare blobOid Cursor for SELECT DISTINCT loid FROM pg_largeobject");
+               blobQry = "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject";
        else
-               appendPQExpBuffer(oidQry, "Declare blobOid Cursor for SELECT oid from pg_class where relkind = 'l'");
+               blobQry = "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_class WHERE relkind = 'l'";
 
-       res = PQexec(g_conn, oidQry->data);
-       if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
-       {
-               write_msg(NULL, "dumpBlobs(): cursor declaration failed: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       res = PQexec(g_conn, blobQry);
+       check_sql_result(res, g_conn, blobQry, PGRES_COMMAND_OK);
 
-       /* Fetch for cursor */
-       appendPQExpBuffer(oidFetchQry, "Fetch %d in blobOid", loFetchSize);
+       /* Command to fetch from cursor */
+       blobFetchQry = "FETCH 1000 IN bloboid";
 
        do
        {
-               /* Do a fetch */
                PQclear(res);
-               res = PQexec(g_conn, oidFetchQry->data);
 
-               if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
-               {
-                       write_msg(NULL, "dumpBlobs(): fetch from cursor failed: %s",
-                                         PQerrorMessage(g_conn));
-                       exit_nicely();
-               }
+               /* Do a fetch */
+               res = PQexec(g_conn, blobFetchQry);
+               check_sql_result(res, g_conn, blobFetchQry, PGRES_TUPLES_OK);
 
                /* Process the tuples, if any */
                for (i = 0; i < PQntuples(res); i++)
                {
+                       Oid                     blobOid;
+                       int                     loFd;
+
                        blobOid = atooid(PQgetvalue(res, i, 0));
                        /* Open the BLOB */
                        loFd = lo_open(g_conn, blobOid, INV_READ);
@@ -1296,7 +1738,7 @@ dumpBlobs(Archive *AH, char *junkOid, void *junkVal)
                        /* Now read it in chunks, sending data to archive */
                        do
                        {
-                               cnt = lo_read(g_conn, loFd, buf, loBufSize);
+                               cnt = lo_read(g_conn, loFd, buf, LOBBUFSIZE);
                                if (cnt < 0)
                                {
                                        write_msg(NULL, "dumpBlobs(): error reading large object: %s",
@@ -1305,18 +1747,91 @@ dumpBlobs(Archive *AH, char *junkOid, void *junkVal)
                                }
 
                                WriteData(AH, buf, cnt);
-
                        } while (cnt > 0);
 
                        lo_close(g_conn, loFd);
 
                        EndBlob(AH, blobOid);
+               }
+       } while (PQntuples(res) > 0);
+
+       PQclear(res);
+
+       return 1;
+}
+
+/*
+ * dumpBlobComments
+ *     dump all blob comments
+ *
+ * Since we don't provide any way to be selective about dumping blobs,
+ * there's no need to be selective about their comments either.  We put
+ * all the comments into one big TOC entry.
+ */
+static int
+dumpBlobComments(Archive *AH, void *arg)
+{
+       const char *blobQry;
+       const char *blobFetchQry;
+       PQExpBuffer commentcmd = createPQExpBuffer();
+       PGresult   *res;
+       int                     i;
+
+       if (g_verbose)
+               write_msg(NULL, "saving large object comments\n");
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       /* Cursor to get all BLOB comments */
+       if (AH->remoteVersion >= 70200)
+               blobQry = "DECLARE blobcmt CURSOR FOR SELECT loid, obj_description(loid, 'pg_largeobject') FROM (SELECT DISTINCT loid FROM pg_largeobject) ss";
+       else if (AH->remoteVersion >= 70100)
+               blobQry = "DECLARE blobcmt CURSOR FOR SELECT loid, obj_description(loid) FROM (SELECT DISTINCT loid FROM pg_largeobject) ss";
+       else
+               blobQry = "DECLARE blobcmt CURSOR FOR SELECT oid, (SELECT description FROM pg_description pd WHERE pd.objoid=pc.oid) FROM pg_class pc WHERE relkind = 'l'";
+
+       res = PQexec(g_conn, blobQry);
+       check_sql_result(res, g_conn, blobQry, PGRES_COMMAND_OK);
+
+       /* Command to fetch from cursor */
+       blobFetchQry = "FETCH 100 IN blobcmt";
+
+       do
+       {
+               PQclear(res);
+
+               /* Do a fetch */
+               res = PQexec(g_conn, blobFetchQry);
+               check_sql_result(res, g_conn, blobFetchQry, PGRES_TUPLES_OK);
+
+               /* Process the tuples, if any */
+               for (i = 0; i < PQntuples(res); i++)
+               {
+                       Oid                     blobOid;
+                       char       *comment;
+
+                       /* ignore blobs without comments */
+                       if (PQgetisnull(res, i, 1))
+                               continue;
+
+                       blobOid = atooid(PQgetvalue(res, i, 0));
+                       comment = PQgetvalue(res, i, 1);
 
+                       printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
+                                                         blobOid);
+                       appendStringLiteralAH(commentcmd, comment, AH);
+                       appendPQExpBuffer(commentcmd, ";\n");
+
+                       archputs(commentcmd->data, AH);
                }
        } while (PQntuples(res) > 0);
 
-       destroyPQExpBuffer(oidQry);
-       destroyPQExpBuffer(oidFetchQry);
+       PQclear(res);
+
+       archputs("\n", AH);
+
+       destroyPQExpBuffer(commentcmd);
 
        return 1;
 }
@@ -1336,29 +1851,36 @@ getNamespaces(int *numNamespaces)
        int                     i;
        PQExpBuffer query;
        NamespaceInfo *nsinfo;
+       int                     i_tableoid;
        int                     i_oid;
        int                     i_nspname;
-       int                     i_usename;
+       int                     i_rolname;
        int                     i_nspacl;
 
        /*
-        * Before 7.3, there are no real namespaces; create two dummy entries,
-        * one for user stuff and one for system stuff.
+        * 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].dobj.objType = DO_NAMESPACE;
+               nsinfo[0].dobj.catId.tableoid = 0;
+               nsinfo[0].dobj.catId.oid = 0;
+               AssignDumpId(&nsinfo[0].dobj);
+               nsinfo[0].dobj.name = strdup("public");
+               nsinfo[0].rolname = 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].dobj.objType = DO_NAMESPACE;
+               nsinfo[1].dobj.catId.tableoid = 0;
+               nsinfo[1].dobj.catId.oid = 1;
+               AssignDumpId(&nsinfo[1].dobj);
+               nsinfo[1].dobj.name = strdup("pg_catalog");
+               nsinfo[1].rolname = strdup("");
                nsinfo[1].nspacl = strdup("");
 
                selectDumpableNamespace(&nsinfo[1]);
@@ -1375,63 +1897,43 @@ getNamespaces(int *numNamespaces)
        selectSourceSchema("pg_catalog");
 
        /*
-        * we fetch all namespaces including system ones, so that every object
-        * we read in can be linked to a containing namespace.
+        * 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");
+       appendPQExpBuffer(query, "SELECT tableoid, oid, nspname, "
+                                         "(%s nspowner) as rolname, "
+                                         "nspacl FROM pg_namespace",
+                                         username_subquery);
 
        res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "query to obtain list of schemas failed: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        ntups = PQntuples(res);
 
        nsinfo = (NamespaceInfo *) malloc(ntups * sizeof(NamespaceInfo));
 
+       i_tableoid = PQfnumber(res, "tableoid");
        i_oid = PQfnumber(res, "oid");
        i_nspname = PQfnumber(res, "nspname");
-       i_usename = PQfnumber(res, "usename");
+       i_rolname = PQfnumber(res, "rolname");
        i_nspacl = PQfnumber(res, "nspacl");
 
        for (i = 0; i < ntups; i++)
        {
-               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].dobj.objType = DO_NAMESPACE;
+               nsinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               nsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&nsinfo[i].dobj);
+               nsinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_nspname));
+               nsinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
                nsinfo[i].nspacl = strdup(PQgetvalue(res, i, i_nspacl));
 
                /* Decide whether to dump this namespace */
                selectDumpableNamespace(&nsinfo[i]);
 
-               if (strlen(nsinfo[i].usename) == 0)
+               if (strlen(nsinfo[i].rolname) == 0)
                        write_msg(NULL, "WARNING: owner of schema \"%s\" appears to be invalid\n",
-                                         nsinfo[i].nspname);
-       }
-
-       /*
-        * If the user attempted to dump a specific namespace, check to ensure
-        * that the specified namespace actually exists.
-        */
-       if (selectSchemaName)
-       {
-               for (i = 0; i < ntups; i++)
-                       if (strcmp(nsinfo[i].nspname, selectSchemaName) == 0)
-                               break;
-
-               /* Didn't find a match */
-               if (i == ntups)
-               {
-                       write_msg(NULL, "specified schema \"%s\" does not exist\n",
-                                         selectSchemaName);
-                       exit_nicely();
-               }
+                                         nsinfo[i].dobj.name);
        }
 
        PQclear(res);
@@ -1452,7 +1954,7 @@ getNamespaces(int *numNamespaces)
  * a system object or not.     In 7.3 and later there is no guessing.
  */
 static NamespaceInfo *
-findNamespace(const char *nsoid, const char *objoid)
+findNamespace(Oid nsoid, Oid objoid)
 {
        int                     i;
 
@@ -1462,16 +1964,16 @@ findNamespace(const char *nsoid, const char *objoid)
                {
                        NamespaceInfo *nsinfo = &g_namespaces[i];
 
-                       if (strcmp(nsoid, nsinfo->oid) == 0)
+                       if (nsoid == nsinfo->dobj.catId.oid)
                                return nsinfo;
                }
-               write_msg(NULL, "schema with OID %s does not exist\n", nsoid);
+               write_msg(NULL, "schema with OID %u does not exist\n", nsoid);
                exit_nicely();
        }
        else
        {
                /* This code depends on the layout set up by getNamespaces. */
-               if (atooid(objoid) > g_last_builtin_oid)
+               if (objoid > g_last_builtin_oid)
                        i = 0;                          /* user object */
                else
                        i = 1;                          /* system object */
@@ -1487,6 +1989,9 @@ findNamespace(const char *nsoid, const char *objoid)
  * TypeInfo* structure
  *
  *     numTypes is set to the number of types read in
+ *
+ * NB: this must run after getFuncs() because we assume we can do
+ * findFuncByOid().
  */
 TypeInfo *
 getTypes(int *numTypes)
@@ -1496,10 +2001,14 @@ getTypes(int *numTypes)
        int                     i;
        PQExpBuffer query = createPQExpBuffer();
        TypeInfo   *tinfo;
+       ShellTypeInfo *stinfo;
+       int                     i_tableoid;
        int                     i_oid;
        int                     i_typname;
        int                     i_typnamespace;
-       int                     i_usename;
+       int                     i_rolname;
+       int                     i_typinput;
+       int                     i_typoutput;
        int                     i_typelem;
        int                     i_typrelid;
        int                     i_typrelkind;
@@ -1507,8 +2016,8 @@ getTypes(int *numTypes)
        int                     i_typisdefined;
 
        /*
-        * we include even the built-in types because those may be used as
-        * array elements by user-defined 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
         *
@@ -1520,43 +2029,60 @@ getTypes(int *numTypes)
 
        if (g_fout->remoteVersion >= 70300)
        {
-               appendPQExpBuffer(query, "SELECT pg_type.oid, typname, "
+               appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
                                                  "typnamespace, "
-                                                 "(select usename from pg_user where typowner = usesysid) as usename, "
-                                                 "typelem, typrelid, "
+                                                 "(%s typowner) as rolname, "
+                                                 "typinput::oid as typinput, "
+                                                 "typoutput::oid as typoutput, typelem, typrelid, "
+                                                 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
+                                                 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
+                                                 "typtype, typisdefined "
+                                                 "FROM pg_type",
+                                                 username_subquery);
+       }
+       else if (g_fout->remoteVersion >= 70100)
+       {
+               appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
+                                                 "0::oid as typnamespace, "
+                                                 "(%s typowner) as rolname, "
+                                                 "typinput::oid as typinput, "
+                                                 "typoutput::oid as typoutput, typelem, typrelid, "
                                                  "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
                                                  "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
                                                  "typtype, typisdefined "
-                                                 "FROM pg_type");
+                                                 "FROM pg_type",
+                                                 username_subquery);
        }
        else
        {
-               appendPQExpBuffer(query, "SELECT pg_type.oid, typname, "
+               appendPQExpBuffer(query, "SELECT "
+                "(SELECT oid FROM pg_class WHERE relname = 'pg_type') AS tableoid, "
+                                                 "oid, typname, "
                                                  "0::oid as typnamespace, "
-                                                 "(select usename from pg_user where typowner = usesysid) as usename, "
-                                                 "typelem, typrelid, "
+                                                 "(%s typowner) as rolname, "
+                                                 "typinput::oid as typinput, "
+                                                 "typoutput::oid as typoutput, typelem, typrelid, "
                                                  "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
                                                  "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
                                                  "typtype, typisdefined "
-                                                 "FROM pg_type");
+                                                 "FROM pg_type",
+                                                 username_subquery);
        }
 
        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();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        ntups = PQntuples(res);
 
        tinfo = (TypeInfo *) malloc(ntups * sizeof(TypeInfo));
 
+       i_tableoid = PQfnumber(res, "tableoid");
        i_oid = PQfnumber(res, "oid");
        i_typname = PQfnumber(res, "typname");
        i_typnamespace = PQfnumber(res, "typnamespace");
-       i_usename = PQfnumber(res, "usename");
+       i_rolname = PQfnumber(res, "rolname");
+       i_typinput = PQfnumber(res, "typinput");
+       i_typoutput = PQfnumber(res, "typoutput");
        i_typelem = PQfnumber(res, "typelem");
        i_typrelid = PQfnumber(res, "typrelid");
        i_typrelkind = PQfnumber(res, "typrelkind");
@@ -1565,21 +2091,35 @@ getTypes(int *numTypes)
 
        for (i = 0; i < ntups; i++)
        {
-               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].dobj.objType = DO_TYPE;
+               tinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               tinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&tinfo[i].dobj);
+               tinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_typname));
+               tinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_typnamespace)),
+                                                                                               tinfo[i].dobj.catId.oid);
+               tinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+               tinfo[i].typelem = atooid(PQgetvalue(res, i, i_typelem));
+               tinfo[i].typrelid = atooid(PQgetvalue(res, i, i_typrelid));
                tinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind);
                tinfo[i].typtype = *PQgetvalue(res, i, i_typtype);
+               tinfo[i].shellType = NULL;
+
+               /*
+                * If it's a table's rowtype, use special type code to facilitate
+                * sorting into the desired order.      (We don't want to consider it an
+                * ordinary type because that would bring the table up into the
+                * datatype part of the dump order.)
+                */
+               if (OidIsValid(tinfo[i].typrelid) &&
+                       tinfo[i].typrelkind != RELKIND_COMPOSITE_TYPE)
+                       tinfo[i].dobj.objType = DO_TABLE_TYPE;
 
                /*
                 * check for user-defined array types, omit system generated ones
                 */
-               if ((strcmp(tinfo[i].typelem, "0") != 0) &&
-                       tinfo[i].typname[0] != '_')
+               if (OidIsValid(tinfo[i].typelem) &&
+                       tinfo[i].dobj.name[0] != '_')
                        tinfo[i].isArray = true;
                else
                        tinfo[i].isArray = false;
@@ -1589,9 +2129,90 @@ getTypes(int *numTypes)
                else
                        tinfo[i].isDefined = false;
 
-               if (strlen(tinfo[i].usename) == 0 && tinfo[i].isDefined)
+               /* Decide whether we want to dump it */
+               selectDumpableType(&tinfo[i]);
+
+               /*
+                * If it's a domain, fetch info about its constraints, if any
+                */
+               tinfo[i].nDomChecks = 0;
+               tinfo[i].domChecks = NULL;
+               if (tinfo[i].dobj.dump && tinfo[i].typtype == 'd')
+                       getDomainConstraints(&(tinfo[i]));
+
+               /*
+                * If it's a base type, make a DumpableObject representing a shell
+                * definition of the type.  We will need to dump that ahead of the
+                * I/O functions for the type.
+                *
+                * Note: the shell type doesn't have a catId.  You might think it
+                * should copy the base type's catId, but then it might capture
+                * the pg_depend entries for the type, which we don't want.
+                */
+               if (tinfo[i].dobj.dump && tinfo[i].typtype == 'b')
+               {
+                       stinfo = (ShellTypeInfo *) malloc(sizeof(ShellTypeInfo));
+                       stinfo->dobj.objType = DO_SHELL_TYPE;
+                       stinfo->dobj.catId = nilCatalogId;
+                       AssignDumpId(&stinfo->dobj);
+                       stinfo->dobj.name = strdup(tinfo[i].dobj.name);
+                       stinfo->dobj.namespace = tinfo[i].dobj.namespace;
+                       stinfo->baseType = &(tinfo[i]);
+                       tinfo[i].shellType = stinfo;
+
+                       /*
+                        * Initially mark the shell type as not to be dumped.  We'll
+                        * only dump it if the I/O functions need to be dumped; this
+                        * is taken care of while sorting dependencies.
+                        */
+                       stinfo->dobj.dump = false;
+
+                       /*
+                        * However, if dumping from pre-7.3, there will be no dependency
+                        * info so we have to fake it here.  We only need to worry about
+                        * typinput and typoutput since the other functions only exist
+                        * post-7.3.
+                        */
+                       if (g_fout->remoteVersion < 70300)
+                       {
+                               Oid                     typinput;
+                               Oid                     typoutput;
+                               FuncInfo   *funcInfo;
+
+                               typinput = atooid(PQgetvalue(res, i, i_typinput));
+                               typoutput = atooid(PQgetvalue(res, i, i_typoutput));
+
+                               funcInfo = findFuncByOid(typinput);
+                               if (funcInfo && funcInfo->dobj.dump)
+                               {
+                                       /* base type depends on function */
+                                       addObjectDependency(&tinfo[i].dobj,
+                                                                               funcInfo->dobj.dumpId);
+                                       /* function depends on shell type */
+                                       addObjectDependency(&funcInfo->dobj,
+                                                                               stinfo->dobj.dumpId);
+                                       /* mark shell type as to be dumped */
+                                       stinfo->dobj.dump = true;
+                               }
+
+                               funcInfo = findFuncByOid(typoutput);
+                               if (funcInfo && funcInfo->dobj.dump)
+                               {
+                                       /* base type depends on function */
+                                       addObjectDependency(&tinfo[i].dobj,
+                                                                               funcInfo->dobj.dumpId);
+                                       /* function depends on shell type */
+                                       addObjectDependency(&funcInfo->dobj,
+                                                                               stinfo->dobj.dumpId);
+                                       /* mark shell type as to be dumped */
+                                       stinfo->dobj.dump = true;
+                               }
+                       }
+               }
+
+               if (strlen(tinfo[i].rolname) == 0 && tinfo[i].isDefined)
                        write_msg(NULL, "WARNING: owner of data type \"%s\" appears to be invalid\n",
-                                         tinfo[i].typname);
+                                         tinfo[i].dobj.name);
        }
 
        *numTypes = ntups;
@@ -1618,10 +2239,11 @@ getOperators(int *numOprs)
        int                     i;
        PQExpBuffer query = createPQExpBuffer();
        OprInfo    *oprinfo;
+       int                     i_tableoid;
        int                     i_oid;
        int                     i_oprname;
        int                     i_oprnamespace;
-       int                     i_usename;
+       int                     i_rolname;
        int                     i_oprcode;
 
        /*
@@ -1634,52 +2256,67 @@ getOperators(int *numOprs)
 
        if (g_fout->remoteVersion >= 70300)
        {
-               appendPQExpBuffer(query, "SELECT pg_operator.oid, oprname, "
+               appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, "
                                                  "oprnamespace, "
-                                                 "(select usename from pg_user where oprowner = usesysid) as usename, "
+                                                 "(%s oprowner) as rolname, "
                                                  "oprcode::oid as oprcode "
-                                                 "from pg_operator");
+                                                 "FROM pg_operator",
+                                                 username_subquery);
+       }
+       else if (g_fout->remoteVersion >= 70100)
+       {
+               appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, "
+                                                 "0::oid as oprnamespace, "
+                                                 "(%s oprowner) as rolname, "
+                                                 "oprcode::oid as oprcode "
+                                                 "FROM pg_operator",
+                                                 username_subquery);
        }
        else
        {
-               appendPQExpBuffer(query, "SELECT pg_operator.oid, oprname, "
+               appendPQExpBuffer(query, "SELECT "
+                                                 "(SELECT oid FROM pg_class WHERE relname = 'pg_operator') AS tableoid, "
+                                                 "oid, oprname, "
                                                  "0::oid as oprnamespace, "
-                                                 "(select usename from pg_user where oprowner = usesysid) as usename, "
+                                                 "(%s oprowner) as rolname, "
                                                  "oprcode::oid as oprcode "
-                                                 "from pg_operator");
+                                                 "FROM pg_operator",
+                                                 username_subquery);
        }
 
        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();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        ntups = PQntuples(res);
        *numOprs = ntups;
 
        oprinfo = (OprInfo *) malloc(ntups * sizeof(OprInfo));
 
+       i_tableoid = PQfnumber(res, "tableoid");
        i_oid = PQfnumber(res, "oid");
        i_oprname = PQfnumber(res, "oprname");
        i_oprnamespace = PQfnumber(res, "oprnamespace");
-       i_usename = PQfnumber(res, "usename");
+       i_rolname = PQfnumber(res, "rolname");
        i_oprcode = PQfnumber(res, "oprcode");
 
        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].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));
+               oprinfo[i].dobj.objType = DO_OPERATOR;
+               oprinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               oprinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&oprinfo[i].dobj);
+               oprinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_oprname));
+               oprinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_oprnamespace)),
+                                                                                                 oprinfo[i].dobj.catId.oid);
+               oprinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+               oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));
 
-               if (strlen(oprinfo[i].usename) == 0)
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(oprinfo[i].dobj));
+
+               if (strlen(oprinfo[i].rolname) == 0)
                        write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
-                                         oprinfo[i].oprname);
+                                         oprinfo[i].dobj.name);
        }
 
        PQclear(res);
@@ -1690,79 +2327,170 @@ getOperators(int *numOprs)
 }
 
 /*
- * getOpclasses:
- *       read all opclasses in the system catalogs and return them in the
- * OpclassInfo* structure
+ * getConversions:
+ *       read all conversions in the system catalogs and return them in the
+ * ConvInfo* structure
  *
- *     numOpclasses is set to the number of opclasses read in
+ *     numConversions is set to the number of conversions read in
  */
-OpclassInfo *
-getOpclasses(int *numOpclasses)
+ConvInfo *
+getConversions(int *numConversions)
 {
        PGresult   *res;
        int                     ntups;
        int                     i;
        PQExpBuffer query = createPQExpBuffer();
-       OpclassInfo *opcinfo;
+       ConvInfo   *convinfo;
+       int                     i_tableoid;
        int                     i_oid;
-       int                     i_opcname;
-       int                     i_opcnamespace;
-       int                     i_usename;
+       int                     i_conname;
+       int                     i_connamespace;
+       int                     i_rolname;
+
+       /* Conversions didn't exist pre-7.3 */
+       if (g_fout->remoteVersion < 70300)
+       {
+               *numConversions = 0;
+               return NULL;
+       }
 
        /*
-        * find all opclasses, including builtin opclasses; we filter out
-        * system-defined opclasses at dump-out time.
+        * find all conversions, including builtin conversions; we filter out
+        * system-defined conversions at dump-out time.
         */
 
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
 
-       if (g_fout->remoteVersion >= 70300)
-       {
-               appendPQExpBuffer(query, "SELECT pg_opclass.oid, opcname, "
-                                                 "opcnamespace, "
-                                                 "(select usename from pg_user where opcowner = usesysid) as usename "
-                                                 "from pg_opclass");
-       }
-       else
-       {
-               appendPQExpBuffer(query, "SELECT pg_opclass.oid, opcname, "
-                                                 "0::oid as opcnamespace, "
-                                                 "''::name as usename "
-                                                 "from pg_opclass");
-       }
+       appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
+                                         "connamespace, "
+                                         "(%s conowner) as rolname "
+                                         "FROM pg_conversion",
+                                         username_subquery);
 
        res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "query to obtain list of operator classes failed: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        ntups = PQntuples(res);
-       *numOpclasses = ntups;
+       *numConversions = ntups;
 
-       opcinfo = (OpclassInfo *) malloc(ntups * sizeof(OpclassInfo));
+       convinfo = (ConvInfo *) malloc(ntups * sizeof(ConvInfo));
 
+       i_tableoid = PQfnumber(res, "tableoid");
        i_oid = PQfnumber(res, "oid");
-       i_opcname = PQfnumber(res, "opcname");
-       i_opcnamespace = PQfnumber(res, "opcnamespace");
-       i_usename = PQfnumber(res, "usename");
+       i_conname = PQfnumber(res, "conname");
+       i_connamespace = PQfnumber(res, "connamespace");
+       i_rolname = PQfnumber(res, "rolname");
 
        for (i = 0; i < ntups; i++)
        {
-               opcinfo[i].oid = strdup(PQgetvalue(res, i, i_oid));
-               opcinfo[i].opcname = strdup(PQgetvalue(res, i, i_opcname));
-               opcinfo[i].opcnamespace = findNamespace(PQgetvalue(res, i, i_opcnamespace),
-                                                                                               opcinfo[i].oid);
-               opcinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+               convinfo[i].dobj.objType = DO_CONVERSION;
+               convinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               convinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&convinfo[i].dobj);
+               convinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_conname));
+               convinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_connamespace)),
+                                                                                                convinfo[i].dobj.catId.oid);
+               convinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(convinfo[i].dobj));
+       }
+
+       PQclear(res);
+
+       destroyPQExpBuffer(query);
+
+       return convinfo;
+}
+
+/*
+ * getOpclasses:
+ *       read all opclasses in the system catalogs and return them in the
+ * OpclassInfo* structure
+ *
+ *     numOpclasses is set to the number of opclasses read in
+ */
+OpclassInfo *
+getOpclasses(int *numOpclasses)
+{
+       PGresult   *res;
+       int                     ntups;
+       int                     i;
+       PQExpBuffer query = createPQExpBuffer();
+       OpclassInfo *opcinfo;
+       int                     i_tableoid;
+       int                     i_oid;
+       int                     i_opcname;
+       int                     i_opcnamespace;
+       int                     i_rolname;
+
+       /*
+        * find all opclasses, including builtin opclasses; we filter out
+        * system-defined opclasses at dump-out time.
+        */
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       if (g_fout->remoteVersion >= 70300)
+       {
+               appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
+                                                 "opcnamespace, "
+                                                 "(%s opcowner) as rolname "
+                                                 "FROM pg_opclass",
+                                                 username_subquery);
+       }
+       else if (g_fout->remoteVersion >= 70100)
+       {
+               appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
+                                                 "0::oid as opcnamespace, "
+                                                 "''::name as rolname "
+                                                 "FROM pg_opclass");
+       }
+       else
+       {
+               appendPQExpBuffer(query, "SELECT "
+                                                 "(SELECT oid FROM pg_class WHERE relname = 'pg_opclass') AS tableoid, "
+                                                 "oid, opcname, "
+                                                 "0::oid as opcnamespace, "
+                                                 "''::name as rolname "
+                                                 "FROM pg_opclass");
+       }
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       ntups = PQntuples(res);
+       *numOpclasses = ntups;
+
+       opcinfo = (OpclassInfo *) malloc(ntups * sizeof(OpclassInfo));
+
+       i_tableoid = PQfnumber(res, "tableoid");
+       i_oid = PQfnumber(res, "oid");
+       i_opcname = PQfnumber(res, "opcname");
+       i_opcnamespace = PQfnumber(res, "opcnamespace");
+       i_rolname = PQfnumber(res, "rolname");
+
+       for (i = 0; i < ntups; i++)
+       {
+               opcinfo[i].dobj.objType = DO_OPCLASS;
+               opcinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               opcinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&opcinfo[i].dobj);
+               opcinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_opcname));
+               opcinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_opcnamespace)),
+                                                                                                 opcinfo[i].dobj.catId.oid);
+               opcinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(opcinfo[i].dobj));
 
                if (g_fout->remoteVersion >= 70300)
                {
-                       if (strlen(opcinfo[i].usename) == 0)
+                       if (strlen(opcinfo[i].rolname) == 0)
                                write_msg(NULL, "WARNING: owner of operator class \"%s\" appears to be invalid\n",
-                                                 opcinfo[i].opcname);
+                                                 opcinfo[i].dobj.name);
                }
        }
 
@@ -1788,12 +2516,13 @@ getAggregates(int *numAggs)
        int                     i;
        PQExpBuffer query = createPQExpBuffer();
        AggInfo    *agginfo;
-
+       int                     i_tableoid;
        int                     i_oid;
        int                     i_aggname;
        int                     i_aggnamespace;
-       int                     i_aggbasetype;
-       int                     i_usename;
+       int                     i_pronargs;
+       int                     i_proargtypes;
+       int                     i_rolname;
        int                     i_aggacl;
 
        /* Make sure we are in proper schema */
@@ -1801,65 +2530,111 @@ getAggregates(int *numAggs)
 
        /* find all user-defined aggregates */
 
-       if (g_fout->remoteVersion >= 70300)
+       if (g_fout->remoteVersion >= 80200)
+       {
+               appendPQExpBuffer(query, "SELECT tableoid, oid, proname as aggname, "
+                                                 "pronamespace as aggnamespace, "
+                                                 "pronargs, proargtypes, "
+                                                 "(%s proowner) as rolname, "
+                                                 "proacl as aggacl "
+                                                 "FROM pg_proc "
+                                                 "WHERE proisagg "
+                                                 "AND pronamespace != "
+                          "(select oid from pg_namespace where nspname = 'pg_catalog')",
+                                                 username_subquery);
+       }
+       else if (g_fout->remoteVersion >= 70300)
        {
-               appendPQExpBuffer(query, "SELECT pg_proc.oid, proname as aggname, "
+               appendPQExpBuffer(query, "SELECT tableoid, oid, proname as aggname, "
                                                  "pronamespace as aggnamespace, "
-                                                 "proargtypes[0] as aggbasetype, "
-                                                 "(select usename from pg_user where proowner = usesysid) as usename, "
+                                                 "CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END as pronargs, "
+                                                 "proargtypes, "
+                                                 "(%s proowner) as rolname, "
                                                  "proacl as aggacl "
                                                  "FROM pg_proc "
                                                  "WHERE proisagg "
                                                  "AND pronamespace != "
-                 "(select oid from pg_namespace where nspname = 'pg_catalog')");
+                          "(select oid from pg_namespace where nspname = 'pg_catalog')",
+                                                 username_subquery);
+       }
+       else if (g_fout->remoteVersion >= 70100)
+       {
+               appendPQExpBuffer(query, "SELECT tableoid, oid, aggname, "
+                                                 "0::oid as aggnamespace, "
+                                                 "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END as pronargs, "
+                                                 "aggbasetype as proargtypes, "
+                                                 "(%s aggowner) as rolname, "
+                                                 "'{=X}' as aggacl "
+                                                 "FROM pg_aggregate "
+                                                 "where oid > '%u'::oid",
+                                                 username_subquery,
+                                                 g_last_builtin_oid);
        }
        else
        {
-               appendPQExpBuffer(query, "SELECT pg_aggregate.oid, aggname, "
+               appendPQExpBuffer(query, "SELECT "
+                                                 "(SELECT oid FROM pg_class WHERE relname = 'pg_aggregate') AS tableoid, "
+                                                 "oid, aggname, "
                                                  "0::oid as aggnamespace, "
-                                                 "aggbasetype, "
-                                                 "(select usename from pg_user where aggowner = usesysid) as usename, "
+                                                 "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END as pronargs, "
+                                                 "aggbasetype as proargtypes, "
+                                                 "(%s aggowner) as rolname, "
                                                  "'{=X}' as aggacl "
-                                                 "from pg_aggregate "
+                                                 "FROM pg_aggregate "
                                                  "where oid > '%u'::oid",
+                                                 username_subquery,
                                                  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 aggregate functions failed: %s",
-                                 PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        ntups = PQntuples(res);
        *numAggs = ntups;
 
        agginfo = (AggInfo *) malloc(ntups * sizeof(AggInfo));
 
+       i_tableoid = PQfnumber(res, "tableoid");
        i_oid = PQfnumber(res, "oid");
        i_aggname = PQfnumber(res, "aggname");
        i_aggnamespace = PQfnumber(res, "aggnamespace");
-       i_aggbasetype = PQfnumber(res, "aggbasetype");
-       i_usename = PQfnumber(res, "usename");
+       i_pronargs = PQfnumber(res, "pronargs");
+       i_proargtypes = PQfnumber(res, "proargtypes");
+       i_rolname = PQfnumber(res, "rolname");
        i_aggacl = PQfnumber(res, "aggacl");
 
        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].aggnamespace = findNamespace(PQgetvalue(res, i, i_aggnamespace),
-                                                                                               agginfo[i].oid);
-               agginfo[i].aggbasetype = strdup(PQgetvalue(res, i, i_aggbasetype));
-               agginfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
-               if (strlen(agginfo[i].usename) == 0)
+               agginfo[i].aggfn.dobj.objType = DO_AGG;
+               agginfo[i].aggfn.dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               agginfo[i].aggfn.dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&agginfo[i].aggfn.dobj);
+               agginfo[i].aggfn.dobj.name = strdup(PQgetvalue(res, i, i_aggname));
+               agginfo[i].aggfn.dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_aggnamespace)),
+                                                                                       agginfo[i].aggfn.dobj.catId.oid);
+               agginfo[i].aggfn.rolname = strdup(PQgetvalue(res, i, i_rolname));
+               if (strlen(agginfo[i].aggfn.rolname) == 0)
                        write_msg(NULL, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n",
-                                         agginfo[i].aggname);
-               agginfo[i].aggacl = strdup(PQgetvalue(res, i, i_aggacl));
-               agginfo[i].anybasetype = false; /* computed when it's dumped */
-               agginfo[i].fmtbasetype = NULL;  /* computed when it's dumped */
+                                         agginfo[i].aggfn.dobj.name);
+               agginfo[i].aggfn.lang = InvalidOid;             /* not currently interesting */
+               agginfo[i].aggfn.prorettype = InvalidOid;               /* not saved */
+               agginfo[i].aggfn.proacl = strdup(PQgetvalue(res, i, i_aggacl));
+               agginfo[i].aggfn.nargs = atoi(PQgetvalue(res, i, i_pronargs));
+               if (agginfo[i].aggfn.nargs == 0)
+                       agginfo[i].aggfn.argtypes = NULL;
+               else
+               {
+                       agginfo[i].aggfn.argtypes = (Oid *) malloc(agginfo[i].aggfn.nargs * sizeof(Oid));
+                       if (g_fout->remoteVersion >= 70300)
+                               parseOidArray(PQgetvalue(res, i, i_proargtypes),
+                                                         agginfo[i].aggfn.argtypes,
+                                                         agginfo[i].aggfn.nargs);
+                       else                            /* it's just aggbasetype */
+                               agginfo[i].aggfn.argtypes[0] = atooid(PQgetvalue(res, i, i_proargtypes));
+               }
+
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(agginfo[i].aggfn.dobj));
        }
 
        PQclear(res);
@@ -1884,11 +2659,11 @@ getFuncs(int *numFuncs)
        int                     i;
        PQExpBuffer query = createPQExpBuffer();
        FuncInfo   *finfo;
-
+       int                     i_tableoid;
        int                     i_oid;
        int                     i_proname;
        int                     i_pronamespace;
-       int                     i_usename;
+       int                     i_rolname;
        int                     i_prolang;
        int                     i_pronargs;
        int                     i_proargtypes;
@@ -1903,49 +2678,61 @@ getFuncs(int *numFuncs)
        if (g_fout->remoteVersion >= 70300)
        {
                appendPQExpBuffer(query,
-                                                 "SELECT pg_proc.oid, proname, prolang, "
+                                                 "SELECT tableoid, oid, proname, prolang, "
                                                  "pronargs, proargtypes, prorettype, proacl, "
                                                  "pronamespace, "
-                                                 "(select usename from pg_user where proowner = usesysid) as usename "
+                                                 "(%s proowner) as rolname "
                                                  "FROM pg_proc "
                                                  "WHERE NOT proisagg "
                                                  "AND pronamespace != "
-                 "(select oid from pg_namespace where nspname = 'pg_catalog')");
+                                                 "(select oid from pg_namespace"
+                                                 " where nspname = 'pg_catalog')",
+                                                 username_subquery);
+       }
+       else if (g_fout->remoteVersion >= 70100)
+       {
+               appendPQExpBuffer(query,
+                                                 "SELECT tableoid, oid, proname, prolang, "
+                                                 "pronargs, proargtypes, prorettype, "
+                                                 "'{=X}' as proacl, "
+                                                 "0::oid as pronamespace, "
+                                                 "(%s proowner) as rolname "
+                                                 "FROM pg_proc "
+                                                 "where pg_proc.oid > '%u'::oid",
+                                                 username_subquery,
+                                                 g_last_builtin_oid);
        }
        else
        {
                appendPQExpBuffer(query,
-                                                 "SELECT pg_proc.oid, proname, prolang, "
+                                                 "SELECT "
+                                                 "(SELECT oid FROM pg_class "
+                                                 " WHERE relname = 'pg_proc') AS tableoid, "
+                                                 "oid, proname, prolang, "
                                                  "pronargs, proargtypes, prorettype, "
                                                  "'{=X}' as proacl, "
                                                  "0::oid as pronamespace, "
-                                                 "(select usename from pg_user where proowner = usesysid) as usename "
+                                                 "(%s proowner) as rolname "
                                                  "FROM pg_proc "
                                                  "where pg_proc.oid > '%u'::oid",
+                                                 username_subquery,
                                                  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 functions failed: %s",
-                                 PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        ntups = PQntuples(res);
 
        *numFuncs = ntups;
 
-       finfo = (FuncInfo *) malloc(ntups * sizeof(FuncInfo));
-
-       memset((char *) finfo, 0, ntups * sizeof(FuncInfo));
+       finfo = (FuncInfo *) calloc(ntups, sizeof(FuncInfo));
 
+       i_tableoid = PQfnumber(res, "tableoid");
        i_oid = PQfnumber(res, "oid");
        i_proname = PQfnumber(res, "proname");
        i_pronamespace = PQfnumber(res, "pronamespace");
-       i_usename = PQfnumber(res, "usename");
+       i_rolname = PQfnumber(res, "rolname");
        i_prolang = PQfnumber(res, "prolang");
        i_pronargs = PQfnumber(res, "pronargs");
        i_proargtypes = PQfnumber(res, "proargtypes");
@@ -1954,30 +2741,35 @@ getFuncs(int *numFuncs)
 
        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].dobj.objType = DO_FUNC;
+               finfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               finfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&finfo[i].dobj);
+               finfo[i].dobj.name = strdup(PQgetvalue(res, i, i_proname));
+               finfo[i].dobj.namespace =
+                       findNamespace(atooid(PQgetvalue(res, i, i_pronamespace)),
+                                                 finfo[i].dobj.catId.oid);
+               finfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
                finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
-               finfo[i].prorettype = strdup(PQgetvalue(res, i, i_prorettype));
+               finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
                finfo[i].proacl = strdup(PQgetvalue(res, i, i_proacl));
                finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
                if (finfo[i].nargs == 0)
                        finfo[i].argtypes = NULL;
                else
                {
-                       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].argtypes = (Oid *) malloc(finfo[i].nargs * sizeof(Oid));
+                       parseOidArray(PQgetvalue(res, i, i_proargtypes),
+                                                 finfo[i].argtypes, finfo[i].nargs);
                }
 
-               finfo[i].dumped = false;
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(finfo[i].dobj));
 
-               if (strlen(finfo[i].usename) == 0)
-                       write_msg(NULL, "WARNING: owner of function \"%s\" appears to be invalid\n",
-                                         finfo[i].proname);
+               if (strlen(finfo[i].rolname) == 0)
+                       write_msg(NULL,
+                                "WARNING: owner of function \"%s\" appears to be invalid\n",
+                                         finfo[i].dobj.name);
        }
 
        PQclear(res);
@@ -2004,13 +2796,13 @@ getTables(int *numTables)
        PQExpBuffer delqry = createPQExpBuffer();
        PQExpBuffer lockquery = createPQExpBuffer();
        TableInfo  *tblinfo;
-
+       int                     i_reltableoid;
        int                     i_reloid;
        int                     i_relname;
        int                     i_relnamespace;
        int                     i_relkind;
        int                     i_relacl;
-       int                     i_usename;
+       int                     i_rolname;
        int                     i_relchecks;
        int                     i_reltriggers;
        int                     i_relhasindex;
@@ -2018,6 +2810,8 @@ getTables(int *numTables)
        int                     i_relhasoids;
        int                     i_owning_tab;
        int                     i_owning_col;
+       int                     i_reltablespace;
+       int                     i_reloptions;
 
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
@@ -2028,131 +2822,202 @@ getTables(int *numTables)
         * 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).
+        * We ignore tables that are not type 'r' (ordinary relation), 'S'
+        * (sequence), 'v' (view), or 'c' (composite type).
+        *
+        * Composite-type table entries won't be dumped as such, but we have to
+        * make a DumpableObject for them so that we can track dependencies of the
+        * composite type (pg_depend entries for columns of the composite type
+        * link to the pg_class entry not the pg_type entry).
         *
         * 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.      We must fetch all tables in this phase because
-        * otherwise we cannot correctly identify inherited columns, serial
-        * columns, etc.
+        * information about each table, basically just enough to decide if it is
+        * interesting. We must fetch all tables in this phase because otherwise
+        * we cannot correctly identify inherited columns, owned sequences, etc.
         */
 
-       if (g_fout->remoteVersion >= 70300)
+       if (g_fout->remoteVersion >= 80200)
        {
                /*
                 * Left join to pick up dependency info linking sequences to their
-                * serial column, if any
+                * owning column, if any (note this dependency is AUTO as of 8.2)
                 */
                appendPQExpBuffer(query,
-                                                 "SELECT c.oid, relname, relacl, relkind, "
-                                                 "relnamespace, "
-                                                 "(select usename from pg_user where relowner = usesysid) as usename, "
+                                                 "SELECT c.tableoid, c.oid, relname, "
+                                                 "relacl, relkind, relnamespace, "
+                                                 "(%s relowner) as rolname, "
                                                  "relchecks, reltriggers, "
                                                  "relhasindex, relhasrules, relhasoids, "
                                                  "d.refobjid as owning_tab, "
-                                                 "d.refobjsubid as owning_col "
+                                                 "d.refobjsubid as owning_col, "
+                                                 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
+                                                 "array_to_string(c.reloptions, ', ') as reloptions "
                                                  "from pg_class c "
                                                  "left join pg_depend d on "
                                                  "(c.relkind = '%c' and "
-                                               "d.classid = c.tableoid and d.objid = c.oid and "
+                                                 "d.classid = c.tableoid and d.objid = c.oid and "
                                                  "d.objsubid = 0 and "
-                                               "d.refclassid = c.tableoid and d.deptype = 'i') "
-                                                 "where relkind in ('%c', '%c', '%c') "
+                                                 "d.refclassid = c.tableoid and d.deptype = 'a') "
+                                                 "where relkind in ('%c', '%c', '%c', '%c') "
+                                                 "order by c.oid",
+                                                 username_subquery,
+                                                 RELKIND_SEQUENCE,
+                                                 RELKIND_RELATION, RELKIND_SEQUENCE,
+                                                 RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
+       }
+       else if (g_fout->remoteVersion >= 80000)
+       {
+               /*
+                * Left join to pick up dependency info linking sequences to their
+                * owning column, if any
+                */
+               appendPQExpBuffer(query,
+                                                 "SELECT c.tableoid, c.oid, relname, "
+                                                 "relacl, relkind, relnamespace, "
+                                                 "(%s relowner) as rolname, "
+                                                 "relchecks, reltriggers, "
+                                                 "relhasindex, relhasrules, relhasoids, "
+                                                 "d.refobjid as owning_tab, "
+                                                 "d.refobjsubid as owning_col, "
+                                                 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
+                                                 "NULL as reloptions "
+                                                 "from pg_class c "
+                                                 "left join pg_depend d on "
+                                                 "(c.relkind = '%c' and "
+                                                 "d.classid = c.tableoid and d.objid = c.oid and "
+                                                 "d.objsubid = 0 and "
+                                                 "d.refclassid = c.tableoid and d.deptype = 'i') "
+                                                 "where relkind in ('%c', '%c', '%c', '%c') "
+                                                 "order by c.oid",
+                                                 username_subquery,
+                                                 RELKIND_SEQUENCE,
+                                                 RELKIND_RELATION, RELKIND_SEQUENCE,
+                                                 RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
+       }
+       else if (g_fout->remoteVersion >= 70300)
+       {
+               /*
+                * Left join to pick up dependency info linking sequences to their
+                * owning column, if any
+                */
+               appendPQExpBuffer(query,
+                                                 "SELECT c.tableoid, c.oid, relname, "
+                                                 "relacl, relkind, relnamespace, "
+                                                 "(%s relowner) as rolname, "
+                                                 "relchecks, reltriggers, "
+                                                 "relhasindex, relhasrules, relhasoids, "
+                                                 "d.refobjid as owning_tab, "
+                                                 "d.refobjsubid as owning_col, "
+                                                 "NULL as reltablespace, "
+                                                 "NULL as reloptions "
+                                                 "from pg_class c "
+                                                 "left join pg_depend d on "
+                                                 "(c.relkind = '%c' and "
+                                                 "d.classid = c.tableoid and d.objid = c.oid and "
+                                                 "d.objsubid = 0 and "
+                                                 "d.refclassid = c.tableoid and d.deptype = 'i') "
+                                                 "where relkind in ('%c', '%c', '%c', '%c') "
                                                  "order by c.oid",
+                                                 username_subquery,
                                                  RELKIND_SEQUENCE,
-                                          RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
+                                                 RELKIND_RELATION, RELKIND_SEQUENCE,
+                                                 RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
        }
        else if (g_fout->remoteVersion >= 70200)
        {
                appendPQExpBuffer(query,
-                                               "SELECT pg_class.oid, relname, relacl, relkind, "
+                                                 "SELECT tableoid, oid, relname, relacl, relkind, "
                                                  "0::oid as relnamespace, "
-                                                 "(select usename from pg_user where relowner = usesysid) as usename, "
+                                                 "(%s relowner) as rolname, "
                                                  "relchecks, reltriggers, "
                                                  "relhasindex, relhasrules, relhasoids, "
                                                  "NULL::oid as owning_tab, "
-                                                 "NULL::int4 as owning_col "
+                                                 "NULL::int4 as owning_col, "
+                                                 "NULL as reltablespace, "
+                                                 "NULL as reloptions "
                                                  "from pg_class "
                                                  "where relkind in ('%c', '%c', '%c') "
                                                  "order by oid",
-                                          RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
+                                                 username_subquery,
+                                                 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, "
+                                                 "SELECT tableoid, oid, relname, relacl, relkind, "
                                                  "0::oid as relnamespace, "
-                                                 "(select usename from pg_user where relowner = usesysid) as usename, "
+                                                 "(%s relowner) as rolname, "
                                                  "relchecks, reltriggers, "
                                                  "relhasindex, relhasrules, "
                                                  "'t'::bool as relhasoids, "
                                                  "NULL::oid as owning_tab, "
-                                                 "NULL::int4 as owning_col "
+                                                 "NULL::int4 as owning_col, "
+                                                 "NULL as reltablespace, "
+                                                 "NULL as reloptions "
                                                  "from pg_class "
                                                  "where relkind in ('%c', '%c', '%c') "
                                                  "order by oid",
-                                          RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
+                                                 username_subquery,
+                                                 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.
+                * 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, "
+                                                 "SELECT "
+               "(SELECT oid FROM pg_class WHERE relname = 'pg_class') AS tableoid, "
+                                                 "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') "
+                                         "  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, "
+                                                 "(%s relowner) as rolname, "
                                                  "relchecks, reltriggers, "
                                                  "relhasindex, relhasrules, "
                                                  "'t'::bool as relhasoids, "
                                                  "NULL::oid as owning_tab, "
-                                                 "NULL::int4 as owning_col "
+                                                 "NULL::int4 as owning_col, "
+                                                 "NULL as reltablespace, "
+                                                 "NULL as reloptions "
                                                  "from pg_class c "
                                                  "where relkind in ('%c', '%c') "
                                                  "order by oid",
                                                  RELKIND_VIEW,
+                                                 username_subquery,
                                                  RELKIND_RELATION, RELKIND_SEQUENCE);
        }
 
        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();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        ntups = PQntuples(res);
 
        *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.
+        * 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.
+        * 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));
+       tblinfo = (TableInfo *) calloc(ntups, sizeof(TableInfo));
 
+       i_reltableoid = PQfnumber(res, "tableoid");
        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_rolname = PQfnumber(res, "rolname");
        i_relchecks = PQfnumber(res, "relchecks");
        i_reltriggers = PQfnumber(res, "reltriggers");
        i_relhasindex = PQfnumber(res, "relhasindex");
@@ -2160,14 +3025,19 @@ getTables(int *numTables)
        i_relhasoids = PQfnumber(res, "relhasoids");
        i_owning_tab = PQfnumber(res, "owning_tab");
        i_owning_col = PQfnumber(res, "owning_col");
+       i_reltablespace = PQfnumber(res, "reltablespace");
+       i_reloptions = PQfnumber(res, "reloptions");
 
        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].dobj.objType = DO_TABLE;
+               tblinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_reltableoid));
+               tblinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_reloid));
+               AssignDumpId(&tblinfo[i].dobj);
+               tblinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_relname));
+               tblinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_relnamespace)),
+                                                                                                 tblinfo[i].dobj.catId.oid);
+               tblinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
                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);
@@ -2177,86 +3047,86 @@ getTables(int *numTables)
                tblinfo[i].ntrig = atoi(PQgetvalue(res, i, i_reltriggers));
                if (PQgetisnull(res, i, i_owning_tab))
                {
-                       tblinfo[i].owning_tab = NULL;
+                       tblinfo[i].owning_tab = InvalidOid;
                        tblinfo[i].owning_col = 0;
                }
                else
                {
-                       tblinfo[i].owning_tab = strdup(PQgetvalue(res, i, i_owning_tab));
+                       tblinfo[i].owning_tab = atooid(PQgetvalue(res, i, i_owning_tab));
                        tblinfo[i].owning_col = atoi(PQgetvalue(res, i, i_owning_col));
                }
+               tblinfo[i].reltablespace = strdup(PQgetvalue(res, i, i_reltablespace));
+               tblinfo[i].reloptions = strdup(PQgetvalue(res, i, i_reloptions));
 
                /* other fields were zeroed above */
 
                /*
-                * Decide whether we want to dump this table.  Sequences owned by
-                * serial columns are never dumpable on their own; we will
-                * transpose their owning table's dump flag to them below.
+                * Decide whether we want to dump this table.
                 */
-               if (tblinfo[i].owning_tab == NULL)
-                       selectDumpableTable(&tblinfo[i]);
+               if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
+                       tblinfo[i].dobj.dump = false;
                else
-                       tblinfo[i].dump = false;
-               tblinfo[i].interesting = tblinfo[i].dump;
+                       selectDumpableTable(&tblinfo[i]);
+               tblinfo[i].interesting = tblinfo[i].dobj.dump;
 
                /*
-                * Read-lock target tables to make sure they aren't DROPPED or
-                * altered in schema before we get around to dumping them.
+                * 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
+                * 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)
+               if (tblinfo[i].dobj.dump && tblinfo[i].relkind == RELKIND_RELATION)
                {
-                       PGresult   *lres;
-
                        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(lres);
+                                                fmtQualifiedId(tblinfo[i].dobj.namespace->dobj.name,
+                                                                               tblinfo[i].dobj.name));
+                       do_sql_command(g_conn, lockquery->data);
                }
 
                /* Emit notice if join for owner failed */
-               if (strlen(tblinfo[i].usename) == 0)
+               if (strlen(tblinfo[i].rolname) == 0)
                        write_msg(NULL, "WARNING: owner of table \"%s\" appears to be invalid\n",
-                                         tblinfo[i].relname);
+                                         tblinfo[i].dobj.name);
        }
 
+       PQclear(res);
+
        /*
-        * If the user is attempting to dump a specific table, check to ensure
-        * that the specified table actually exists (and is a table or a view,
-        * not a sequence).
+        * Force sequences that are "owned" by table columns to be dumped
+        * whenever their owning table is being dumped.
         */
-       if (selectTableName)
+       for (i = 0; i < ntups; i++)
        {
-               for (i = 0; i < ntups; i++)
-                       if (strcmp(tblinfo[i].relname, selectTableName) == 0 &&
-                               tblinfo[i].relkind != 'S')
-                               break;
+               TableInfo  *seqinfo = &tblinfo[i];
+               int             j;
 
-               /* Didn't find a match */
-               if (i == ntups)
+               if (!OidIsValid(seqinfo->owning_tab))
+                       continue;                       /* not an owned sequence */
+               if (seqinfo->dobj.dump)
+                       continue;                       /* no need to search */
+
+               /* can't use findTableByOid yet, unfortunately */
+               for (j = 0; j < ntups; j++)
                {
-                       write_msg(NULL, "specified table \"%s\" does not exist\n",
-                                         selectTableName);
-                       exit_nicely();
+                       if (tblinfo[j].dobj.catId.oid == seqinfo->owning_tab)
+                       {
+                               if (tblinfo[j].dobj.dump)
+                               {
+                                       seqinfo->interesting = true;
+                                       seqinfo->dobj.dump = true;
+                               }
+                               break;
+                       }
                }
        }
 
-       PQclear(res);
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(delqry);
        destroyPQExpBuffer(lockquery);
@@ -2291,13 +3161,7 @@ getInherits(int *numInherits)
        appendPQExpBuffer(query, "SELECT inhrelid, inhparent from pg_inherits");
 
        res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "query to obtain inheritance relationships failed: %s",
-                                 PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        ntups = PQntuples(res);
 
@@ -2310,8 +3174,8 @@ getInherits(int *numInherits)
 
        for (i = 0; i < ntups; i++)
        {
-               inhinfo[i].inhrelid = strdup(PQgetvalue(res, i, i_inhrelid));
-               inhinfo[i].inhparent = strdup(PQgetvalue(res, i, i_inhparent));
+               inhinfo[i].inhrelid = atooid(PQgetvalue(res, i, i_inhrelid));
+               inhinfo[i].inhparent = atooid(PQgetvalue(res, i, i_inhparent));
        }
 
        PQclear(res);
@@ -2322,121 +3186,1102 @@ getInherits(int *numInherits)
 }
 
 /*
- * getTableAttrs -
- *       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
- * types
+ * getIndexes
+ *       get information about every index on a dumpable table
  *
- *     modifies tblinfo
+ * Note: index data is not returned directly to the caller, but it
+ * does get entered into the DumpableObject tables.
  */
 void
-getTableAttrs(TableInfo *tblinfo, int numTables)
+getIndexes(TableInfo tblinfo[], int numTables)
 {
        int                     i,
-                               j,
-                               k;
-       PQExpBuffer q = createPQExpBuffer();
-       int                     i_attnum;
-       int                     i_attname;
-       int                     i_atttypname;
-       int                     i_atttypmod;
-       int                     i_attstattarget;
-       int                     i_attstorage;
-       int                     i_typstorage;
-       int                     i_attnotnull;
-       int                     i_atthasdef;
-       int                     i_attisdropped;
-       int                     i_attislocal;
+                               j;
+       PQExpBuffer query = createPQExpBuffer();
        PGresult   *res;
+       IndxInfo   *indxinfo;
+       ConstraintInfo *constrinfo;
+       int                     i_tableoid,
+                               i_oid,
+                               i_indexname,
+                               i_indexdef,
+                               i_indnkeys,
+                               i_indkey,
+                               i_indisclustered,
+                               i_contype,
+                               i_conname,
+                               i_contableoid,
+                               i_conoid,
+                               i_tablespace,
+                               i_options;
        int                     ntups;
-       bool            hasdefaults;
 
        for (i = 0; i < numTables; i++)
        {
                TableInfo  *tbinfo = &tblinfo[i];
 
-               /* Don't bother to collect info for sequences */
-               if (tbinfo->relkind == RELKIND_SEQUENCE)
+               /* Only plain tables have indexes */
+               if (tbinfo->relkind != RELKIND_RELATION || !tbinfo->hasindex)
                        continue;
 
-               /* Don't bother with uninteresting tables, either */
-               if (!tbinfo->interesting)
+               /* Ignore indexes of tables not to be dumped */
+               if (!tbinfo->dobj.dump)
                        continue;
 
-               /*
-                * Make sure we are in proper schema for this table; this allows
-                * correct retrieval of formatted type names and default exprs
-                */
-               selectSourceSchema(tbinfo->relnamespace->nspname);
+               if (g_verbose)
+                       write_msg(NULL, "reading indexes for table \"%s\"\n",
+                                         tbinfo->dobj.name);
 
-               /* find all the user attributes and their types */
+               /* Make sure we are in proper schema so indexdef is right */
+               selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
 
                /*
-                * we must read the attribute names in attribute number order!
-                * because we will use the attnum to index into the attnames array
-                * 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.
+                * The point of the messy-looking outer join is to find a constraint
+                * that is related by an internal dependency link to the index. If we
+                * find one, create a CONSTRAINT entry linked to the INDEX entry.  We
+                * assume an index won't have more than one internal dependency.
                 */
-               if (g_verbose)
-                       write_msg(NULL, "finding the columns and types of table \"%s\"\n",
-                                         tbinfo->relname);
-
-               resetPQExpBuffer(q);
-
-               if (g_fout->remoteVersion >= 70300)
-               {
-                       /* need left join here to not fail on dropped columns ... */
-                       appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, a.attstattarget, a.attstorage, t.typstorage, "
-                         "a.attnotnull, a.atthasdef, a.attisdropped, a.attislocal, "
-                          "pg_catalog.format_type(t.oid,a.atttypmod) as atttypname "
-                                                         "from pg_catalog.pg_attribute a left join pg_catalog.pg_type t "
-                                                         "on a.atttypid = t.oid "
-                                                         "where a.attrelid = '%s'::pg_catalog.oid "
-                                                         "and a.attnum > 0::pg_catalog.int2 "
-                                                         "order by a.attrelid, a.attnum",
-                                                         tbinfo->oid);
-               }
-               else if (g_fout->remoteVersion >= 70100)
+               resetPQExpBuffer(query);
+               if (g_fout->remoteVersion >= 80200)
                {
-                       /*
-                        * attstattarget doesn't exist in 7.1.  It does exist in 7.2,
-                        * but we don't dump it because we can't tell whether it's
-                        * been explicitly set or was just a default.
-                        */
-                       appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, -1 as attstattarget, a.attstorage, t.typstorage, "
-                                                         "a.attnotnull, a.atthasdef, false as attisdropped, null as attislocal, "
-                                                 "format_type(t.oid,a.atttypmod) as atttypname "
-                                                         "from pg_attribute a left join pg_type t "
-                                                         "on a.atttypid = t.oid "
-                                                         "where a.attrelid = '%s'::oid "
-                                                         "and a.attnum > 0::int2 "
-                                                         "order by a.attrelid, a.attnum",
-                                                         tbinfo->oid);
+                       appendPQExpBuffer(query,
+                                                         "SELECT t.tableoid, t.oid, "
+                                                         "t.relname as indexname, "
+                                        "pg_catalog.pg_get_indexdef(i.indexrelid) as indexdef, "
+                                                         "t.relnatts as indnkeys, "
+                                                         "i.indkey, i.indisclustered, "
+                                                         "c.contype, c.conname, "
+                                                         "c.tableoid as contableoid, "
+                                                         "c.oid as conoid, "
+                                                         "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) as tablespace, "
+                                                         "array_to_string(t.reloptions, ', ') as options "
+                                                         "FROM pg_catalog.pg_index i "
+                                         "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
+                                                         "LEFT JOIN pg_catalog.pg_depend d "
+                                                         "ON (d.classid = t.tableoid "
+                                                         "AND d.objid = t.oid "
+                                                         "AND d.deptype = 'i') "
+                                                         "LEFT JOIN pg_catalog.pg_constraint c "
+                                                         "ON (d.refclassid = c.tableoid "
+                                                         "AND d.refobjid = c.oid) "
+                                                         "WHERE i.indrelid = '%u'::pg_catalog.oid "
+                                                         "ORDER BY indexname",
+                                                         tbinfo->dobj.catId.oid);
                }
-               else
+               else if (g_fout->remoteVersion >= 80000)
                {
-                       /* format_type not available before 7.1 */
-                       appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, -1 as attstattarget, attstorage, attstorage as typstorage, "
-                                                         "attnotnull, atthasdef, false as attisdropped, null as attislocal, "
-                                                         "(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",
-                                                         tbinfo->oid);
+                       appendPQExpBuffer(query,
+                                                         "SELECT t.tableoid, t.oid, "
+                                                         "t.relname as indexname, "
+                                        "pg_catalog.pg_get_indexdef(i.indexrelid) as indexdef, "
+                                                         "t.relnatts as indnkeys, "
+                                                         "i.indkey, i.indisclustered, "
+                                                         "c.contype, c.conname, "
+                                                         "c.tableoid as contableoid, "
+                                                         "c.oid as conoid, "
+                                                         "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) as tablespace, "
+                                                         "null as options "
+                                                         "FROM pg_catalog.pg_index i "
+                                         "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
+                                                         "LEFT JOIN pg_catalog.pg_depend d "
+                                                         "ON (d.classid = t.tableoid "
+                                                         "AND d.objid = t.oid "
+                                                         "AND d.deptype = 'i') "
+                                                         "LEFT JOIN pg_catalog.pg_constraint c "
+                                                         "ON (d.refclassid = c.tableoid "
+                                                         "AND d.refobjid = c.oid) "
+                                                         "WHERE i.indrelid = '%u'::pg_catalog.oid "
+                                                         "ORDER BY indexname",
+                                                         tbinfo->dobj.catId.oid);
                }
-
-               res = PQexec(g_conn, q->data);
-               if (!res ||
-                       PQresultStatus(res) != PGRES_TUPLES_OK)
+               else if (g_fout->remoteVersion >= 70300)
                {
-                       write_msg(NULL, "query to get table columns failed: %s", PQerrorMessage(g_conn));
-                       exit_nicely();
-               }
+                       appendPQExpBuffer(query,
+                                                         "SELECT t.tableoid, t.oid, "
+                                                         "t.relname as indexname, "
+                                        "pg_catalog.pg_get_indexdef(i.indexrelid) as indexdef, "
+                                                         "t.relnatts as indnkeys, "
+                                                         "i.indkey, i.indisclustered, "
+                                                         "c.contype, c.conname, "
+                                                         "c.tableoid as contableoid, "
+                                                         "c.oid as conoid, "
+                                                         "NULL as tablespace, "
+                                                         "null as options "
+                                                         "FROM pg_catalog.pg_index i "
+                                         "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
+                                                         "LEFT JOIN pg_catalog.pg_depend d "
+                                                         "ON (d.classid = t.tableoid "
+                                                         "AND d.objid = t.oid "
+                                                         "AND d.deptype = 'i') "
+                                                         "LEFT JOIN pg_catalog.pg_constraint c "
+                                                         "ON (d.refclassid = c.tableoid "
+                                                         "AND d.refobjid = c.oid) "
+                                                         "WHERE i.indrelid = '%u'::pg_catalog.oid "
+                                                         "ORDER BY indexname",
+                                                         tbinfo->dobj.catId.oid);
+               }
+               else if (g_fout->remoteVersion >= 70100)
+               {
+                       appendPQExpBuffer(query,
+                                                         "SELECT t.tableoid, t.oid, "
+                                                         "t.relname as indexname, "
+                                                         "pg_get_indexdef(i.indexrelid) as indexdef, "
+                                                         "t.relnatts as indnkeys, "
+                                                         "i.indkey, false as indisclustered, "
+                                                         "CASE WHEN i.indisprimary THEN 'p'::char "
+                                                         "ELSE '0'::char END as contype, "
+                                                         "t.relname as conname, "
+                                                         "0::oid as contableoid, "
+                                                         "t.oid as conoid, "
+                                                         "NULL as tablespace, "
+                                                         "null as options "
+                                                         "FROM pg_index i, pg_class t "
+                                                         "WHERE t.oid = i.indexrelid "
+                                                         "AND i.indrelid = '%u'::oid "
+                                                         "ORDER BY indexname",
+                                                         tbinfo->dobj.catId.oid);
+               }
+               else
+               {
+                       appendPQExpBuffer(query,
+                                                         "SELECT "
+                                                         "(SELECT oid FROM pg_class WHERE relname = 'pg_class') AS tableoid, "
+                                                         "t.oid, "
+                                                         "t.relname as indexname, "
+                                                         "pg_get_indexdef(i.indexrelid) as indexdef, "
+                                                         "t.relnatts as indnkeys, "
+                                                         "i.indkey, false as indisclustered, "
+                                                         "CASE WHEN i.indisprimary THEN 'p'::char "
+                                                         "ELSE '0'::char END as contype, "
+                                                         "t.relname as conname, "
+                                                         "0::oid as contableoid, "
+                                                         "t.oid as conoid, "
+                                                         "NULL as tablespace, "
+                                                         "null as options "
+                                                         "FROM pg_index i, pg_class t "
+                                                         "WHERE t.oid = i.indexrelid "
+                                                         "AND i.indrelid = '%u'::oid "
+                                                         "ORDER BY indexname",
+                                                         tbinfo->dobj.catId.oid);
+               }
+
+               res = PQexec(g_conn, query->data);
+               check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+               ntups = PQntuples(res);
+
+               i_tableoid = PQfnumber(res, "tableoid");
+               i_oid = PQfnumber(res, "oid");
+               i_indexname = PQfnumber(res, "indexname");
+               i_indexdef = PQfnumber(res, "indexdef");
+               i_indnkeys = PQfnumber(res, "indnkeys");
+               i_indkey = PQfnumber(res, "indkey");
+               i_indisclustered = PQfnumber(res, "indisclustered");
+               i_contype = PQfnumber(res, "contype");
+               i_conname = PQfnumber(res, "conname");
+               i_contableoid = PQfnumber(res, "contableoid");
+               i_conoid = PQfnumber(res, "conoid");
+               i_tablespace = PQfnumber(res, "tablespace");
+               i_options = PQfnumber(res, "options");
+
+               indxinfo = (IndxInfo *) malloc(ntups * sizeof(IndxInfo));
+               constrinfo = (ConstraintInfo *) malloc(ntups * sizeof(ConstraintInfo));
+
+               for (j = 0; j < ntups; j++)
+               {
+                       char            contype;
+
+                       indxinfo[j].dobj.objType = DO_INDEX;
+                       indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
+                       indxinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
+                       AssignDumpId(&indxinfo[j].dobj);
+                       indxinfo[j].dobj.name = strdup(PQgetvalue(res, j, i_indexname));
+                       indxinfo[j].dobj.namespace = tbinfo->dobj.namespace;
+                       indxinfo[j].indextable = tbinfo;
+                       indxinfo[j].indexdef = strdup(PQgetvalue(res, j, i_indexdef));
+                       indxinfo[j].indnkeys = atoi(PQgetvalue(res, j, i_indnkeys));
+                       indxinfo[j].tablespace = strdup(PQgetvalue(res, j, i_tablespace));
+                       indxinfo[j].options = strdup(PQgetvalue(res, j, i_options));
+
+                       /*
+                        * In pre-7.4 releases, indkeys may contain more entries than
+                        * indnkeys says (since indnkeys will be 1 for a functional
+                        * index).      We don't actually care about this case since we don't
+                        * examine indkeys except for indexes associated with PRIMARY and
+                        * UNIQUE constraints, which are never functional indexes. But we
+                        * have to allocate enough space to keep parseOidArray from
+                        * complaining.
+                        */
+                       indxinfo[j].indkeys = (Oid *) malloc(INDEX_MAX_KEYS * sizeof(Oid));
+                       parseOidArray(PQgetvalue(res, j, i_indkey),
+                                                 indxinfo[j].indkeys, INDEX_MAX_KEYS);
+                       indxinfo[j].indisclustered = (PQgetvalue(res, j, i_indisclustered)[0] == 't');
+                       contype = *(PQgetvalue(res, j, i_contype));
+
+                       if (contype == 'p' || contype == 'u')
+                       {
+                               /*
+                                * If we found a constraint matching the index, create an
+                                * entry for it.
+                                *
+                                * In a pre-7.3 database, we take this path iff the index was
+                                * marked indisprimary.
+                                */
+                               constrinfo[j].dobj.objType = DO_CONSTRAINT;
+                               constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid));
+                               constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
+                               AssignDumpId(&constrinfo[j].dobj);
+                               constrinfo[j].dobj.name = strdup(PQgetvalue(res, j, i_conname));
+                               constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
+                               constrinfo[j].contable = tbinfo;
+                               constrinfo[j].condomain = NULL;
+                               constrinfo[j].contype = contype;
+                               constrinfo[j].condef = NULL;
+                               constrinfo[j].conindex = indxinfo[j].dobj.dumpId;
+                               constrinfo[j].coninherited = false;
+                               constrinfo[j].separate = true;
+
+                               indxinfo[j].indexconstraint = constrinfo[j].dobj.dumpId;
+
+                               /* If pre-7.3 DB, better make sure table comes first */
+                               addObjectDependency(&constrinfo[j].dobj,
+                                                                       tbinfo->dobj.dumpId);
+                       }
+                       else
+                       {
+                               /* Plain secondary index */
+                               indxinfo[j].indexconstraint = 0;
+                       }
+               }
+
+               PQclear(res);
+       }
+
+       destroyPQExpBuffer(query);
+}
+
+/*
+ * getConstraints
+ *
+ * Get info about constraints on dumpable tables.
+ *
+ * Currently handles foreign keys only.
+ * Unique and primary key constraints are handled with indexes,
+ * while check constraints are processed in getTableAttrs().
+ */
+void
+getConstraints(TableInfo tblinfo[], int numTables)
+{
+       int                     i,
+                               j;
+       ConstraintInfo *constrinfo;
+       PQExpBuffer query;
+       PGresult   *res;
+       int                     i_condef,
+                               i_contableoid,
+                               i_conoid,
+                               i_conname;
+       int                     ntups;
+
+       /* pg_constraint was created in 7.3, so nothing to do if older */
+       if (g_fout->remoteVersion < 70300)
+               return;
+
+       query = createPQExpBuffer();
+
+       for (i = 0; i < numTables; i++)
+       {
+               TableInfo  *tbinfo = &tblinfo[i];
+
+               if (tbinfo->ntrig == 0 || !tbinfo->dobj.dump)
+                       continue;
+
+               if (g_verbose)
+                       write_msg(NULL, "reading foreign key constraints for table \"%s\"\n",
+                                         tbinfo->dobj.name);
+
+               /*
+                * select table schema to ensure constraint expr is qualified if
+                * needed
+                */
+               selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
+
+               resetPQExpBuffer(query);
+               appendPQExpBuffer(query,
+                                                 "SELECT tableoid, oid, conname, "
+                                                 "pg_catalog.pg_get_constraintdef(oid) as condef "
+                                                 "FROM pg_catalog.pg_constraint "
+                                                 "WHERE conrelid = '%u'::pg_catalog.oid "
+                                                 "AND contype = 'f'",
+                                                 tbinfo->dobj.catId.oid);
+               res = PQexec(g_conn, query->data);
+               check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+               ntups = PQntuples(res);
+
+               i_contableoid = PQfnumber(res, "tableoid");
+               i_conoid = PQfnumber(res, "oid");
+               i_conname = PQfnumber(res, "conname");
+               i_condef = PQfnumber(res, "condef");
+
+               constrinfo = (ConstraintInfo *) malloc(ntups * sizeof(ConstraintInfo));
+
+               for (j = 0; j < ntups; j++)
+               {
+                       constrinfo[j].dobj.objType = DO_FK_CONSTRAINT;
+                       constrinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_contableoid));
+                       constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
+                       AssignDumpId(&constrinfo[j].dobj);
+                       constrinfo[j].dobj.name = strdup(PQgetvalue(res, j, i_conname));
+                       constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
+                       constrinfo[j].contable = tbinfo;
+                       constrinfo[j].condomain = NULL;
+                       constrinfo[j].contype = 'f';
+                       constrinfo[j].condef = strdup(PQgetvalue(res, j, i_condef));
+                       constrinfo[j].conindex = 0;
+                       constrinfo[j].coninherited = false;
+                       constrinfo[j].separate = true;
+               }
+
+               PQclear(res);
+       }
+
+       destroyPQExpBuffer(query);
+}
+
+/*
+ * getDomainConstraints
+ *
+ * Get info about constraints on a domain.
+ */
+static void
+getDomainConstraints(TypeInfo *tinfo)
+{
+       int                     i;
+       ConstraintInfo *constrinfo;
+       PQExpBuffer query;
+       PGresult   *res;
+       int                     i_tableoid,
+                               i_oid,
+                               i_conname,
+                               i_consrc;
+       int                     ntups;
+
+       /* pg_constraint was created in 7.3, so nothing to do if older */
+       if (g_fout->remoteVersion < 70300)
+               return;
+
+       /*
+        * select appropriate schema to ensure names in constraint are properly
+        * qualified
+        */
+       selectSourceSchema(tinfo->dobj.namespace->dobj.name);
+
+       query = createPQExpBuffer();
+
+       if (g_fout->remoteVersion >= 70400)
+               appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
+                                                 "pg_catalog.pg_get_constraintdef(oid) AS consrc "
+                                                 "FROM pg_catalog.pg_constraint "
+                                                 "WHERE contypid = '%u'::pg_catalog.oid "
+                                                 "ORDER BY conname",
+                                                 tinfo->dobj.catId.oid);
+       else
+               appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
+                                                 "'CHECK (' || consrc || ')' AS consrc "
+                                                 "FROM pg_catalog.pg_constraint "
+                                                 "WHERE contypid = '%u'::pg_catalog.oid "
+                                                 "ORDER BY conname",
+                                                 tinfo->dobj.catId.oid);
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       ntups = PQntuples(res);
+
+       i_tableoid = PQfnumber(res, "tableoid");
+       i_oid = PQfnumber(res, "oid");
+       i_conname = PQfnumber(res, "conname");
+       i_consrc = PQfnumber(res, "consrc");
+
+       constrinfo = (ConstraintInfo *) malloc(ntups * sizeof(ConstraintInfo));
+
+       tinfo->nDomChecks = ntups;
+       tinfo->domChecks = constrinfo;
+
+       for (i = 0; i < ntups; i++)
+       {
+               constrinfo[i].dobj.objType = DO_CONSTRAINT;
+               constrinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               constrinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&constrinfo[i].dobj);
+               constrinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_conname));
+               constrinfo[i].dobj.namespace = tinfo->dobj.namespace;
+               constrinfo[i].contable = NULL;
+               constrinfo[i].condomain = tinfo;
+               constrinfo[i].contype = 'c';
+               constrinfo[i].condef = strdup(PQgetvalue(res, i, i_consrc));
+               constrinfo[i].conindex = 0;
+               constrinfo[i].coninherited = false;
+               constrinfo[i].separate = false;
+
+               /*
+                * Make the domain depend on the constraint, ensuring it won't be
+                * output till any constraint dependencies are OK.
+                */
+               addObjectDependency(&tinfo->dobj,
+                                                       constrinfo[i].dobj.dumpId);
+       }
+
+       PQclear(res);
+
+       destroyPQExpBuffer(query);
+}
+
+/*
+ * getRules
+ *       get basic information about every rule in the system
+ *
+ * numRules is set to the number of rules read in
+ */
+RuleInfo *
+getRules(int *numRules)
+{
+       PGresult   *res;
+       int                     ntups;
+       int                     i;
+       PQExpBuffer query = createPQExpBuffer();
+       RuleInfo   *ruleinfo;
+       int                     i_tableoid;
+       int                     i_oid;
+       int                     i_rulename;
+       int                     i_ruletable;
+       int                     i_ev_type;
+       int                     i_is_instead;
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       if (g_fout->remoteVersion >= 70100)
+       {
+               appendPQExpBuffer(query, "SELECT "
+                                                 "tableoid, oid, rulename, "
+                                                 "ev_class as ruletable, ev_type, is_instead "
+                                                 "FROM pg_rewrite "
+                                                 "ORDER BY oid");
+       }
+       else
+       {
+               appendPQExpBuffer(query, "SELECT "
+                                                 "(SELECT oid FROM pg_class WHERE relname = 'pg_rewrite') AS tableoid, "
+                                                 "oid, rulename, "
+                                                 "ev_class as ruletable, ev_type, is_instead "
+                                                 "FROM pg_rewrite "
+                                                 "ORDER BY oid");
+       }
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       ntups = PQntuples(res);
+
+       *numRules = ntups;
+
+       ruleinfo = (RuleInfo *) malloc(ntups * sizeof(RuleInfo));
+
+       i_tableoid = PQfnumber(res, "tableoid");
+       i_oid = PQfnumber(res, "oid");
+       i_rulename = PQfnumber(res, "rulename");
+       i_ruletable = PQfnumber(res, "ruletable");
+       i_ev_type = PQfnumber(res, "ev_type");
+       i_is_instead = PQfnumber(res, "is_instead");
+
+       for (i = 0; i < ntups; i++)
+       {
+               Oid                     ruletableoid;
+
+               ruleinfo[i].dobj.objType = DO_RULE;
+               ruleinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               ruleinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&ruleinfo[i].dobj);
+               ruleinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_rulename));
+               ruletableoid = atooid(PQgetvalue(res, i, i_ruletable));
+               ruleinfo[i].ruletable = findTableByOid(ruletableoid);
+               if (ruleinfo[i].ruletable == NULL)
+               {
+                       write_msg(NULL, "failed sanity check, parent table OID %u of pg_rewrite entry OID %u not found\n",
+                                         ruletableoid,
+                                         ruleinfo[i].dobj.catId.oid);
+                       exit_nicely();
+               }
+               ruleinfo[i].dobj.namespace = ruleinfo[i].ruletable->dobj.namespace;
+               ruleinfo[i].dobj.dump = ruleinfo[i].ruletable->dobj.dump;
+               ruleinfo[i].ev_type = *(PQgetvalue(res, i, i_ev_type));
+               ruleinfo[i].is_instead = *(PQgetvalue(res, i, i_is_instead)) == 't';
+               if (ruleinfo[i].ruletable)
+               {
+                       /*
+                        * If the table is a view, force its ON SELECT rule to be sorted
+                        * before the view itself --- this ensures that any dependencies
+                        * for the rule affect the table's positioning. Other rules are
+                        * forced to appear after their table.
+                        */
+                       if (ruleinfo[i].ruletable->relkind == RELKIND_VIEW &&
+                               ruleinfo[i].ev_type == '1' && ruleinfo[i].is_instead)
+                       {
+                               addObjectDependency(&ruleinfo[i].ruletable->dobj,
+                                                                       ruleinfo[i].dobj.dumpId);
+                               /* We'll merge the rule into CREATE VIEW, if possible */
+                               ruleinfo[i].separate = false;
+                       }
+                       else
+                       {
+                               addObjectDependency(&ruleinfo[i].dobj,
+                                                                       ruleinfo[i].ruletable->dobj.dumpId);
+                               ruleinfo[i].separate = true;
+                       }
+               }
+               else
+                       ruleinfo[i].separate = true;
+       }
+
+       PQclear(res);
+
+       destroyPQExpBuffer(query);
+
+       return ruleinfo;
+}
+
+/*
+ * getTriggers
+ *       get information about every trigger on a dumpable table
+ *
+ * Note: trigger data is not returned directly to the caller, but it
+ * does get entered into the DumpableObject tables.
+ */
+void
+getTriggers(TableInfo tblinfo[], int numTables)
+{
+       int                     i,
+                               j;
+       PQExpBuffer query = createPQExpBuffer();
+       PGresult   *res;
+       TriggerInfo *tginfo;
+       int                     i_tableoid,
+                               i_oid,
+                               i_tgname,
+                               i_tgfname,
+                               i_tgtype,
+                               i_tgnargs,
+                               i_tgargs,
+                               i_tgisconstraint,
+                               i_tgconstrname,
+                               i_tgconstrrelid,
+                               i_tgconstrrelname,
+                               i_tgenabled,
+                               i_tgdeferrable,
+                               i_tginitdeferred;
+       int                     ntups;
+
+       for (i = 0; i < numTables; i++)
+       {
+               TableInfo  *tbinfo = &tblinfo[i];
+
+               if (tbinfo->ntrig == 0 || !tbinfo->dobj.dump)
+                       continue;
+
+               if (g_verbose)
+                       write_msg(NULL, "reading triggers for table \"%s\"\n",
+                                         tbinfo->dobj.name);
+
+               /*
+                * select table schema to ensure regproc name is qualified if needed
+                */
+               selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
+
+               resetPQExpBuffer(query);
+               if (g_fout->remoteVersion >= 70300)
+               {
+                       /*
+                        * We ignore triggers that are tied to a foreign-key constraint
+                        */
+                       appendPQExpBuffer(query,
+                                                         "SELECT tgname, "
+                                                         "tgfoid::pg_catalog.regproc as tgfname, "
+                                                         "tgtype, tgnargs, tgargs, tgenabled, "
+                                                         "tgisconstraint, tgconstrname, tgdeferrable, "
+                                                         "tgconstrrelid, tginitdeferred, tableoid, oid, "
+                                        "tgconstrrelid::pg_catalog.regclass as tgconstrrelname "
+                                                         "from pg_catalog.pg_trigger t "
+                                                         "where tgrelid = '%u'::pg_catalog.oid "
+                                                         "and (not tgisconstraint "
+                                                         " OR NOT EXISTS"
+                                                         "  (SELECT 1 FROM pg_catalog.pg_depend d "
+                                                         "   JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) "
+                                                         "   WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))",
+                                                         tbinfo->dobj.catId.oid);
+               }
+               else if (g_fout->remoteVersion >= 70100)
+               {
+                       appendPQExpBuffer(query,
+                                                         "SELECT tgname, tgfoid::regproc as tgfname, "
+                                                         "tgtype, tgnargs, tgargs, tgenabled, "
+                                                         "tgisconstraint, tgconstrname, tgdeferrable, "
+                                                         "tgconstrrelid, tginitdeferred, tableoid, oid, "
+                                 "(select relname from pg_class where oid = tgconstrrelid) "
+                                                         "             as tgconstrrelname "
+                                                         "from pg_trigger "
+                                                         "where tgrelid = '%u'::oid",
+                                                         tbinfo->dobj.catId.oid);
+               }
+               else
+               {
+                       appendPQExpBuffer(query,
+                                                         "SELECT tgname, tgfoid::regproc as tgfname, "
+                                                         "tgtype, tgnargs, tgargs, tgenabled, "
+                                                         "tgisconstraint, tgconstrname, tgdeferrable, "
+                                                         "tgconstrrelid, tginitdeferred, "
+                                                         "(SELECT oid FROM pg_class WHERE relname = 'pg_trigger') AS tableoid, "
+
+                                                         "oid, "
+                                 "(select relname from pg_class where oid = tgconstrrelid) "
+                                                         "             as tgconstrrelname "
+                                                         "from pg_trigger "
+                                                         "where tgrelid = '%u'::oid",
+                                                         tbinfo->dobj.catId.oid);
+               }
+               res = PQexec(g_conn, query->data);
+               check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+               ntups = PQntuples(res);
+
+               /*
+                * We may have less triggers than recorded due to having ignored
+                * foreign-key triggers
+                */
+               if (ntups > tbinfo->ntrig)
+               {
+                       write_msg(NULL, "expected %d triggers on table \"%s\" but found %d\n",
+                                         tbinfo->ntrig, tbinfo->dobj.name, ntups);
+                       exit_nicely();
+               }
+               i_tableoid = PQfnumber(res, "tableoid");
+               i_oid = PQfnumber(res, "oid");
+               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_tgisconstraint = PQfnumber(res, "tgisconstraint");
+               i_tgconstrname = PQfnumber(res, "tgconstrname");
+               i_tgconstrrelid = PQfnumber(res, "tgconstrrelid");
+               i_tgconstrrelname = PQfnumber(res, "tgconstrrelname");
+               i_tgenabled = PQfnumber(res, "tgenabled");
+               i_tgdeferrable = PQfnumber(res, "tgdeferrable");
+               i_tginitdeferred = PQfnumber(res, "tginitdeferred");
+
+               tginfo = (TriggerInfo *) malloc(ntups * sizeof(TriggerInfo));
+
+               for (j = 0; j < ntups; j++)
+               {
+                       tginfo[j].dobj.objType = DO_TRIGGER;
+                       tginfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
+                       tginfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
+                       AssignDumpId(&tginfo[j].dobj);
+                       tginfo[j].dobj.name = strdup(PQgetvalue(res, j, i_tgname));
+                       tginfo[j].dobj.namespace = tbinfo->dobj.namespace;
+                       tginfo[j].tgtable = tbinfo;
+                       tginfo[j].tgfname = strdup(PQgetvalue(res, j, i_tgfname));
+                       tginfo[j].tgtype = atoi(PQgetvalue(res, j, i_tgtype));
+                       tginfo[j].tgnargs = atoi(PQgetvalue(res, j, i_tgnargs));
+                       tginfo[j].tgargs = strdup(PQgetvalue(res, j, i_tgargs));
+                       tginfo[j].tgisconstraint = *(PQgetvalue(res, j, i_tgisconstraint)) == 't';
+                       tginfo[j].tgenabled = *(PQgetvalue(res, j, i_tgenabled)) == 't';
+                       tginfo[j].tgdeferrable = *(PQgetvalue(res, j, i_tgdeferrable)) == 't';
+                       tginfo[j].tginitdeferred = *(PQgetvalue(res, j, i_tginitdeferred)) == 't';
+
+                       if (tginfo[j].tgisconstraint)
+                       {
+                               tginfo[j].tgconstrname = strdup(PQgetvalue(res, j, i_tgconstrname));
+                               tginfo[j].tgconstrrelid = atooid(PQgetvalue(res, j, i_tgconstrrelid));
+                               if (OidIsValid(tginfo[j].tgconstrrelid))
+                               {
+                                       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: %u)\n",
+                                                                 tginfo[j].dobj.name, tbinfo->dobj.name,
+                                                                 tginfo[j].tgconstrrelid);
+                                               exit_nicely();
+                                       }
+                                       tginfo[j].tgconstrrelname = strdup(PQgetvalue(res, j, i_tgconstrrelname));
+                               }
+                               else
+                                       tginfo[j].tgconstrrelname = NULL;
+                       }
+                       else
+                       {
+                               tginfo[j].tgconstrname = NULL;
+                               tginfo[j].tgconstrrelid = InvalidOid;
+                               tginfo[j].tgconstrrelname = NULL;
+                       }
+               }
+
+               PQclear(res);
+       }
+
+       destroyPQExpBuffer(query);
+}
+
+/*
+ * getProcLangs
+ *       get basic information about every procedural language in the system
+ *
+ * numProcLangs is set to the number of langs read in
+ *
+ * NB: this must run after getFuncs() because we assume we can do
+ * findFuncByOid().
+ */
+ProcLangInfo *
+getProcLangs(int *numProcLangs)
+{
+       PGresult   *res;
+       int                     ntups;
+       int                     i;
+       PQExpBuffer query = createPQExpBuffer();
+       ProcLangInfo *planginfo;
+       int                     i_tableoid;
+       int                     i_oid;
+       int                     i_lanname;
+       int                     i_lanpltrusted;
+       int                     i_lanplcallfoid;
+       int                     i_lanvalidator;
+       int                     i_lanacl;
+       int                     i_lanowner;
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       if (g_fout->remoteVersion >= 80100)
+       {
+               /* Languages are owned by the bootstrap superuser, OID 10 */
+               appendPQExpBuffer(query, "SELECT tableoid, oid, *, "
+                                                 "(%s '10') as lanowner "
+                                                 "FROM pg_language "
+                                                 "WHERE lanispl "
+                                                 "ORDER BY oid",
+                                                 username_subquery);
+       }
+       else if (g_fout->remoteVersion >= 70400)
+       {
+               /* Languages are owned by the bootstrap superuser, sysid 1 */
+               appendPQExpBuffer(query, "SELECT tableoid, oid, *, "
+                                                 "(%s '1') as lanowner "
+                                                 "FROM pg_language "
+                                                 "WHERE lanispl "
+                                                 "ORDER BY oid",
+                                                 username_subquery);
+       }
+       else if (g_fout->remoteVersion >= 70100)
+       {
+               /* No clear notion of an owner at all before 7.4 ... */
+               appendPQExpBuffer(query, "SELECT tableoid, oid, * FROM pg_language "
+                                                 "WHERE lanispl "
+                                                 "ORDER BY oid");
+       }
+       else
+       {
+               appendPQExpBuffer(query, "SELECT "
+                                                 "(SELECT oid FROM pg_class WHERE relname = 'pg_language') AS tableoid, "
+                                                 "oid, * FROM pg_language "
+                                                 "WHERE lanispl "
+                                                 "ORDER BY oid");
+       }
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       ntups = PQntuples(res);
+
+       *numProcLangs = ntups;
+
+       planginfo = (ProcLangInfo *) malloc(ntups * sizeof(ProcLangInfo));
+
+       i_tableoid = PQfnumber(res, "tableoid");
+       i_oid = PQfnumber(res, "oid");
+       i_lanname = PQfnumber(res, "lanname");
+       i_lanpltrusted = PQfnumber(res, "lanpltrusted");
+       i_lanplcallfoid = PQfnumber(res, "lanplcallfoid");
+       /* these may fail and return -1: */
+       i_lanvalidator = PQfnumber(res, "lanvalidator");
+       i_lanacl = PQfnumber(res, "lanacl");
+       i_lanowner = PQfnumber(res, "lanowner");
+
+       for (i = 0; i < ntups; i++)
+       {
+               planginfo[i].dobj.objType = DO_PROCLANG;
+               planginfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               planginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&planginfo[i].dobj);
+
+               planginfo[i].dobj.name = strdup(PQgetvalue(res, i, i_lanname));
+               planginfo[i].lanpltrusted = *(PQgetvalue(res, i, i_lanpltrusted)) == 't';
+               planginfo[i].lanplcallfoid = atooid(PQgetvalue(res, i, i_lanplcallfoid));
+               if (i_lanvalidator >= 0)
+                       planginfo[i].lanvalidator = atooid(PQgetvalue(res, i, i_lanvalidator));
+               else
+                       planginfo[i].lanvalidator = InvalidOid;
+               if (i_lanacl >= 0)
+                       planginfo[i].lanacl = strdup(PQgetvalue(res, i, i_lanacl));
+               else
+                       planginfo[i].lanacl = strdup("{=U}");
+               if (i_lanowner >= 0)
+                       planginfo[i].lanowner = strdup(PQgetvalue(res, i, i_lanowner));
+               else
+                       planginfo[i].lanowner = strdup("");
+
+               if (g_fout->remoteVersion < 70300)
+               {
+                       /*
+                        * We need to make a dependency to ensure the function will be
+                        * dumped first.  (In 7.3 and later the regular dependency
+                        * mechanism will handle this for us.)
+                        */
+                       FuncInfo   *funcInfo = findFuncByOid(planginfo[i].lanplcallfoid);
+
+                       if (funcInfo)
+                               addObjectDependency(&planginfo[i].dobj,
+                                                                       funcInfo->dobj.dumpId);
+               }
+       }
+
+       PQclear(res);
+
+       destroyPQExpBuffer(query);
+
+       return planginfo;
+}
+
+/*
+ * getCasts
+ *       get basic information about every cast in the system
+ *
+ * numCasts is set to the number of casts read in
+ */
+CastInfo *
+getCasts(int *numCasts)
+{
+       PGresult   *res;
+       int                     ntups;
+       int                     i;
+       PQExpBuffer query = createPQExpBuffer();
+       CastInfo   *castinfo;
+       int                     i_tableoid;
+       int                     i_oid;
+       int                     i_castsource;
+       int                     i_casttarget;
+       int                     i_castfunc;
+       int                     i_castcontext;
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       if (g_fout->remoteVersion >= 70300)
+       {
+               appendPQExpBuffer(query, "SELECT tableoid, oid, "
+                                                 "castsource, casttarget, castfunc, castcontext "
+                                                 "FROM pg_cast ORDER BY 3,4");
+       }
+       else
+       {
+               appendPQExpBuffer(query, "SELECT 0 as tableoid, p.oid, "
+                                                 "t1.oid as castsource, t2.oid as casttarget, "
+                                                 "p.oid as castfunc, 'e' as castcontext "
+                                                 "FROM pg_type t1, pg_type t2, pg_proc p "
+                                                 "WHERE p.pronargs = 1 AND "
+                                                 "p.proargtypes[0] = t1.oid AND "
+                                                 "p.prorettype = t2.oid AND p.proname = t2.typname "
+                                                 "ORDER BY 3,4");
+       }
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       ntups = PQntuples(res);
+
+       *numCasts = ntups;
+
+       castinfo = (CastInfo *) malloc(ntups * sizeof(CastInfo));
+
+       i_tableoid = PQfnumber(res, "tableoid");
+       i_oid = PQfnumber(res, "oid");
+       i_castsource = PQfnumber(res, "castsource");
+       i_casttarget = PQfnumber(res, "casttarget");
+       i_castfunc = PQfnumber(res, "castfunc");
+       i_castcontext = PQfnumber(res, "castcontext");
+
+       for (i = 0; i < ntups; i++)
+       {
+               PQExpBufferData namebuf;
+               TypeInfo   *sTypeInfo;
+               TypeInfo   *tTypeInfo;
+
+               castinfo[i].dobj.objType = DO_CAST;
+               castinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               castinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&castinfo[i].dobj);
+               castinfo[i].castsource = atooid(PQgetvalue(res, i, i_castsource));
+               castinfo[i].casttarget = atooid(PQgetvalue(res, i, i_casttarget));
+               castinfo[i].castfunc = atooid(PQgetvalue(res, i, i_castfunc));
+               castinfo[i].castcontext = *(PQgetvalue(res, i, i_castcontext));
+
+               /*
+                * Try to name cast as concatenation of typnames.  This is only used
+                * for purposes of sorting.  If we fail to find either type, the name
+                * will be an empty string.
+                */
+               initPQExpBuffer(&namebuf);
+               sTypeInfo = findTypeByOid(castinfo[i].castsource);
+               tTypeInfo = findTypeByOid(castinfo[i].casttarget);
+               if (sTypeInfo && tTypeInfo)
+                       appendPQExpBuffer(&namebuf, "%s %s",
+                                                         sTypeInfo->dobj.name, tTypeInfo->dobj.name);
+               castinfo[i].dobj.name = namebuf.data;
+
+               if (OidIsValid(castinfo[i].castfunc))
+               {
+                       /*
+                        * We need to make a dependency to ensure the function will be
+                        * dumped first.  (In 7.3 and later the regular dependency
+                        * mechanism will handle this for us.)
+                        */
+                       FuncInfo   *funcInfo;
+
+                       funcInfo = findFuncByOid(castinfo[i].castfunc);
+                       if (funcInfo)
+                               addObjectDependency(&castinfo[i].dobj,
+                                                                       funcInfo->dobj.dumpId);
+               }
+       }
+
+       PQclear(res);
+
+       destroyPQExpBuffer(query);
+
+       return castinfo;
+}
+
+/*
+ * getTableAttrs -
+ *       for each interesting table, read info about its attributes
+ *       (names, types, default values, CHECK constraints, etc)
+ *
+ * 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
+ * types.  However, because we want type names and so forth to be named
+ * relative to the schema of each table, we couldn't do it in just one
+ * query.  (Maybe one query per schema?)
+ *
+ *     modifies tblinfo
+ */
+void
+getTableAttrs(TableInfo *tblinfo, int numTables)
+{
+       int                     i,
+                               j;
+       PQExpBuffer q = createPQExpBuffer();
+       int                     i_attnum;
+       int                     i_attname;
+       int                     i_atttypname;
+       int                     i_atttypmod;
+       int                     i_attstattarget;
+       int                     i_attstorage;
+       int                     i_typstorage;
+       int                     i_attnotnull;
+       int                     i_atthasdef;
+       int                     i_attisdropped;
+       int                     i_attislocal;
+       PGresult   *res;
+       int                     ntups;
+       bool            hasdefaults;
+
+       for (i = 0; i < numTables; i++)
+       {
+               TableInfo  *tbinfo = &tblinfo[i];
+
+               /* Don't bother to collect info for sequences */
+               if (tbinfo->relkind == RELKIND_SEQUENCE)
+                       continue;
+
+               /* Don't bother with uninteresting tables, either */
+               if (!tbinfo->interesting)
+                       continue;
+
+               /*
+                * Make sure we are in proper schema for this table; this allows
+                * correct retrieval of formatted type names and default exprs
+                */
+               selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
+
+               /* find all the user attributes and their types */
+
+               /*
+                * we must read the attribute names in attribute number order! because
+                * we will use the attnum to index into the attnames array 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 of table \"%s\"\n",
+                                         tbinfo->dobj.name);
+
+               resetPQExpBuffer(q);
+
+               if (g_fout->remoteVersion >= 70300)
+               {
+                       /* need left join here to not fail on dropped columns ... */
+                       appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, a.attstattarget, a.attstorage, t.typstorage, "
+                                 "a.attnotnull, a.atthasdef, a.attisdropped, a.attislocal, "
+                                  "pg_catalog.format_type(t.oid,a.atttypmod) as atttypname "
+                        "from pg_catalog.pg_attribute a left join pg_catalog.pg_type t "
+                                                         "on a.atttypid = t.oid "
+                                                         "where a.attrelid = '%u'::pg_catalog.oid "
+                                                         "and a.attnum > 0::pg_catalog.int2 "
+                                                         "order by a.attrelid, a.attnum",
+                                                         tbinfo->dobj.catId.oid);
+               }
+               else if (g_fout->remoteVersion >= 70100)
+               {
+                       /*
+                        * attstattarget doesn't exist in 7.1.  It does exist in 7.2, but
+                        * we don't dump it because we can't tell whether it's been
+                        * explicitly set or was just a default.
+                        */
+                       appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, -1 as attstattarget, a.attstorage, t.typstorage, "
+                                                         "a.attnotnull, a.atthasdef, false as attisdropped, false as attislocal, "
+                                                         "format_type(t.oid,a.atttypmod) as atttypname "
+                                                         "from pg_attribute a left join pg_type t "
+                                                         "on a.atttypid = t.oid "
+                                                         "where a.attrelid = '%u'::oid "
+                                                         "and a.attnum > 0::int2 "
+                                                         "order by a.attrelid, a.attnum",
+                                                         tbinfo->dobj.catId.oid);
+               }
+               else
+               {
+                       /* format_type not available before 7.1 */
+                       appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, -1 as attstattarget, attstorage, attstorage as typstorage, "
+                                                         "attnotnull, atthasdef, false as attisdropped, false as attislocal, "
+                                                         "(select typname from pg_type where oid = atttypid) as atttypname "
+                                                         "from pg_attribute a "
+                                                         "where attrelid = '%u'::oid "
+                                                         "and attnum > 0::int2 "
+                                                         "order by attrelid, attnum",
+                                                         tbinfo->dobj.catId.oid);
+               }
+
+               res = PQexec(g_conn, q->data);
+               check_sql_result(res, g_conn, q->data, PGRES_TUPLES_OK);
 
                ntups = PQntuples(res);
 
@@ -2461,9 +4306,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                tbinfo->typstorage = (char *) malloc(ntups * sizeof(char));
                tbinfo->attisdropped = (bool *) malloc(ntups * sizeof(bool));
                tbinfo->attislocal = (bool *) malloc(ntups * sizeof(bool));
-               tbinfo->attisserial = (bool *) malloc(ntups * sizeof(bool));
                tbinfo->notnull = (bool *) malloc(ntups * sizeof(bool));
-               tbinfo->adef_expr = (char **) malloc(ntups * sizeof(char *));
+               tbinfo->attrdefs = (AttrDefInfo **) malloc(ntups * sizeof(AttrDefInfo *));
                tbinfo->inhAttrs = (bool *) malloc(ntups * sizeof(bool));
                tbinfo->inhAttrDef = (bool *) malloc(ntups * sizeof(bool));
                tbinfo->inhNotNull = (bool *) malloc(ntups * sizeof(bool));
@@ -2474,7 +4318,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                        if (j + 1 != atoi(PQgetvalue(res, j, i_attnum)))
                        {
                                write_msg(NULL, "invalid column numbering in table \"%s\"\n",
-                                                 tbinfo->relname);
+                                                 tbinfo->dobj.name);
                                exit_nicely();
                        }
                        tbinfo->attnames[j] = strdup(PQgetvalue(res, j, i_attname));
@@ -2485,9 +4329,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                        tbinfo->typstorage[j] = *(PQgetvalue(res, j, i_typstorage));
                        tbinfo->attisdropped[j] = (PQgetvalue(res, j, i_attisdropped)[0] == 't');
                        tbinfo->attislocal[j] = (PQgetvalue(res, j, i_attislocal)[0] == 't');
-                       tbinfo->attisserial[j] = false;         /* fix below */
                        tbinfo->notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't');
-                       tbinfo->adef_expr[j] = NULL;            /* fix below */
+                       tbinfo->attrdefs[j] = NULL; /* fix below */
                        if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
                                hasdefaults = true;
                        /* these flags will be set in flagInhAttrs() */
@@ -2498,100 +4341,225 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 
                PQclear(res);
 
+               /*
+                * Get info about column defaults
+                */
                if (hasdefaults)
                {
+                       AttrDefInfo *attrdefs;
                        int                     numDefaults;
 
                        if (g_verbose)
                                write_msg(NULL, "finding default expressions of table \"%s\"\n",
-                                                 tbinfo->relname);
+                                                 tbinfo->dobj.name);
 
                        resetPQExpBuffer(q);
                        if (g_fout->remoteVersion >= 70300)
                        {
-                               appendPQExpBuffer(q, "SELECT adnum, "
-                                          "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc "
+                               appendPQExpBuffer(q, "SELECT tableoid, oid, adnum, "
+                                                  "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc "
                                                                  "FROM pg_catalog.pg_attrdef "
-                                                                 "WHERE adrelid = '%s'::pg_catalog.oid",
-                                                                 tbinfo->oid);
+                                                                 "WHERE adrelid = '%u'::pg_catalog.oid",
+                                                                 tbinfo->dobj.catId.oid);
                        }
                        else if (g_fout->remoteVersion >= 70200)
                        {
-                               appendPQExpBuffer(q, "SELECT adnum, "
+                               /* 7.2 did not have OIDs in pg_attrdef */
+                               appendPQExpBuffer(q, "SELECT tableoid, 0 as oid, adnum, "
                                                                  "pg_get_expr(adbin, adrelid) AS adsrc "
                                                                  "FROM pg_attrdef "
-                                                                 "WHERE adrelid = '%s'::oid",
-                                                                 tbinfo->oid);
+                                                                 "WHERE adrelid = '%u'::oid",
+                                                                 tbinfo->dobj.catId.oid);
                        }
-                       else
+                       else if (g_fout->remoteVersion >= 70100)
                        {
                                /* no pg_get_expr, so must rely on adsrc */
-                               appendPQExpBuffer(q, "SELECT adnum, adsrc FROM pg_attrdef "
-                                                                 "WHERE adrelid = '%s'::oid",
-                                                                 tbinfo->oid);
+                               appendPQExpBuffer(q, "SELECT tableoid, oid, adnum, adsrc "
+                                                                 "FROM pg_attrdef "
+                                                                 "WHERE adrelid = '%u'::oid",
+                                                                 tbinfo->dobj.catId.oid);
                        }
-                       res = PQexec(g_conn, q->data);
-                       if (!res ||
-                               PQresultStatus(res) != PGRES_TUPLES_OK)
+                       else
                        {
-                               write_msg(NULL, "query to get column default values failed: %s",
-                                                 PQerrorMessage(g_conn));
-                               exit_nicely();
+                               /* no pg_get_expr, no tableoid either */
+                               appendPQExpBuffer(q, "SELECT "
+                                                                 "(SELECT oid FROM pg_class WHERE relname = 'pg_attrdef') AS tableoid, "
+                                                                 "oid, adnum, adsrc "
+                                                                 "FROM pg_attrdef "
+                                                                 "WHERE adrelid = '%u'::oid",
+                                                                 tbinfo->dobj.catId.oid);
                        }
+                       res = PQexec(g_conn, q->data);
+                       check_sql_result(res, g_conn, q->data, PGRES_TUPLES_OK);
 
                        numDefaults = PQntuples(res);
+                       attrdefs = (AttrDefInfo *) malloc(numDefaults * sizeof(AttrDefInfo));
+
                        for (j = 0; j < numDefaults; j++)
                        {
-                               int                     adnum = atoi(PQgetvalue(res, j, 0));
+                               int                     adnum;
+
+                               attrdefs[j].dobj.objType = DO_ATTRDEF;
+                               attrdefs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0));
+                               attrdefs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1));
+                               AssignDumpId(&attrdefs[j].dobj);
+                               attrdefs[j].adtable = tbinfo;
+                               attrdefs[j].adnum = adnum = atoi(PQgetvalue(res, j, 2));
+                               attrdefs[j].adef_expr = strdup(PQgetvalue(res, j, 3));
+
+                               attrdefs[j].dobj.name = strdup(tbinfo->dobj.name);
+                               attrdefs[j].dobj.namespace = tbinfo->dobj.namespace;
+
+                               attrdefs[j].dobj.dump = tbinfo->dobj.dump;
+
+                               /*
+                                * Defaults on a VIEW must always be dumped as separate ALTER
+                                * TABLE commands.      Defaults on regular tables are dumped as
+                                * part of the CREATE TABLE if possible.  To check if it's
+                                * safe, we mark the default as needing to appear before the
+                                * CREATE.
+                                */
+                               if (tbinfo->relkind == RELKIND_VIEW)
+                               {
+                                       attrdefs[j].separate = true;
+                                       /* needed in case pre-7.3 DB: */
+                                       addObjectDependency(&attrdefs[j].dobj,
+                                                                               tbinfo->dobj.dumpId);
+                               }
+                               else
+                               {
+                                       attrdefs[j].separate = false;
+                                       addObjectDependency(&tbinfo->dobj,
+                                                                               attrdefs[j].dobj.dumpId);
+                               }
 
                                if (adnum <= 0 || adnum > ntups)
                                {
                                        write_msg(NULL, "invalid adnum value %d for table \"%s\"\n",
-                                                         adnum, tbinfo->relname);
+                                                         adnum, tbinfo->dobj.name);
                                        exit_nicely();
                                }
-                               tbinfo->adef_expr[adnum - 1] = strdup(PQgetvalue(res, j, 1));
+                               tbinfo->attrdefs[adnum - 1] = &attrdefs[j];
                        }
                        PQclear(res);
                }
 
                /*
-                * Check to see if any columns are serial columns.      Our first
-                * quick filter is that it must be integer or bigint with a
-                * default.  If so, we scan to see if we found a sequence linked
-                * to this column. If we did, mark the column and sequence
-                * appropriately.
+                * Get info about table CHECK constraints
                 */
-               for (j = 0; j < ntups; j++)
+               if (tbinfo->ncheck > 0)
                {
-                       /*
-                        * Note assumption that format_type will show these types as
-                        * exactly "integer" and "bigint" regardless of schema path.
-                        * This is correct in 7.3 but needs to be watched.
-                        */
-                       if (strcmp(tbinfo->atttypnames[j], "integer") != 0 &&
-                               strcmp(tbinfo->atttypnames[j], "bigint") != 0)
-                               continue;
-                       if (tbinfo->adef_expr[j] == NULL)
-                               continue;
-                       for (k = 0; k < numTables; k++)
+                       ConstraintInfo *constrs;
+                       int                     numConstrs;
+
+                       if (g_verbose)
+                               write_msg(NULL, "finding check constraints for table \"%s\"\n",
+                                                 tbinfo->dobj.name);
+
+                       resetPQExpBuffer(q);
+                       if (g_fout->remoteVersion >= 70400)
+                       {
+                               appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
+                                                       "pg_catalog.pg_get_constraintdef(oid) AS consrc "
+                                                                 "FROM pg_catalog.pg_constraint "
+                                                                 "WHERE conrelid = '%u'::pg_catalog.oid "
+                                                                 "   AND contype = 'c' "
+                                                                 "ORDER BY conname",
+                                                                 tbinfo->dobj.catId.oid);
+                       }
+                       else if (g_fout->remoteVersion >= 70300)
+                       {
+                               /* no pg_get_constraintdef, must use consrc */
+                               appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
+                                                                 "'CHECK (' || consrc || ')' AS consrc "
+                                                                 "FROM pg_catalog.pg_constraint "
+                                                                 "WHERE conrelid = '%u'::pg_catalog.oid "
+                                                                 "   AND contype = 'c' "
+                                                                 "ORDER BY conname",
+                                                                 tbinfo->dobj.catId.oid);
+                       }
+                       else if (g_fout->remoteVersion >= 70200)
                        {
-                               TableInfo  *seqinfo = &tblinfo[k];
+                               /* 7.2 did not have OIDs in pg_relcheck */
+                               appendPQExpBuffer(q, "SELECT tableoid, 0 as oid, "
+                                                                 "rcname AS conname, "
+                                                                 "'CHECK (' || rcsrc || ')' AS consrc "
+                                                                 "FROM pg_relcheck "
+                                                                 "WHERE rcrelid = '%u'::oid "
+                                                                 "ORDER BY rcname",
+                                                                 tbinfo->dobj.catId.oid);
+                       }
+                       else if (g_fout->remoteVersion >= 70100)
+                       {
+                               appendPQExpBuffer(q, "SELECT tableoid, oid, "
+                                                                 "rcname AS conname, "
+                                                                 "'CHECK (' || rcsrc || ')' AS consrc "
+                                                                 "FROM pg_relcheck "
+                                                                 "WHERE rcrelid = '%u'::oid "
+                                                                 "ORDER BY rcname",
+                                                                 tbinfo->dobj.catId.oid);
+                       }
+                       else
+                       {
+                               /* no tableoid in 7.0 */
+                               appendPQExpBuffer(q, "SELECT "
+                                                                 "(SELECT oid FROM pg_class WHERE relname = 'pg_relcheck') AS tableoid, "
+                                                                 "oid, rcname AS conname, "
+                                                                 "'CHECK (' || rcsrc || ')' AS consrc "
+                                                                 "FROM pg_relcheck "
+                                                                 "WHERE rcrelid = '%u'::oid "
+                                                                 "ORDER BY rcname",
+                                                                 tbinfo->dobj.catId.oid);
+                       }
+                       res = PQexec(g_conn, q->data);
+                       check_sql_result(res, g_conn, q->data, PGRES_TUPLES_OK);
 
-                               if (seqinfo->owning_tab != NULL &&
-                                       strcmp(seqinfo->owning_tab, tbinfo->oid) == 0 &&
-                                       seqinfo->owning_col == j + 1)
-                               {
-                                       /*
-                                        * Found a match.  Copy the table's interesting and
-                                        * dumpable flags to the sequence.
-                                        */
-                                       tbinfo->attisserial[j] = true;
-                                       seqinfo->interesting = tbinfo->interesting;
-                                       seqinfo->dump = tbinfo->dump;
-                                       break;
-                               }
+                       numConstrs = PQntuples(res);
+                       if (numConstrs != tbinfo->ncheck)
+                       {
+                               write_msg(NULL, "expected %d check constraints on table \"%s\" but found %d\n",
+                                                 tbinfo->ncheck, tbinfo->dobj.name, numConstrs);
+                               write_msg(NULL, "(The system catalogs might be corrupted.)\n");
+                               exit_nicely();
+                       }
+
+                       constrs = (ConstraintInfo *) malloc(numConstrs * sizeof(ConstraintInfo));
+                       tbinfo->checkexprs = constrs;
+
+                       for (j = 0; j < numConstrs; j++)
+                       {
+                               constrs[j].dobj.objType = DO_CONSTRAINT;
+                               constrs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0));
+                               constrs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1));
+                               AssignDumpId(&constrs[j].dobj);
+                               constrs[j].dobj.name = strdup(PQgetvalue(res, j, 2));
+                               constrs[j].dobj.namespace = tbinfo->dobj.namespace;
+                               constrs[j].contable = tbinfo;
+                               constrs[j].condomain = NULL;
+                               constrs[j].contype = 'c';
+                               constrs[j].condef = strdup(PQgetvalue(res, j, 3));
+                               constrs[j].conindex = 0;
+                               constrs[j].coninherited = false;
+                               constrs[j].separate = false;
+
+                               constrs[j].dobj.dump = tbinfo->dobj.dump;
+
+                               /*
+                                * Mark the constraint as needing to appear before the table
+                                * --- this is so that any other dependencies of the
+                                * constraint will be emitted before we try to create the
+                                * table.
+                                */
+                               addObjectDependency(&tbinfo->dobj,
+                                                                       constrs[j].dobj.dumpId);
+
+                               /*
+                                * If the constraint is inherited, this will be detected
+                                * later.  We also detect later if the constraint must be
+                                * split out from the table definition.
+                                */
                        }
+                       PQclear(res);
                }
        }
 
@@ -2603,394 +4571,561 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
  * dumpComment --
  *
  * This routine is used to dump any comments associated with the
- * oid handed to this routine. The routine takes a constant character
+ * object handed to this routine. The routine takes a constant character
  * string for the target part of the comment-creation command, plus
  * 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.
+ * plus catalog ID and subid which are the lookup key for pg_description,
+ * plus the dump ID for the object (for setting a dependency).
  * 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.
+ *
+ * Note: although this routine takes a dumpId for dependency purposes,
+ * that purpose is just to mark the dependency in the emitted dump file
+ * for possible future use by pg_restore.  We do NOT use it for determining
+ * ordering of the comment in the dump file, because this routine is called
+ * after dependency sorting occurs.  This routine should be called just after
+ * calling ArchiveEntry() for the specified object.
  */
-
 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)[]))
+                       CatalogId catalogId, int subid, DumpId dumpId)
 {
-       PGresult   *res;
-       PQExpBuffer query;
-       int                     i_description;
+       CommentItem *comments;
+       int                     ncomments;
 
        /* 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 comment */
-
-       query = createPQExpBuffer();
-
-       if (fout->remoteVersion >= 70300)
-       {
-               appendPQExpBuffer(query, "SELECT description FROM pg_catalog.pg_description "
-                                       "WHERE objoid = '%s'::pg_catalog.oid and classoid = "
-                                                 "'pg_catalog.%s'::pg_catalog.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 = "
-                                          "(SELECT oid FROM pg_class where relname = '%s') "
-                                                 "and objsubid = %d",
-                                                 oid, classname, subid);
-       }
-       else
-       {
-               /* Note: this will fail to find attribute comments in pre-7.2... */
-               appendPQExpBuffer(query, "SELECT description FROM pg_description WHERE objoid = '%s'::oid", oid);
-       }
-
-       /* Execute query */
+       /* Search for comments associated with catalogId, using table */
+       ncomments = findComments(fout, catalogId.tableoid, catalogId.oid,
+                                                        &comments);
 
-       res = PQexec(g_conn, query->data);
-       if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
+       /* Is there one matching the subid? */
+       while (ncomments > 0)
        {
-               write_msg(NULL, "query to get comment on OID %s failed: %s",
-                                 oid, PQerrorMessage(g_conn));
-               exit_nicely();
+               if (comments->objsubid == subid)
+                       break;
+               comments++;
+               ncomments--;
        }
 
        /* If a comment exists, build COMMENT ON statement */
-
-       if (PQntuples(res) == 1)
+       if (ncomments > 0)
        {
-               i_description = PQfnumber(res, "description");
-               resetPQExpBuffer(query);
+               PQExpBuffer query = createPQExpBuffer();
+
                appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
-               appendStringLiteral(query, PQgetvalue(res, 0, i_description), false);
+               appendStringLiteralAH(query, comments->descr, fout);
                appendPQExpBuffer(query, ";\n");
 
-               ArchiveEntry(fout, oid, target, namespace, owner,
-                                        "COMMENT", deps,
-                                        query->data, "", NULL, NULL, NULL);
-       }
+               ArchiveEntry(fout, nilCatalogId, createDumpId(),
+                                        target, namespace, NULL, owner, false,
+                                        "COMMENT", query->data, "", NULL,
+                                        &(dumpId), 1,
+                                        NULL, NULL);
 
-       PQclear(res);
-       destroyPQExpBuffer(query);
+               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.
+ * and its columns.
  */
 static void
 dumpTableComment(Archive *fout, TableInfo *tbinfo,
-                                const char *reltypename,
-                                const char *((*deps)[]))
+                                const char *reltypename)
 {
-       PGresult   *res;
+       CommentItem *comments;
+       int                     ncomments;
        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.
-        */
+       /* Search for comments associated with relation, using table */
+       ncomments = findComments(fout,
+                                                        tbinfo->dobj.catId.tableoid,
+                                                        tbinfo->dobj.catId.oid,
+                                                        &comments);
 
-       /* Build query to find comments */
+       /* If comments exist, build COMMENT ON statements */
+       if (ncomments <= 0)
+               return;
 
        query = createPQExpBuffer();
        target = createPQExpBuffer();
 
-       if (fout->remoteVersion >= 70300)
-       {
-               appendPQExpBuffer(query, "SELECT description, objsubid FROM pg_catalog.pg_description "
-                                       "WHERE objoid = '%s'::pg_catalog.oid and classoid = "
-                                                 "'pg_catalog.pg_class'::pg_catalog.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++)
+       while (ncomments > 0)
        {
-               const char *descr = PQgetvalue(res, i, i_description);
-               int                     objsubid = atoi(PQgetvalue(res, i, i_objsubid));
+               const char *descr = comments->descr;
+               int                     objsubid = comments->objsubid;
 
                if (objsubid == 0)
                {
                        resetPQExpBuffer(target);
                        appendPQExpBuffer(target, "%s %s", reltypename,
-                                                         fmtId(tbinfo->relname));
+                                                         fmtId(tbinfo->dobj.name));
 
                        resetPQExpBuffer(query);
                        appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
-                       appendStringLiteral(query, descr, false);
+                       appendStringLiteralAH(query, descr, fout);
                        appendPQExpBuffer(query, ";\n");
 
-                       ArchiveEntry(fout, tbinfo->oid, target->data,
-                                                tbinfo->relnamespace->nspname, tbinfo->usename,
-                                                "COMMENT", deps,
-                                                query->data, "", NULL, NULL, NULL);
+                       ArchiveEntry(fout, nilCatalogId, createDumpId(),
+                                                target->data,
+                                                tbinfo->dobj.namespace->dobj.name,
+                                                NULL,
+                                                tbinfo->rolname,
+                                                false, "COMMENT", query->data, "", NULL,
+                                                &(tbinfo->dobj.dumpId), 1,
+                                                NULL, NULL);
                }
                else if (objsubid > 0 && objsubid <= tbinfo->numatts)
                {
                        resetPQExpBuffer(target);
                        appendPQExpBuffer(target, "COLUMN %s.",
-                                                         fmtId(tbinfo->relname));
+                                                         fmtId(tbinfo->dobj.name));
                        appendPQExpBuffer(target, "%s",
                                                          fmtId(tbinfo->attnames[objsubid - 1]));
 
                        resetPQExpBuffer(query);
                        appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
-                       appendStringLiteral(query, descr, false);
+                       appendStringLiteralAH(query, descr, fout);
                        appendPQExpBuffer(query, ";\n");
 
-                       ArchiveEntry(fout, tbinfo->oid, target->data,
-                                                tbinfo->relnamespace->nspname, tbinfo->usename,
-                                                "COMMENT", deps,
-                                                query->data, "", NULL, NULL, NULL);
+                       ArchiveEntry(fout, nilCatalogId, createDumpId(),
+                                                target->data,
+                                                tbinfo->dobj.namespace->dobj.name,
+                                                NULL,
+                                                tbinfo->rolname,
+                                                false, "COMMENT", query->data, "", NULL,
+                                                &(tbinfo->dobj.dumpId), 1,
+                                                NULL, NULL);
                }
+
+               comments++;
+               ncomments--;
        }
 
-       PQclear(res);
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(target);
 }
 
 /*
- * dumpDBComment --
+ * findComments --
  *
- * This routine is used to dump any comments associated with the
- * database to which we are currently connected.
+ * Find the comment(s), if any, associated with the given object.  All the
+ * objsubid values associated with the given classoid/objoid are found with
+ * one search.
  */
-void
-dumpDBComment(Archive *fout)
+static int
+findComments(Archive *fout, Oid classoid, Oid objoid,
+                        CommentItem **items)
+{
+       /* static storage for table of comments */
+       static CommentItem *comments = NULL;
+       static int      ncomments = -1;
+
+       CommentItem *middle = NULL;
+       CommentItem *low;
+       CommentItem *high;
+       int                     nmatch;
+
+       /* Get comments if we didn't already */
+       if (ncomments < 0)
+               ncomments = collectComments(fout, &comments);
+
+       /*
+        * Pre-7.2, pg_description does not contain classoid, so collectComments
+        * just stores a zero.  If there's a collision on object OID, well, you
+        * get duplicate comments.
+        */
+       if (fout->remoteVersion < 70200)
+               classoid = 0;
+
+       /*
+        * Do binary search to find some item matching the object.
+        */
+       low = &comments[0];
+       high = &comments[ncomments - 1];
+       while (low <= high)
+       {
+               middle = low + (high - low) / 2;
+
+               if (classoid < middle->classoid)
+                       high = middle - 1;
+               else if (classoid > middle->classoid)
+                       low = middle + 1;
+               else if (objoid < middle->objoid)
+                       high = middle - 1;
+               else if (objoid > middle->objoid)
+                       low = middle + 1;
+               else
+                       break;                          /* found a match */
+       }
+
+       if (low > high)                         /* no matches */
+       {
+               *items = NULL;
+               return 0;
+       }
+
+       /*
+        * Now determine how many items match the object.  The search loop
+        * invariant still holds: only items between low and high inclusive could
+        * match.
+        */
+       nmatch = 1;
+       while (middle > low)
+       {
+               if (classoid != middle[-1].classoid ||
+                       objoid != middle[-1].objoid)
+                       break;
+               middle--;
+               nmatch++;
+       }
+
+       *items = middle;
+
+       middle += nmatch;
+       while (middle <= high)
+       {
+               if (classoid != middle->classoid ||
+                       objoid != middle->objoid)
+                       break;
+               middle++;
+               nmatch++;
+       }
+
+       return nmatch;
+}
+
+/*
+ * collectComments --
+ *
+ * Construct a table of all comments available for database objects.
+ * We used to do per-object queries for the comments, but it's much faster
+ * to pull them all over at once, and on most databases the memory cost
+ * isn't high.
+ *
+ * The table is sorted by classoid/objid/objsubid for speed in lookup.
+ */
+static int
+collectComments(Archive *fout, CommentItem **items)
 {
        PGresult   *res;
        PQExpBuffer query;
-       int                     i_oid;
+       int                     i_description;
+       int                     i_classoid;
+       int                     i_objoid;
+       int                     i_objsubid;
+       int                     ntups;
+       int                     i;
+       CommentItem *comments;
+
+       /*
+        * Note we do NOT change source schema here; preserve the caller's
+        * setting, instead.
+        */
+
+       query = createPQExpBuffer();
+
+       if (fout->remoteVersion >= 70300)
+       {
+               appendPQExpBuffer(query, "SELECT description, classoid, objoid, objsubid "
+                                                 "FROM pg_catalog.pg_description "
+                                                 "ORDER BY classoid, objoid, objsubid");
+       }
+       else if (fout->remoteVersion >= 70200)
+       {
+               appendPQExpBuffer(query, "SELECT description, classoid, objoid, objsubid "
+                                                 "FROM pg_description "
+                                                 "ORDER BY classoid, objoid, objsubid");
+       }
+       else
+       {
+               /* Note: this will fail to find attribute comments in pre-7.2... */
+               appendPQExpBuffer(query, "SELECT description, 0 as classoid, objoid, 0 as objsubid "
+                                                 "FROM pg_description "
+                                                 "ORDER BY objoid");
+       }
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema("pg_catalog");
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
-       /* Build query to find comment */
+       /* Construct lookup table containing OIDs in numeric form */
 
-       query = createPQExpBuffer();
-       appendPQExpBuffer(query, "SELECT oid FROM pg_database WHERE datname = ");
-       appendStringLiteral(query, PQdb(g_conn), true);
+       i_description = PQfnumber(res, "description");
+       i_classoid = PQfnumber(res, "classoid");
+       i_objoid = PQfnumber(res, "objoid");
+       i_objsubid = PQfnumber(res, "objsubid");
 
-       /* Execute query */
+       ntups = PQntuples(res);
 
-       res = PQexec(g_conn, query->data);
-       if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
+       comments = (CommentItem *) malloc(ntups * sizeof(CommentItem));
+
+       for (i = 0; i < ntups; i++)
        {
-               write_msg(NULL, "query to get database OID failed: %s",
-                                 PQerrorMessage(g_conn));
-               exit_nicely();
+               comments[i].descr = PQgetvalue(res, i, i_description);
+               comments[i].classoid = atooid(PQgetvalue(res, i, i_classoid));
+               comments[i].objoid = atooid(PQgetvalue(res, i, i_objoid));
+               comments[i].objsubid = atoi(PQgetvalue(res, i, i_objsubid));
        }
 
-       /* If a comment exists, build COMMENT ON statement */
+       /* Do NOT free the PGresult since we are keeping pointers into it */
+       destroyPQExpBuffer(query);
+
+       *items = comments;
+       return ntups;
+}
 
-       if (PQntuples(res) != 0)
+/*
+ * dumpDumpableObject
+ *
+ * This routine and its subsidiaries are responsible for creating
+ * ArchiveEntries (TOC objects) for each object to be dumped.
+ */
+static void
+dumpDumpableObject(Archive *fout, DumpableObject *dobj)
+{
+       switch (dobj->objType)
        {
-               i_oid = PQfnumber(res, "oid");
-               resetPQExpBuffer(query);
-               appendPQExpBuffer(query, "DATABASE %s", fmtId(PQdb(g_conn)));
-               dumpComment(fout, query->data, NULL, "",
-                                       PQgetvalue(res, 0, i_oid), "pg_database", 0, NULL);
+               case DO_NAMESPACE:
+                       dumpNamespace(fout, (NamespaceInfo *) dobj);
+                       break;
+               case DO_TYPE:
+                       dumpType(fout, (TypeInfo *) dobj);
+                       break;
+               case DO_SHELL_TYPE:
+                       dumpShellType(fout, (ShellTypeInfo *) dobj);
+                       break;
+               case DO_FUNC:
+                       dumpFunc(fout, (FuncInfo *) dobj);
+                       break;
+               case DO_AGG:
+                       dumpAgg(fout, (AggInfo *) dobj);
+                       break;
+               case DO_OPERATOR:
+                       dumpOpr(fout, (OprInfo *) dobj);
+                       break;
+               case DO_OPCLASS:
+                       dumpOpclass(fout, (OpclassInfo *) dobj);
+                       break;
+               case DO_CONVERSION:
+                       dumpConversion(fout, (ConvInfo *) dobj);
+                       break;
+               case DO_TABLE:
+                       dumpTable(fout, (TableInfo *) dobj);
+                       break;
+               case DO_ATTRDEF:
+                       dumpAttrDef(fout, (AttrDefInfo *) dobj);
+                       break;
+               case DO_INDEX:
+                       dumpIndex(fout, (IndxInfo *) dobj);
+                       break;
+               case DO_RULE:
+                       dumpRule(fout, (RuleInfo *) dobj);
+                       break;
+               case DO_TRIGGER:
+                       dumpTrigger(fout, (TriggerInfo *) dobj);
+                       break;
+               case DO_CONSTRAINT:
+                       dumpConstraint(fout, (ConstraintInfo *) dobj);
+                       break;
+               case DO_FK_CONSTRAINT:
+                       dumpConstraint(fout, (ConstraintInfo *) dobj);
+                       break;
+               case DO_PROCLANG:
+                       dumpProcLang(fout, (ProcLangInfo *) dobj);
+                       break;
+               case DO_CAST:
+                       dumpCast(fout, (CastInfo *) dobj);
+                       break;
+               case DO_TABLE_DATA:
+                       dumpTableData(fout, (TableDataInfo *) dobj);
+                       break;
+               case DO_TABLE_TYPE:
+                       /* table rowtypes are never dumped separately */
+                       break;
+               case DO_BLOBS:
+                       ArchiveEntry(fout, dobj->catId, dobj->dumpId,
+                                                dobj->name, NULL, NULL, "",
+                                                false, "BLOBS", "", "", NULL,
+                                                NULL, 0,
+                                                dumpBlobs, NULL);
+                       break;
+               case DO_BLOB_COMMENTS:
+                       ArchiveEntry(fout, dobj->catId, dobj->dumpId,
+                                                dobj->name, NULL, NULL, "",
+                                                false, "BLOB COMMENTS", "", "", NULL,
+                                                NULL, 0,
+                                                dumpBlobComments, NULL);
+                       break;
        }
-
-       PQclear(res);
-       destroyPQExpBuffer(query);
 }
 
 /*
- * dumpNamespaces
- *       writes out to fout the queries to recreate user-defined namespaces
+ * dumpNamespace
+ *       writes out to fout the queries to recreate a user-defined namespace
  */
-void
-dumpNamespaces(Archive *fout, NamespaceInfo *nsinfo, int numNamespaces)
+static void
+dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 {
-       PQExpBuffer q = createPQExpBuffer();
-       PQExpBuffer delq = createPQExpBuffer();
-       int                     i;
+       PQExpBuffer q;
+       PQExpBuffer delq;
        char       *qnspname;
 
-       for (i = 0; i < numNamespaces; i++)
-       {
-               NamespaceInfo *nspinfo = &nsinfo[i];
+       /* Skip if not to be dumped */
+       if (!nspinfo->dobj.dump || dataOnly)
+               return;
 
-               /* skip if not to be dumped */
-               if (!nspinfo->dump)
-                       continue;
+       /* don't dump dummy namespace from pre-7.3 source */
+       if (strlen(nspinfo->dobj.name) == 0)
+               return;
 
-               /* don't dump dummy namespace from pre-7.3 source */
-               if (strlen(nspinfo->nspname) == 0)
-                       continue;
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
 
-               qnspname = strdup(fmtId(nspinfo->nspname));
+       qnspname = strdup(fmtId(nspinfo->dobj.name));
 
-               /*
-                * If it's the PUBLIC namespace, don't emit a CREATE SCHEMA record
-                * for it, since we expect PUBLIC to exist already in the
-                * destination database.  And emit ACL info only if the ACL isn't
-                * the standard value for PUBLIC.
-                */
-               if (strcmp(nspinfo->nspname, "public") == 0)
-               {
-                       if (!aclsSkip && strcmp(nspinfo->nspacl, "{=UC}") != 0)
-                               dumpACL(fout, "SCHEMA", qnspname, nspinfo->nspname, NULL,
-                                               nspinfo->usename, nspinfo->nspacl,
-                                               nspinfo->oid);
-               }
-               else
-               {
-                       resetPQExpBuffer(q);
-                       resetPQExpBuffer(delq);
+       appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
 
-                       appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
+       appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
 
-                       appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
+       ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
+                                nspinfo->dobj.name,
+                                NULL, NULL,
+                                nspinfo->rolname,
+                                false, "SCHEMA", q->data, delq->data, NULL,
+                                nspinfo->dobj.dependencies, nspinfo->dobj.nDeps,
+                                NULL, NULL);
 
-                       ArchiveEntry(fout, nspinfo->oid, nspinfo->nspname,
-                                                NULL,
-                                                nspinfo->usename, "SCHEMA", NULL,
-                                                q->data, delq->data, NULL, NULL, NULL);
+       /* Dump Schema Comments */
+       resetPQExpBuffer(q);
+       appendPQExpBuffer(q, "SCHEMA %s", qnspname);
+       dumpComment(fout, q->data,
+                               NULL, nspinfo->rolname,
+                               nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
 
-                       /* Dump Schema Comments */
-                       resetPQExpBuffer(q);
-                       appendPQExpBuffer(q, "SCHEMA %s", qnspname);
-                       dumpComment(fout, q->data,
-                                               NULL, nspinfo->usename,
-                                               nspinfo->oid, "pg_namespace", 0, NULL);
-
-                       if (!aclsSkip)
-                               dumpACL(fout, "SCHEMA", qnspname, nspinfo->nspname, NULL,
-                                               nspinfo->usename, nspinfo->nspacl,
-                                               nspinfo->oid);
-               }
+       dumpACL(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, "SCHEMA",
+                       qnspname, nspinfo->dobj.name, NULL,
+                       nspinfo->rolname, nspinfo->nspacl);
 
-               free(qnspname);
-       }
+       free(qnspname);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
 }
 
 /*
- * dumpOneBaseType
+ * dumpType
+ *       writes out to fout the queries to recreate a user-defined type
+ */
+static void
+dumpType(Archive *fout, TypeInfo *tinfo)
+{
+       /* Skip if not to be dumped */
+       if (!tinfo->dobj.dump || dataOnly)
+               return;
+
+       /* Dump out in proper style */
+       if (tinfo->typtype == 'b')
+               dumpBaseType(fout, tinfo);
+       else if (tinfo->typtype == 'd')
+               dumpDomain(fout, tinfo);
+       else if (tinfo->typtype == 'c')
+               dumpCompositeType(fout, tinfo);
+}
+
+/*
+ * dumpBaseType
  *       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)
+dumpBaseType(Archive *fout, TypeInfo *tinfo)
 {
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
        PQExpBuffer query = createPQExpBuffer();
        PGresult   *res;
        int                     ntups;
-       int                     funcInd;
        char       *typlen;
        char       *typinput;
        char       *typoutput;
        char       *typreceive;
        char       *typsend;
-       char       *typinputoid;
-       char       *typoutputoid;
-       char       *typreceiveoid;
-       char       *typsendoid;
+       char       *typanalyze;
+       Oid                     typinputoid;
+       Oid                     typoutputoid;
+       Oid                     typreceiveoid;
+       Oid                     typsendoid;
+       Oid                     typanalyzeoid;
        char       *typdelim;
-       char       *typdefault;
        char       *typbyval;
        char       *typalign;
        char       *typstorage;
-       const char *((*deps)[]);
-       int                     depIdx = 0;
-
-       deps = malloc(sizeof(char *) * 10);
+       char       *typdefault;
+       bool            typdefault_is_literal = false;
 
        /* Set proper schema search path so regproc references list correctly */
-       selectSourceSchema(tinfo->typnamespace->nspname);
+       selectSourceSchema(tinfo->dobj.namespace->dobj.name);
 
        /* Fetch type-specific details */
-       if (fout->remoteVersion >= 70400)
+       if (fout->remoteVersion >= 80000)
+       {
+               appendPQExpBuffer(query, "SELECT typlen, "
+                                                 "typinput, typoutput, typreceive, typsend, "
+                                                 "typanalyze, "
+                                                 "typinput::pg_catalog.oid as typinputoid, "
+                                                 "typoutput::pg_catalog.oid as typoutputoid, "
+                                                 "typreceive::pg_catalog.oid as typreceiveoid, "
+                                                 "typsend::pg_catalog.oid as typsendoid, "
+                                                 "typanalyze::pg_catalog.oid as typanalyzeoid, "
+                                                 "typdelim, typbyval, typalign, typstorage, "
+                                                 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
+                                                 "FROM pg_catalog.pg_type "
+                                                 "WHERE oid = '%u'::pg_catalog.oid",
+                                                 tinfo->dobj.catId.oid);
+       }
+       else if (fout->remoteVersion >= 70400)
        {
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, typreceive, typsend, "
+                                                 "'-' as typanalyze, "
                                                  "typinput::pg_catalog.oid as typinputoid, "
                                                  "typoutput::pg_catalog.oid as typoutputoid, "
                                                  "typreceive::pg_catalog.oid as typreceiveoid, "
                                                  "typsend::pg_catalog.oid as typsendoid, "
-                                                 "typdelim, typdefault, typbyval, typalign, "
-                                                 "typstorage "
+                                                 "0 as typanalyzeoid, "
+                                                 "typdelim, typbyval, typalign, typstorage, "
+                                                 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
                                                  "FROM pg_catalog.pg_type "
-                                                 "WHERE oid = '%s'::pg_catalog.oid",
-                                                 tinfo->oid);
+                                                 "WHERE oid = '%u'::pg_catalog.oid",
+                                                 tinfo->dobj.catId.oid);
        }
        else if (fout->remoteVersion >= 70300)
        {
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, "
                                                  "'-' as typreceive, '-' as typsend, "
+                                                 "'-' as typanalyze, "
                                                  "typinput::pg_catalog.oid as typinputoid, "
                                                  "typoutput::pg_catalog.oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
-                                                 "typdelim, typdefault, typbyval, typalign, "
-                                                 "typstorage "
+                                                 "0 as typanalyzeoid, "
+                                                 "typdelim, typbyval, typalign, typstorage, "
+                                                 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
                                                  "FROM pg_catalog.pg_type "
-                                                 "WHERE oid = '%s'::pg_catalog.oid",
-                                                 tinfo->oid);
+                                                 "WHERE oid = '%u'::pg_catalog.oid",
+                                                 tinfo->dobj.catId.oid);
        }
-       else if (fout->remoteVersion >= 70100)
+       else if (fout->remoteVersion >= 70200)
        {
                /*
                 * Note: although pre-7.3 catalogs contain typreceive and typsend,
@@ -2999,38 +5134,57 @@ dumpOneBaseType(Archive *fout, TypeInfo *tinfo,
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, "
                                                  "'-' as typreceive, '-' as typsend, "
+                                                 "'-' as typanalyze, "
+                                                 "typinput::oid as typinputoid, "
+                                                 "typoutput::oid as typoutputoid, "
+                                                 "0 as typreceiveoid, 0 as typsendoid, "
+                                                 "0 as typanalyzeoid, "
+                                                 "typdelim, typbyval, typalign, typstorage, "
+                                                 "NULL as typdefaultbin, typdefault "
+                                                 "FROM pg_type "
+                                                 "WHERE oid = '%u'::oid",
+                                                 tinfo->dobj.catId.oid);
+       }
+       else if (fout->remoteVersion >= 70100)
+       {
+               /*
+                * Ignore pre-7.2 typdefault; the field exists but has an unusable
+                * representation.
+                */
+               appendPQExpBuffer(query, "SELECT typlen, "
+                                                 "typinput, typoutput, "
+                                                 "'-' as typreceive, '-' as typsend, "
+                                                 "'-' as typanalyze, "
                                                  "typinput::oid as typinputoid, "
                                                  "typoutput::oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
-                                                 "typdelim, typdefault, typbyval, typalign, "
-                                                 "typstorage "
+                                                 "0 as typanalyzeoid, "
+                                                 "typdelim, typbyval, typalign, typstorage, "
+                                                 "NULL as typdefaultbin, NULL as typdefault "
                                                  "FROM pg_type "
-                                                 "WHERE oid = '%s'::oid",
-                                                 tinfo->oid);
+                                                 "WHERE oid = '%u'::oid",
+                                                 tinfo->dobj.catId.oid);
        }
        else
        {
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, "
                                                  "'-' as typreceive, '-' as typsend, "
+                                                 "'-' as typanalyze, "
                                                  "typinput::oid as typinputoid, "
                                                  "typoutput::oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
-                                                 "typdelim, typdefault, typbyval, typalign, "
-                                                 "'p'::char as typstorage "
+                                                 "0 as typanalyzeoid, "
+                                                 "typdelim, typbyval, typalign, "
+                                                 "'p'::char as typstorage, "
+                                                 "NULL as typdefaultbin, NULL as typdefault "
                                                  "FROM pg_type "
-                                                 "WHERE oid = '%s'::oid",
-                                                 tinfo->oid);
+                                                 "WHERE oid = '%u'::oid",
+                                                 tinfo->dobj.catId.oid);
        }
 
        res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "query to obtain information on data type \"%s\" failed: %s",
-                                 tinfo->typname, PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        /* Expecting a single result only */
        ntups = PQntuples(res);
@@ -3046,71 +5200,54 @@ dumpOneBaseType(Archive *fout, TypeInfo *tinfo,
        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"));
+       typanalyze = PQgetvalue(res, 0, PQfnumber(res, "typanalyze"));
+       typinputoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typinputoid")));
+       typoutputoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typoutputoid")));
+       typreceiveoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typreceiveoid")));
+       typsendoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typsendoid")));
+       typanalyzeoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typanalyzeoid")));
        typdelim = PQgetvalue(res, 0, PQfnumber(res, "typdelim"));
-       if (PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
-               typdefault = NULL;
-       else
-               typdefault = 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, "0") != 0)
-       {
-               funcInd = findFuncByOid(g_finfo, numFuncs, typreceiveoid);
-               if (funcInd >= 0 && g_finfo[funcInd].pronamespace->dump)
-                       (*deps)[depIdx++] = strdup(typreceiveoid);
-       }
-
-       if (strcmp(typsendoid, "0") != 0)
+       if (!PQgetisnull(res, 0, PQfnumber(res, "typdefaultbin")))
+               typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefaultbin"));
+       else if (!PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
        {
-               funcInd = findFuncByOid(g_finfo, numFuncs, typsendoid);
-               if (funcInd >= 0 && g_finfo[funcInd].pronamespace->dump)
-                       (*deps)[depIdx++] = strdup(typsendoid);
+               typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault"));
+               typdefault_is_literal = true;           /* it needs quotes */
        }
+       else
+               typdefault = NULL;
 
        /*
-        * DROP must be fully qualified in case same name appears in
-        * pg_catalog
+        * DROP must be fully qualified in case same name appears in pg_catalog.
+        * The reason we include CASCADE is that the circular dependency between
+        * the type and its I/O functions makes it impossible to drop the type
+        * any other way.
         */
        appendPQExpBuffer(delq, "DROP TYPE %s.",
-                                         fmtId(tinfo->typnamespace->nspname));
+                                         fmtId(tinfo->dobj.namespace->dobj.name));
        appendPQExpBuffer(delq, "%s CASCADE;\n",
-                                         fmtId(tinfo->typname));
+                                         fmtId(tinfo->dobj.name));
 
        appendPQExpBuffer(q,
                                          "CREATE TYPE %s (\n"
                                          "    INTERNALLENGTH = %s",
-                                         fmtId(tinfo->typname),
+                                         fmtId(tinfo->dobj.name),
                                          (strcmp(typlen, "-1") == 0) ? "variable" : typlen);
 
        if (fout->remoteVersion >= 70300)
        {
-               /* regproc result is correctly quoted in 7.3 */
+               /* regproc result is correctly quoted as of 7.3 */
                appendPQExpBuffer(q, ",\n    INPUT = %s", typinput);
                appendPQExpBuffer(q, ",\n    OUTPUT = %s", typoutput);
-               if (strcmp(typreceiveoid, "0") != 0)
+               if (OidIsValid(typreceiveoid))
                        appendPQExpBuffer(q, ",\n    RECEIVE = %s", typreceive);
-               if (strcmp(typsendoid, "0") != 0)
+               if (OidIsValid(typsendoid))
                        appendPQExpBuffer(q, ",\n    SEND = %s", typsend);
+               if (OidIsValid(typanalyzeoid))
+                       appendPQExpBuffer(q, ",\n    ANALYZE = %s", typanalyze);
        }
        else
        {
@@ -3118,13 +5255,16 @@ dumpOneBaseType(Archive *fout, TypeInfo *tinfo,
                /* cannot combine these because fmtId uses static result area */
                appendPQExpBuffer(q, ",\n    INPUT = %s", fmtId(typinput));
                appendPQExpBuffer(q, ",\n    OUTPUT = %s", fmtId(typoutput));
-               /* no chance that receive/send need be printed */
+               /* no chance that receive/send/analyze need be printed */
        }
 
        if (typdefault != NULL)
        {
                appendPQExpBuffer(q, ",\n    DEFAULT = ");
-               appendStringLiteral(q, typdefault, true);
+               if (typdefault_is_literal)
+                       appendStringLiteralAH(q, typdefault, fout);
+               else
+                       appendPQExpBufferStr(q, typdefault);
        }
 
        if (tinfo->isArray)
@@ -3132,18 +5272,16 @@ dumpOneBaseType(Archive *fout, TypeInfo *tinfo,
                char       *elemType;
 
                /* reselect schema in case changed by function dump */
-               selectSourceSchema(tinfo->typnamespace->nspname);
+               selectSourceSchema(tinfo->dobj.namespace->dobj.name);
                elemType = getFormattedTypeName(tinfo->typelem, zeroAsOpaque);
                appendPQExpBuffer(q, ",\n    ELEMENT = %s", elemType);
                free(elemType);
-
-               (*deps)[depIdx++] = strdup(tinfo->typelem);
        }
 
        if (typdelim && strcmp(typdelim, ",") != 0)
        {
                appendPQExpBuffer(q, ",\n    DELIMITER = ");
-               appendStringLiteral(q, typdelim, true);
+               appendStringLiteralAH(q, typdelim, fout);
        }
 
        if (strcmp(typalign, "c") == 0)
@@ -3169,20 +5307,22 @@ dumpOneBaseType(Archive *fout, TypeInfo *tinfo,
 
        appendPQExpBuffer(q, "\n);\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);
+       ArchiveEntry(fout, tinfo->dobj.catId, tinfo->dobj.dumpId,
+                                tinfo->dobj.name,
+                                tinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                tinfo->rolname, false,
+                                "TYPE", q->data, delq->data, NULL,
+                                tinfo->dobj.dependencies, tinfo->dobj.nDeps,
+                                NULL, NULL);
 
        /* Dump Type Comments */
        resetPQExpBuffer(q);
 
-       appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo->typname));
+       appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo->dobj.name));
        dumpComment(fout, q->data,
-                               tinfo->typnamespace->nspname, tinfo->usename,
-                               tinfo->oid, "pg_type", 0, NULL);
+                               tinfo->dobj.namespace->dobj.name, tinfo->rolname,
+                               tinfo->dobj.catId, 0, tinfo->dobj.dumpId);
 
        PQclear(res);
        destroyPQExpBuffer(q);
@@ -3191,48 +5331,37 @@ dumpOneBaseType(Archive *fout, TypeInfo *tinfo,
 }
 
 /*
- * dumpOneDomain
+ * dumpDomain
  *       writes out to fout the queries to recreate a user-defined domain
- *       as requested by dumpTypes
  */
 static void
-dumpOneDomain(Archive *fout, TypeInfo *tinfo)
+dumpDomain(Archive *fout, TypeInfo *tinfo)
 {
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
        PQExpBuffer query = createPQExpBuffer();
-       PQExpBuffer chkquery = createPQExpBuffer();
        PGresult   *res;
        int                     ntups;
        int                     i;
        char       *typnotnull;
        char       *typdefn;
        char       *typdefault;
-       char       *typbasetype;
-       const char *((*deps)[]);
-       int                     depIdx = 0;
-
-       deps = malloc(sizeof(char *) * 10);
+       bool            typdefault_is_literal = false;
 
        /* Set proper schema search path so type references list correctly */
-       selectSourceSchema(tinfo->typnamespace->nspname);
+       selectSourceSchema(tinfo->dobj.namespace->dobj.name);
 
        /* Fetch domain specific details */
        /* We assume here that remoteVersion must be at least 70300 */
        appendPQExpBuffer(query, "SELECT typnotnull, "
-                       "pg_catalog.format_type(typbasetype, typtypmod) as typdefn, "
-                                         "typdefault, typbasetype "
+                               "pg_catalog.format_type(typbasetype, typtypmod) as typdefn, "
+                                         "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
                                          "FROM pg_catalog.pg_type "
-                                         "WHERE oid = '%s'::pg_catalog.oid",
-                                         tinfo->oid);
+                                         "WHERE oid = '%u'::pg_catalog.oid",
+                                         tinfo->dobj.catId.oid);
 
        res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "query to obtain domain information failed: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        /* Expecting a single result only */
        ntups = PQntuples(res);
@@ -3245,105 +5374,86 @@ dumpOneDomain(Archive *fout, TypeInfo *tinfo)
 
        typnotnull = PQgetvalue(res, 0, PQfnumber(res, "typnotnull"));
        typdefn = PQgetvalue(res, 0, PQfnumber(res, "typdefn"));
-       if (PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
-               typdefault = NULL;
-       else
+       if (!PQgetisnull(res, 0, PQfnumber(res, "typdefaultbin")))
+               typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefaultbin"));
+       else if (!PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
+       {
                typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault"));
-       typbasetype = PQgetvalue(res, 0, PQfnumber(res, "typbasetype"));
-
-       /*
-        * DROP must be fully qualified in case same name appears in
-        * pg_catalog
-        */
-       appendPQExpBuffer(delq, "DROP DOMAIN %s.",
-                                         fmtId(tinfo->typnamespace->nspname));
-       appendPQExpBuffer(delq, "%s;\n",
-                                         fmtId(tinfo->typname));
+               typdefault_is_literal = true;           /* it needs quotes */
+       }
+       else
+               typdefault = NULL;
 
        appendPQExpBuffer(q,
                                          "CREATE DOMAIN %s AS %s",
-                                         fmtId(tinfo->typname),
+                                         fmtId(tinfo->dobj.name),
                                          typdefn);
 
-       /* Depends on the base type */
-       (*deps)[depIdx++] = strdup(typbasetype);
-
        if (typnotnull[0] == 't')
                appendPQExpBuffer(q, " NOT NULL");
 
-       if (typdefault)
-               appendPQExpBuffer(q, " DEFAULT %s", typdefault);
+       if (typdefault != NULL)
+       {
+               appendPQExpBuffer(q, " DEFAULT ");
+               if (typdefault_is_literal)
+                       appendStringLiteralAH(q, typdefault, fout);
+               else
+                       appendPQExpBufferStr(q, typdefault);
+       }
 
        PQclear(res);
 
        /*
-        * Fetch and process CHECK constraints for the domain
+        * Add any CHECK constraints for the domain
         */
-       if (g_fout->remoteVersion >= 70400)
-               appendPQExpBuffer(chkquery, "SELECT conname, "
-                                               "pg_catalog.pg_get_constraintdef(oid) AS consrc "
-                                                 "FROM pg_catalog.pg_constraint "
-                                                 "WHERE contypid = '%s'::pg_catalog.oid",
-                                                 tinfo->oid);
-       else
-               appendPQExpBuffer(chkquery, "SELECT conname, 'CHECK (' || consrc || ')' AS consrc "
-                                                 "FROM pg_catalog.pg_constraint "
-                                                 "WHERE contypid = '%s'::pg_catalog.oid",
-                                                 tinfo->oid);
-
-       res = PQexec(g_conn, chkquery->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
+       for (i = 0; i < tinfo->nDomChecks; i++)
        {
-               write_msg(NULL, "query to obtain domain constraint information failed: %s",
-                                 PQerrorMessage(g_conn));
-               exit_nicely();
-       }
-
-       ntups = PQntuples(res);
-       for (i = 0; i < ntups; i++)
-       {
-               char       *conname;
-               char       *consrc;
+               ConstraintInfo *domcheck = &(tinfo->domChecks[i]);
 
-               conname = PQgetvalue(res, i, PQfnumber(res, "conname"));
-               consrc = PQgetvalue(res, i, PQfnumber(res, "consrc"));
-
-               appendPQExpBuffer(q, "\n\tCONSTRAINT %s %s",
-                                                 fmtId(conname), consrc);
+               if (!domcheck->separate)
+                       appendPQExpBuffer(q, "\n\tCONSTRAINT %s %s",
+                                                         fmtId(domcheck->dobj.name), domcheck->condef);
        }
 
        appendPQExpBuffer(q, ";\n");
 
-       (*deps)[depIdx++] = NULL;       /* End of List */
+       /*
+        * DROP must be fully qualified in case same name appears in pg_catalog
+        */
+       appendPQExpBuffer(delq, "DROP DOMAIN %s.",
+                                         fmtId(tinfo->dobj.namespace->dobj.name));
+       appendPQExpBuffer(delq, "%s;\n",
+                                         fmtId(tinfo->dobj.name));
 
-       ArchiveEntry(fout, tinfo->oid, tinfo->typname,
-                                tinfo->typnamespace->nspname,
-                                tinfo->usename, "DOMAIN", deps,
-                                q->data, delq->data, NULL, NULL, NULL);
+       ArchiveEntry(fout, tinfo->dobj.catId, tinfo->dobj.dumpId,
+                                tinfo->dobj.name,
+                                tinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                tinfo->rolname, false,
+                                "DOMAIN", q->data, delq->data, NULL,
+                                tinfo->dobj.dependencies, tinfo->dobj.nDeps,
+                                NULL, NULL);
 
        /* Dump Domain Comments */
        resetPQExpBuffer(q);
 
-       appendPQExpBuffer(q, "DOMAIN %s", fmtId(tinfo->typname));
+       appendPQExpBuffer(q, "DOMAIN %s", fmtId(tinfo->dobj.name));
        dumpComment(fout, q->data,
-                               tinfo->typnamespace->nspname, tinfo->usename,
-                               tinfo->oid, "pg_type", 0, NULL);
+                               tinfo->dobj.namespace->dobj.name, tinfo->rolname,
+                               tinfo->dobj.catId, 0, tinfo->dobj.dumpId);
 
-       PQclear(res);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
        destroyPQExpBuffer(query);
-       destroyPQExpBuffer(chkquery);
 }
 
 /*
- * dumpOneCompositeType
+ * dumpCompositeType
  *       writes out to fout the queries to recreate a user-defined stand-alone
- *       composite type as requested by dumpTypes
+ *       composite type
  */
 static void
-dumpOneCompositeType(Archive *fout, TypeInfo *tinfo)
+dumpCompositeType(Archive *fout, TypeInfo *tinfo)
 {
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
@@ -3355,27 +5465,22 @@ dumpOneCompositeType(Archive *fout, TypeInfo *tinfo)
        int                     i;
 
        /* Set proper schema search path so type references list correctly */
-       selectSourceSchema(tinfo->typnamespace->nspname);
+       selectSourceSchema(tinfo->dobj.namespace->dobj.name);
 
        /* Fetch type specific details */
        /* We assume here that remoteVersion must be at least 70300 */
 
        appendPQExpBuffer(query, "SELECT a.attname, "
-                "pg_catalog.format_type(a.atttypid, a.atttypmod) as atttypdefn "
-                                 "FROM pg_catalog.pg_type t, pg_catalog.pg_attribute a "
-                                         "WHERE t.oid = '%s'::pg_catalog.oid "
+                        "pg_catalog.format_type(a.atttypid, a.atttypmod) as atttypdefn "
+                                         "FROM pg_catalog.pg_type t, pg_catalog.pg_attribute a "
+                                         "WHERE t.oid = '%u'::pg_catalog.oid "
                                          "AND a.attrelid = t.typrelid "
                                          "AND NOT a.attisdropped "
                                          "ORDER BY a.attnum ",
-                                         tinfo->oid);
+                                         tinfo->dobj.catId.oid);
 
        res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "query to obtain data type information failed: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        /* Expecting at least a single result */
        ntups = PQntuples(res);
@@ -3389,7 +5494,7 @@ dumpOneCompositeType(Archive *fout, TypeInfo *tinfo)
        i_atttypdefn = PQfnumber(res, "atttypdefn");
 
        appendPQExpBuffer(q, "CREATE TYPE %s AS (",
-                                         fmtId(tinfo->typname));
+                                         fmtId(tinfo->dobj.name));
 
        for (i = 0; i < ntups; i++)
        {
@@ -3406,26 +5511,30 @@ dumpOneCompositeType(Archive *fout, TypeInfo *tinfo)
        appendPQExpBuffer(q, "\n);\n");
 
        /*
-        * DROP must be fully qualified in case same name appears in
-        * pg_catalog
+        * DROP must be fully qualified in case same name appears in pg_catalog
         */
        appendPQExpBuffer(delq, "DROP TYPE %s.",
-                                         fmtId(tinfo->typnamespace->nspname));
+                                         fmtId(tinfo->dobj.namespace->dobj.name));
        appendPQExpBuffer(delq, "%s;\n",
-                                         fmtId(tinfo->typname));
+                                         fmtId(tinfo->dobj.name));
+
+       ArchiveEntry(fout, tinfo->dobj.catId, tinfo->dobj.dumpId,
+                                tinfo->dobj.name,
+                                tinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                tinfo->rolname, false,
+                                "TYPE", q->data, delq->data, NULL,
+                                tinfo->dobj.dependencies, tinfo->dobj.nDeps,
+                                NULL, NULL);
 
-       ArchiveEntry(fout, tinfo->oid, tinfo->typname,
-                                tinfo->typnamespace->nspname,
-                                tinfo->usename, "TYPE", NULL,
-                                q->data, delq->data, NULL, NULL, NULL);
 
        /* Dump Type Comments */
        resetPQExpBuffer(q);
 
-       appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo->typname));
+       appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo->dobj.name));
        dumpComment(fout, q->data,
-                               tinfo->typnamespace->nspname, tinfo->usename,
-                               tinfo->oid, "pg_type", 0, NULL);
+                               tinfo->dobj.namespace->dobj.name, tinfo->rolname,
+                               tinfo->dobj.catId, 0, tinfo->dobj.dumpId);
 
        PQclear(res);
        destroyPQExpBuffer(q);
@@ -3434,228 +5543,259 @@ dumpOneCompositeType(Archive *fout, TypeInfo *tinfo)
 }
 
 /*
- * dumpTypes
- *       writes out to fout the queries to recreate all the user-defined types
+ * dumpShellType
+ *       writes out to fout the queries to create a shell type
+ *
+ * We dump a shell definition in advance of the I/O functions for the type.
  */
-void
-dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
-                 TypeInfo *tinfo, int numTypes)
+static void
+dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
 {
-       int                     i;
+       PQExpBuffer q;
 
-       for (i = 0; i < numTypes; i++)
-       {
-               /* Dump only types in dumpable namespaces */
-               if (!tinfo[i].typnamespace->dump)
-                       continue;
+       /* Skip if not to be dumped */
+       if (!stinfo->dobj.dump || dataOnly)
+               return;
 
-               /* skip complex types, except for standalone composite types */
-               if (atooid(tinfo[i].typrelid) != 0 && tinfo[i].typrelkind != 'c')
-                       continue;
+       q = createPQExpBuffer();
 
-               /* skip undefined placeholder types */
-               if (!tinfo[i].isDefined)
-                       continue;
+       /*
+        * Note the lack of a DROP command for the shell type; any required DROP
+        * is driven off the base type entry, instead.  This interacts with
+        * _printTocEntry()'s use of the presence of a DROP command to decide
+        * whether an entry needs an ALTER OWNER command.  We don't want to
+        * alter the shell type's owner immediately on creation; that should
+        * happen only after it's filled in, otherwise the backend complains.
+        */
 
-               /* skip all array types that start w/ underscore */
-               if ((tinfo[i].typname[0] == '_') &&
-                       atooid(tinfo[i].typelem) != 0)
-                       continue;
+       appendPQExpBuffer(q, "CREATE TYPE %s;\n",
+                                         fmtId(stinfo->dobj.name));
 
-               /* 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]);
-               else if (tinfo[i].typtype == 'c')
-                       dumpOneCompositeType(fout, &tinfo[i]);
-       }
+       ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId,
+                                stinfo->dobj.name,
+                                stinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                stinfo->baseType->rolname, false,
+                                "SHELL TYPE", q->data, "", NULL,
+                                stinfo->dobj.dependencies, stinfo->dobj.nDeps,
+                                NULL, NULL);
+
+       destroyPQExpBuffer(q);
 }
 
 /*
- * dumpProcLangs
- *               writes out to fout the queries to recreate user-defined procedural languages
+ * Determine whether we want to dump definitions for procedural languages.
+ * Since the languages themselves don't have schemas, we can't rely on
+ * the normal schema-based selection mechanism.  We choose to dump them
+ * whenever neither --schema nor --table was given.  (Before 8.1, we used
+ * the dump flag of the PL's call handler function, but in 8.1 this will
+ * probably always be false since call handlers are created in pg_catalog.)
+ *
+ * For some backwards compatibility with the older behavior, we forcibly
+ * dump a PL if its handler function (and validator if any) are in a
+ * dumpable namespace. That case is not checked here.
  */
-void
-dumpProcLangs(Archive *fout, FuncInfo finfo[], int numFuncs)
+static bool
+shouldDumpProcLangs(void)
 {
-       PGresult   *res;
-       PQExpBuffer query = createPQExpBuffer();
-       PQExpBuffer defqry = createPQExpBuffer();
-       PQExpBuffer delqry = createPQExpBuffer();
-       int                     ntups;
-       int                     i_oid;
-       int                     i_lanname;
-       int                     i_lanpltrusted;
-       int                     i_lanplcallfoid;
-       int                     i_lanvalidator = -1;
-       int                     i_lanacl = -1;
-       char       *lanoid;
-       char       *lanname;
-       char       *lanacl;
-       const char *lanplcallfoid;
-       const char *lanvalidator;
-       const char *((*deps)[]);
-       int                     depIdx;
-       int                     i,
-                               fidx,
-                               vidx = -1;
+       if (matchingTables != NULL || matchingSchemas != NULL)
+               return false;
+       /* And they're schema not data */
+       if (dataOnly)
+               return false;
+       return true;
+}
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema("pg_catalog");
+/*
+ * dumpProcLang
+ *               writes out to fout the queries to recreate a user-defined
+ *               procedural language
+ */
+static void
+dumpProcLang(Archive *fout, ProcLangInfo *plang)
+{
+       PQExpBuffer defqry;
+       PQExpBuffer delqry;
+       bool            useParams;
+       char       *qlanname;
+       char       *lanschema;
+       FuncInfo   *funcInfo;
+       FuncInfo   *validatorInfo = NULL;
 
-       appendPQExpBuffer(query, "SELECT oid, * FROM pg_language "
-                                         "WHERE lanispl "
-                                         "ORDER BY oid");
-       res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "query to obtain list of procedural languages failed: %s",
-                                 PQerrorMessage(g_conn));
-               exit_nicely();
-       }
-       ntups = PQntuples(res);
+       if (dataOnly)
+               return;
 
-       i_lanname = PQfnumber(res, "lanname");
-       i_lanpltrusted = PQfnumber(res, "lanpltrusted");
-       i_lanplcallfoid = PQfnumber(res, "lanplcallfoid");
-       i_oid = PQfnumber(res, "oid");
-       if (fout->remoteVersion >= 70300)
-       {
-               i_lanvalidator = PQfnumber(res, "lanvalidator");
-               i_lanacl = PQfnumber(res, "lanacl");
-       }
+       /*
+        * Try to find the support function(s).  It is not an error if we don't
+        * find them --- if the functions are in the pg_catalog schema, as is
+        * standard in 8.1 and up, then we won't have loaded them. (In this case
+        * we will emit a parameterless CREATE LANGUAGE command, which will
+        * require PL template knowledge in the backend to reload.)
+        */
 
-       for (i = 0; i < ntups; i++)
-       {
-               lanoid = PQgetvalue(res, i, i_oid);
-               lanplcallfoid = PQgetvalue(res, i, i_lanplcallfoid);
-               lanname = PQgetvalue(res, i, i_lanname);
-               if (fout->remoteVersion >= 70300)
-               {
-                       lanvalidator = PQgetvalue(res, i, i_lanvalidator);
-                       lanacl = PQgetvalue(res, i, i_lanacl);
-               }
-               else
-               {
-                       lanvalidator = "0";
-                       lanacl = "{=U}";
-               }
+       funcInfo = findFuncByOid(plang->lanplcallfoid);
+       if (funcInfo != NULL && !funcInfo->dobj.dump)
+               funcInfo = NULL;                /* treat not-dumped same as not-found */
 
-               fidx = findFuncByOid(finfo, numFuncs, lanplcallfoid);
-               if (fidx < 0)
-               {
-                       write_msg(NULL, "handler procedure for procedural language \"%s\" not found\n",
-                                         lanname);
-                       exit_nicely();
-               }
+       if (OidIsValid(plang->lanvalidator))
+       {
+               validatorInfo = findFuncByOid(plang->lanvalidator);
+               if (validatorInfo != NULL && !validatorInfo->dobj.dump)
+                       validatorInfo = NULL;
+       }
 
-               if (strcmp(lanvalidator, "0") != 0)
-               {
-                       vidx = findFuncByOid(finfo, numFuncs, lanvalidator);
-                       if (vidx < 0)
-                       {
-                               write_msg(NULL, "validator procedure for procedural language \"%s\" not found\n",
-                                                 lanname);
-                               exit_nicely();
-                       }
-               }
+       /*
+        * If the functions are dumpable then emit a traditional CREATE LANGUAGE
+        * with parameters.  Otherwise, dump only if shouldDumpProcLangs() says to
+        * dump it.
+        */
+       useParams = (funcInfo != NULL &&
+                                (validatorInfo != NULL || !OidIsValid(plang->lanvalidator)));
 
-               /*
-                * 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;
+       if (!useParams && !shouldDumpProcLangs())
+               return;
 
-               resetPQExpBuffer(defqry);
-               resetPQExpBuffer(delqry);
+       defqry = createPQExpBuffer();
+       delqry = createPQExpBuffer();
 
-               /* Make a dependency to ensure function is dumped first */
-               deps = malloc(sizeof(char *) * 10);
-               depIdx = 0;
+       qlanname = strdup(fmtId(plang->dobj.name));
 
-               (*deps)[depIdx++] = strdup(lanplcallfoid);
+       /*
+        * If dumping a HANDLER clause, treat the language as being in the handler
+        * function's schema; this avoids cluttering the HANDLER clause. Otherwise
+        * it doesn't really have a schema.
+        */
+       if (useParams)
+               lanschema = funcInfo->dobj.namespace->dobj.name;
+       else
+               lanschema = NULL;
 
-               appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n",
-                                                 fmtId(lanname));
+       appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n",
+                                         qlanname);
 
-               appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE %s",
-                                                 (PQgetvalue(res, i, i_lanpltrusted)[0] == 't') ?
-                                                 "TRUSTED " : "",
-                                                 fmtId(lanname));
+       appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE %s",
+                                         (useParams && plang->lanpltrusted) ? "TRUSTED " : "",
+                                         qlanname);
+       if (useParams)
+       {
                appendPQExpBuffer(defqry, " HANDLER %s",
-                                                 fmtId(finfo[fidx].proname));
-               if (strcmp(lanvalidator, "0") != 0)
+                                                 fmtId(funcInfo->dobj.name));
+               if (OidIsValid(plang->lanvalidator))
                {
                        appendPQExpBuffer(defqry, " VALIDATOR ");
                        /* Cope with possibility that validator is in different schema */
-                       if (finfo[vidx].pronamespace != finfo[fidx].pronamespace)
+                       if (validatorInfo->dobj.namespace != funcInfo->dobj.namespace)
                                appendPQExpBuffer(defqry, "%s.",
-                                                          fmtId(finfo[vidx].pronamespace->nspname));
+                                                       fmtId(validatorInfo->dobj.namespace->dobj.name));
                        appendPQExpBuffer(defqry, "%s",
-                                                         fmtId(finfo[vidx].proname));
-                       (*deps)[depIdx++] = strdup(lanvalidator);
+                                                         fmtId(validatorInfo->dobj.name));
                }
-               appendPQExpBuffer(defqry, ";\n");
-
-               (*deps)[depIdx++] = NULL;               /* End of List */
+       }
+       appendPQExpBuffer(defqry, ";\n");
 
-               ArchiveEntry(fout, lanoid, lanname,
-                                        finfo[fidx].pronamespace->nspname, "",
-                                        "PROCEDURAL LANGUAGE", deps,
-                                        defqry->data, delqry->data, NULL, NULL, NULL);
+       ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
+                                plang->dobj.name,
+                                lanschema, NULL, plang->lanowner,
+                                false, "PROCEDURAL LANGUAGE",
+                                defqry->data, delqry->data, NULL,
+                                plang->dobj.dependencies, plang->dobj.nDeps,
+                                NULL, NULL);
 
-               if (!aclsSkip)
-               {
-                       char       *tmp = strdup(fmtId(lanname));
+       /* Dump Proc Lang Comments */
+       resetPQExpBuffer(defqry);
+       appendPQExpBuffer(defqry, "LANGUAGE %s", qlanname);
+       dumpComment(fout, defqry->data,
+                               NULL, "",
+                               plang->dobj.catId, 0, plang->dobj.dumpId);
 
-                       dumpACL(fout, "ACL LANGUAGE", tmp, lanname,
-                                       finfo[fidx].pronamespace->nspname,
-                                       NULL, lanacl, lanoid);
-                       free(tmp);
-               }
-       }
+       if (plang->lanpltrusted)
+               dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
+                               qlanname, plang->dobj.name,
+                               lanschema,
+                               plang->lanowner, plang->lanacl);
 
-       PQclear(res);
+       free(qlanname);
 
-       destroyPQExpBuffer(query);
        destroyPQExpBuffer(defqry);
        destroyPQExpBuffer(delqry);
 }
 
 /*
- * dumpFuncs
- *       writes out to fout the queries to recreate all the user-defined functions
+ * format_function_arguments: generate function name and argument list
+ *
+ * The argument type names are qualified if needed.  The function name
+ * is never qualified.
+ *
+ * Any or all of allargtypes, argmodes, argnames may be NULL.
  */
-void
-dumpFuncs(Archive *fout, FuncInfo finfo[], int numFuncs)
+static char *
+format_function_arguments(FuncInfo *finfo, int nallargs,
+                                                 char **allargtypes,
+                                                 char **argmodes,
+                                                 char **argnames)
 {
-       int                     i;
+       PQExpBufferData fn;
+       int                     j;
 
-       for (i = 0; i < numFuncs; i++)
+       initPQExpBuffer(&fn);
+       appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name));
+       for (j = 0; j < nallargs; j++)
        {
-               /* Dump only funcs in dumpable namespaces */
-               if (!finfo[i].pronamespace->dump)
-                       continue;
+               Oid                     typid;
+               char       *typname;
+               const char *argmode;
+               const char *argname;
+
+               typid = allargtypes ? atooid(allargtypes[j]) : finfo->argtypes[j];
+               typname = getFormattedTypeName(typid, zeroAsOpaque);
+
+               if (argmodes)
+               {
+                       switch (argmodes[j][0])
+                       {
+                               case 'i':
+                                       argmode = "";
+                                       break;
+                               case 'o':
+                                       argmode = "OUT ";
+                                       break;
+                               case 'b':
+                                       argmode = "INOUT ";
+                                       break;
+                               default:
+                                       write_msg(NULL, "WARNING: bogus value in proargmodes array\n");
+                                       argmode = "";
+                                       break;
+                       }
+               }
+               else
+                       argmode = "";
+
+               argname = argnames ? argnames[j] : (char *) NULL;
+               if (argname && argname[0] == '\0')
+                       argname = NULL;
 
-               dumpOneFunc(fout, &finfo[i]);
-               if (!aclsSkip)
-                       dumpFuncACL(fout, &finfo[i]);
+               appendPQExpBuffer(&fn, "%s%s%s%s%s",
+                                                 (j > 0) ? ", " : "",
+                                                 argmode,
+                                                 argname ? fmtId(argname) : "",
+                                                 argname ? " " : "",
+                                                 typname);
+               free(typname);
        }
+       appendPQExpBuffer(&fn, ")");
+       return fn.data;
 }
 
 /*
  * format_function_signature: generate function name and argument list
  *
- * The argument type names are qualified if needed.  The function name
- * is never qualified.
+ * This is like format_function_arguments except that only a minimal
+ * list of input argument types is generated; this is sufficient to
+ * reference the function, but not to define it.
+ *
+ * If honor_quotes is false then the function name is never quoted.
+ * This is appropriate for use in TOC tags, but not in SQL commands.
  */
 static char *
 format_function_signature(FuncInfo *finfo, bool honor_quotes)
@@ -3665,14 +5805,15 @@ format_function_signature(FuncInfo *finfo, bool honor_quotes)
 
        initPQExpBuffer(&fn);
        if (honor_quotes)
-               appendPQExpBuffer(&fn, "%s(", fmtId(finfo->proname));
+               appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name));
        else
-               appendPQExpBuffer(&fn, "%s(", finfo->proname);
+               appendPQExpBuffer(&fn, "%s(", finfo->dobj.name);
        for (j = 0; j < finfo->nargs; j++)
        {
                char       *typname;
 
                typname = getFormattedTypeName(finfo->argtypes[j], zeroAsOpaque);
+
                appendPQExpBuffer(&fn, "%s%s",
                                                  (j > 0) ? ", " : "",
                                                  typname);
@@ -3683,103 +5824,120 @@ format_function_signature(FuncInfo *finfo, bool honor_quotes)
 }
 
 
-static void
-dumpFuncACL(Archive *fout, FuncInfo *finfo)
-{
-       char       *funcsig,
-                          *funcsig_tag;
-
-       funcsig = format_function_signature(finfo, true);
-       funcsig_tag = format_function_signature(finfo, false);
-       dumpACL(fout, "FUNCTION", funcsig, funcsig_tag,
-                       finfo->pronamespace->nspname,
-                       finfo->usename, finfo->proacl, finfo->oid);
-       free(funcsig);
-       free(funcsig_tag);
-}
-
-
 /*
- * dumpOneFunc:
- *       dump out only one function
+ * dumpFunc:
+ *       dump out one function
  */
 static void
-dumpOneFunc(Archive *fout, FuncInfo *finfo)
+dumpFunc(Archive *fout, FuncInfo *finfo)
 {
-       PQExpBuffer query = createPQExpBuffer();
-       PQExpBuffer q = createPQExpBuffer();
-       PQExpBuffer delqry = createPQExpBuffer();
-       PQExpBuffer asPart = createPQExpBuffer();
-       PGresult   *res = NULL;
-       char       *funcsig = NULL;
-       char       *funcsig_tag = NULL;
+       PQExpBuffer query;
+       PQExpBuffer q;
+       PQExpBuffer delqry;
+       PQExpBuffer asPart;
+       PGresult   *res;
+       char       *funcsig;
+       char       *funcsig_tag;
        int                     ntups;
        char       *proretset;
        char       *prosrc;
        char       *probin;
+       char       *proallargtypes;
+       char       *proargmodes;
+       char       *proargnames;
        char       *provolatile;
        char       *proisstrict;
        char       *prosecdef;
        char       *lanname;
        char       *rettypename;
-       char       *funcproclang;       /* Boolean : is this function a PLang
-                                                                * handler ? */
+       int                     nallargs;
+       char      **allargtypes = NULL;
+       char      **argmodes = NULL;
+       char      **argnames = NULL;
 
-       if (finfo->dumped)
-               goto done;
+       /* Skip if not to be dumped */
+       if (!finfo->dobj.dump || dataOnly)
+               return;
 
-       finfo->dumped = true;
+       query = createPQExpBuffer();
+       q = createPQExpBuffer();
+       delqry = createPQExpBuffer();
+       asPart = createPQExpBuffer();
 
        /* Set proper schema search path so type references list correctly */
-       selectSourceSchema(finfo->pronamespace->nspname);
+       selectSourceSchema(finfo->dobj.namespace->dobj.name);
 
        /* Fetch function-specific details */
-       if (g_fout->remoteVersion >= 70300)
+       if (g_fout->remoteVersion >= 80100)
+       {
+               appendPQExpBuffer(query,
+                                                 "SELECT proretset, prosrc, probin, "
+                                                 "proallargtypes, proargmodes, proargnames, "
+                                                 "provolatile, proisstrict, prosecdef, "
+                                                 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
+                                                 "FROM pg_catalog.pg_proc "
+                                                 "WHERE oid = '%u'::pg_catalog.oid",
+                                                 finfo->dobj.catId.oid);
+       }
+       else if (g_fout->remoteVersion >= 80000)
+       {
+               appendPQExpBuffer(query,
+                                                 "SELECT proretset, prosrc, probin, "
+                                                 "null as proallargtypes, "
+                                                 "null as proargmodes, "
+                                                 "proargnames, "
+                                                 "provolatile, proisstrict, prosecdef, "
+                                                 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
+                                                 "FROM pg_catalog.pg_proc "
+                                                 "WHERE oid = '%u'::pg_catalog.oid",
+                                                 finfo->dobj.catId.oid);
+       }
+       else if (g_fout->remoteVersion >= 70300)
        {
                appendPQExpBuffer(query,
                                                  "SELECT proretset, prosrc, probin, "
+                                                 "null as proallargtypes, "
+                                                 "null as proargmodes, "
+                                                 "null as proargnames, "
                                                  "provolatile, proisstrict, prosecdef, "
-                                                 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname, "
-                                                 "exists (SELECT 'x' FROM pg_catalog.pg_language WHERE lanplcallfoid = pg_catalog.pg_proc.oid) as funcproclang "
+                                                 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
                                                  "FROM pg_catalog.pg_proc "
-                                                 "WHERE oid = '%s'::pg_catalog.oid",
-                                                 finfo->oid);
+                                                 "WHERE oid = '%u'::pg_catalog.oid",
+                                                 finfo->dobj.catId.oid);
        }
        else if (g_fout->remoteVersion >= 70100)
        {
                appendPQExpBuffer(query,
                                                  "SELECT proretset, prosrc, probin, "
-                "case when proiscachable then 'i' else 'v' end as provolatile, "
+                                                 "null as proallargtypes, "
+                                                 "null as proargmodes, "
+                                                 "null as proargnames, "
+                        "case when proiscachable then 'i' else 'v' end as provolatile, "
                                                  "proisstrict, "
                                                  "'f'::boolean as prosecdef, "
-                                                 "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname, "
-                                                 "exists (SELECT 'x' FROM pg_language WHERE lanplcallfoid = pg_proc.oid) as funcproclang "
+                 "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
                                                  "FROM pg_proc "
-                                                 "WHERE oid = '%s'::oid",
-                                                 finfo->oid);
+                                                 "WHERE oid = '%u'::oid",
+                                                 finfo->dobj.catId.oid);
        }
        else
        {
                appendPQExpBuffer(query,
                                                  "SELECT proretset, prosrc, probin, "
-                "case when proiscachable then 'i' else 'v' end as provolatile, "
+                                                 "null as proallargtypes, "
+                                                 "null as proargmodes, "
+                                                 "null as proargnames, "
+                        "case when proiscachable then 'i' else 'v' end as provolatile, "
                                                  "'f'::boolean as proisstrict, "
                                                  "'f'::boolean as prosecdef, "
-                                                 "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname, "
-                                                 "exists (SELECT 'x' FROM pg_language WHERE lanplcallfoid = pg_proc.oid) as funcproclang "
+                 "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
                                                  "FROM pg_proc "
-                                                 "WHERE oid = '%s'::oid",
-                                                 finfo->oid);
+                                                 "WHERE oid = '%u'::oid",
+                                                 finfo->dobj.catId.oid);
        }
 
        res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "query to obtain information on function \"%s\" failed: %s",
-                                 finfo->proname, PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        /* Expecting a single result only */
        ntups = PQntuples(res);
@@ -3793,11 +5951,13 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
        proretset = PQgetvalue(res, 0, PQfnumber(res, "proretset"));
        prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc"));
        probin = PQgetvalue(res, 0, PQfnumber(res, "probin"));
+       proallargtypes = PQgetvalue(res, 0, PQfnumber(res, "proallargtypes"));
+       proargmodes = PQgetvalue(res, 0, PQfnumber(res, "proargmodes"));
+       proargnames = PQgetvalue(res, 0, PQfnumber(res, "proargnames"));
        provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
        proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
        prosecdef = PQgetvalue(res, 0, PQfnumber(res, "prosecdef"));
        lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
-       funcproclang = PQgetvalue(res, 0, PQfnumber(res, "funcproclang"));
 
        /*
         * See backend/commands/define.c for details of how the 'AS' clause is
@@ -3806,11 +5966,20 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
        if (strcmp(probin, "-") != 0)
        {
                appendPQExpBuffer(asPart, "AS ");
-               appendStringLiteral(asPart, probin, true);
+               appendStringLiteralAH(asPart, probin, fout);
                if (strcmp(prosrc, "-") != 0)
                {
                        appendPQExpBuffer(asPart, ", ");
-                       appendStringLiteral(asPart, prosrc, false);
+
+                       /*
+                        * where we have bin, use dollar quoting if allowed and src
+                        * contains quote or backslash; else use regular quoting.
+                        */
+                       if (disable_dollar_quoting ||
+                               (strchr(prosrc, '\'') == NULL && strchr(prosrc, '\\') == NULL))
+                               appendStringLiteralAH(asPart, prosrc, fout);
+                       else
+                               appendStringLiteralDQ(asPart, prosrc, NULL);
                }
        }
        else
@@ -3818,19 +5987,69 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
                if (strcmp(prosrc, "-") != 0)
                {
                        appendPQExpBuffer(asPart, "AS ");
-                       appendStringLiteral(asPart, prosrc, false);
+                       /* with no bin, dollar quote src unconditionally if allowed */
+                       if (disable_dollar_quoting)
+                               appendStringLiteralAH(asPart, prosrc, fout);
+                       else
+                               appendStringLiteralDQ(asPart, prosrc, NULL);
+               }
+       }
+
+       nallargs = finfo->nargs;        /* unless we learn different from allargs */
+
+       if (proallargtypes && *proallargtypes)
+       {
+               int                     nitems = 0;
+
+               if (!parsePGArray(proallargtypes, &allargtypes, &nitems) ||
+                       nitems < finfo->nargs)
+               {
+                       write_msg(NULL, "WARNING: could not parse proallargtypes array\n");
+                       if (allargtypes)
+                               free(allargtypes);
+                       allargtypes = NULL;
+               }
+               else
+                       nallargs = nitems;
+       }
+
+       if (proargmodes && *proargmodes)
+       {
+               int                     nitems = 0;
+
+               if (!parsePGArray(proargmodes, &argmodes, &nitems) ||
+                       nitems != nallargs)
+               {
+                       write_msg(NULL, "WARNING: could not parse proargmodes array\n");
+                       if (argmodes)
+                               free(argmodes);
+                       argmodes = NULL;
+               }
+       }
+
+       if (proargnames && *proargnames)
+       {
+               int                     nitems = 0;
+
+               if (!parsePGArray(proargnames, &argnames, &nitems) ||
+                       nitems != nallargs)
+               {
+                       write_msg(NULL, "WARNING: could not parse proargnames array\n");
+                       if (argnames)
+                               free(argnames);
+                       argnames = NULL;
                }
        }
 
-       funcsig = format_function_signature(finfo, true);
+       funcsig = format_function_arguments(finfo, nallargs, allargtypes,
+                                                                               argmodes, argnames);
        funcsig_tag = format_function_signature(finfo, false);
 
        /*
-        * DROP must be fully qualified in case same name appears in
-        * pg_catalog
+        * DROP must be fully qualified in case same name appears in pg_catalog
         */
        appendPQExpBuffer(delqry, "DROP FUNCTION %s.%s;\n",
-                                         fmtId(finfo->pronamespace->nspname),
+                                         fmtId(finfo->dobj.namespace->dobj.name),
                                          funcsig);
 
        rettypename = getFormattedTypeName(finfo->prorettype, zeroAsOpaque);
@@ -3853,7 +6072,7 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
                else if (provolatile[0] != PROVOLATILE_VOLATILE)
                {
                        write_msg(NULL, "unrecognized provolatile value for function \"%s\"\n",
-                                         finfo->proname);
+                                         finfo->dobj.name);
                        exit_nicely();
                }
        }
@@ -3866,21 +6085,27 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
 
        appendPQExpBuffer(q, ";\n");
 
-       ArchiveEntry(fout, finfo->oid, funcsig_tag,
-                                finfo->pronamespace->nspname,
-                                finfo->usename, strcmp(funcproclang, "t") ? "FUNCTION" : "FUNC PROCEDURAL LANGUAGE", NULL,
-                                q->data, delqry->data,
-                                NULL, NULL, NULL);
+       ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
+                                funcsig_tag,
+                                finfo->dobj.namespace->dobj.name,
+                                NULL,
+                                finfo->rolname, false,
+                                "FUNCTION", q->data, delqry->data, NULL,
+                                finfo->dobj.dependencies, finfo->dobj.nDeps,
+                                NULL, NULL);
 
        /* Dump Function Comments */
-
        resetPQExpBuffer(q);
        appendPQExpBuffer(q, "FUNCTION %s", funcsig);
        dumpComment(fout, q->data,
-                               finfo->pronamespace->nspname, finfo->usename,
-                               finfo->oid, "pg_proc", 0, NULL);
+                               finfo->dobj.namespace->dobj.name, finfo->rolname,
+                               finfo->dobj.catId, 0, finfo->dobj.dumpId);
+
+       dumpACL(fout, finfo->dobj.catId, finfo->dobj.dumpId, "FUNCTION",
+                       funcsig, funcsig_tag,
+                       finfo->dobj.namespace->dobj.name,
+                       finfo->rolname, finfo->proacl);
 
-done:
        PQclear(res);
 
        destroyPQExpBuffer(query);
@@ -3889,153 +6114,153 @@ done:
        destroyPQExpBuffer(asPart);
        free(funcsig);
        free(funcsig_tag);
+       if (allargtypes)
+               free(allargtypes);
+       if (argmodes)
+               free(argmodes);
+       if (argnames)
+               free(argnames);
 }
 
 
 /*
- * Dump all casts
+ * Dump a user-defined cast
  */
-void
-dumpCasts(Archive *fout,
-                 FuncInfo *finfo, int numFuncs,
-                 TypeInfo *tinfo, int numTypes)
+static void
+dumpCast(Archive *fout, CastInfo *cast)
 {
-       PGresult   *res;
-       PQExpBuffer query = createPQExpBuffer();
-       PQExpBuffer defqry = createPQExpBuffer();
-       PQExpBuffer delqry = createPQExpBuffer();
-       int                     ntups;
-       int                     i;
-
-       /* Make sure we are in proper schema */
-       selectSourceSchema("pg_catalog");
+       PQExpBuffer defqry;
+       PQExpBuffer delqry;
+       PQExpBuffer castsig;
+       FuncInfo   *funcInfo = NULL;
+       TypeInfo   *sourceInfo;
+       TypeInfo   *targetInfo;
 
-       if (fout->remoteVersion >= 70300)
-               appendPQExpBuffer(query, "SELECT oid, castsource, casttarget, castfunc, castcontext FROM pg_cast ORDER BY 1,2,3;");
-       else
-               appendPQExpBuffer(query, "SELECT p.oid, t1.oid, t2.oid, p.oid, true FROM pg_type t1, pg_type t2, pg_proc p WHERE p.pronargs = 1 AND p.proargtypes[0] = t1.oid AND p.prorettype = t2.oid AND p.proname = t2.typname ORDER BY 1,2,3;");
+       if (dataOnly)
+               return;
 
-       res = PQexec(g_conn, query->data);
-       if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
+       if (OidIsValid(cast->castfunc))
        {
-               write_msg(NULL, "query to obtain list of casts failed: %s",
-                                 PQerrorMessage(g_conn));
-               exit_nicely();
+               funcInfo = findFuncByOid(cast->castfunc);
+               if (funcInfo == NULL)
+                       return;
        }
-       ntups = PQntuples(res);
 
-       for (i = 0; i < ntups; i++)
-       {
-               char       *castoid = PQgetvalue(res, i, 0);
-               char       *castsource = PQgetvalue(res, i, 1);
-               char       *casttarget = PQgetvalue(res, i, 2);
-               char       *castfunc = PQgetvalue(res, i, 3);
-               char       *castcontext = PQgetvalue(res, i, 4);
-               int                     fidx = -1;
-               const char *((*deps)[]);
-
-               if (strcmp(castfunc, "0") != 0)
-                       fidx = findFuncByOid(finfo, numFuncs, castfunc);
-
-               /*
-                * We treat the cast as being in the namespace of the underlying
-                * function.  This doesn't handle binary compatible casts.  Where
-                * should those go?
-                */
-               if (fidx < 0 || !finfo[fidx].pronamespace->dump)
-                       continue;
-
-               /* Make a dependency to ensure function is dumped first */
-               if (fidx >= 0)
-               {
-                       deps = malloc(sizeof(char *) * 2);
-
-                       (*deps)[0] = strdup(castfunc);
-                       (*deps)[1] = NULL;      /* End of List */
-               }
-               else
-                       deps = NULL;
-
-               resetPQExpBuffer(defqry);
-               resetPQExpBuffer(delqry);
+       /*
+        * As per discussion we dump casts if one or more of the underlying
+        * objects (the conversion function and the two data types) are not
+        * builtin AND if all of the non-builtin objects are included in the dump.
+        * Builtin meaning, the namespace name does not start with "pg_".
+        */
+       sourceInfo = findTypeByOid(cast->castsource);
+       targetInfo = findTypeByOid(cast->casttarget);
 
-               appendPQExpBuffer(delqry, "DROP CAST (%s AS %s);\n",
-                                                 getFormattedTypeName(castsource, zeroAsNone),
-                                                 getFormattedTypeName(casttarget, zeroAsNone));
+       if (sourceInfo == NULL || targetInfo == NULL)
+               return;
 
-               appendPQExpBuffer(defqry, "CREATE CAST (%s AS %s) ",
-                                                 getFormattedTypeName(castsource, zeroAsNone),
-                                                 getFormattedTypeName(casttarget, zeroAsNone));
+       /*
+        * Skip this cast if all objects are from pg_
+        */
+       if ((funcInfo == NULL ||
+               strncmp(funcInfo->dobj.namespace->dobj.name, "pg_", 3) == 0) &&
+               strncmp(sourceInfo->dobj.namespace->dobj.name, "pg_", 3) == 0 &&
+               strncmp(targetInfo->dobj.namespace->dobj.name, "pg_", 3) == 0)
+               return;
 
-               if (strcmp(castfunc, "0") == 0)
-                       appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
-               else
-                       appendPQExpBuffer(defqry, "WITH FUNCTION %s",
-                                                 format_function_signature(&finfo[fidx], true));
+       /*
+        * Skip cast if function isn't from pg_ and is not to be dumped.
+        */
+       if (funcInfo &&
+               strncmp(funcInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
+               !funcInfo->dobj.dump)
+               return;
 
-               if (strcmp(castcontext, "a") == 0)
-                       appendPQExpBuffer(defqry, " AS ASSIGNMENT");
-               else if (strcmp(castcontext, "i") == 0)
-                       appendPQExpBuffer(defqry, " AS IMPLICIT");
-               appendPQExpBuffer(defqry, ";\n");
+       /*
+        * Same for the source type
+        */
+       if (strncmp(sourceInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
+               !sourceInfo->dobj.dump)
+               return;
 
-               ArchiveEntry(fout, castoid,
-                                        format_function_signature(&finfo[fidx], false),
-                                        finfo[fidx].pronamespace->nspname, "",
-                                        "CAST", deps,
-                                        defqry->data, delqry->data,
-                                        NULL, NULL, NULL);
-       }
+       /*
+        * and the target type.
+        */
+       if (strncmp(targetInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
+               !targetInfo->dobj.dump)
+               return;
 
-       PQclear(res);
+       /* Make sure we are in proper schema (needed for getFormattedTypeName) */
+       selectSourceSchema("pg_catalog");
 
-       destroyPQExpBuffer(query);
-       destroyPQExpBuffer(defqry);
-       destroyPQExpBuffer(delqry);
-}
+       defqry = createPQExpBuffer();
+       delqry = createPQExpBuffer();
+       castsig = createPQExpBuffer();
 
+       appendPQExpBuffer(delqry, "DROP CAST (%s AS %s);\n",
+                                         getFormattedTypeName(cast->castsource, zeroAsNone),
+                                         getFormattedTypeName(cast->casttarget, zeroAsNone));
 
-/*
- * dumpOprs
- *       writes out to fout the queries to recreate all the user-defined operators
- */
-void
-dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators)
-{
-       int                     i;
+       appendPQExpBuffer(defqry, "CREATE CAST (%s AS %s) ",
+                                         getFormattedTypeName(cast->castsource, zeroAsNone),
+                                         getFormattedTypeName(cast->casttarget, zeroAsNone));
 
-       for (i = 0; i < numOperators; i++)
+       if (!OidIsValid(cast->castfunc))
+               appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
+       else
        {
-               /* Dump only operators in dumpable namespaces */
-               if (!oprinfo[i].oprnamespace->dump)
-                       continue;
-
                /*
-                * some operators are invalid because they were the result of user
-                * defining operators before commutators exist
+                * Always qualify the function name, in case it is not in pg_catalog
+                * schema (format_function_signature won't qualify it).
                 */
-               if (strcmp(oprinfo[i].oprcode, "0") == 0)
-                       continue;
+               appendPQExpBuffer(defqry, "WITH FUNCTION %s.",
+                                                 fmtId(funcInfo->dobj.namespace->dobj.name));
+               appendPQExpBuffer(defqry, "%s",
+                                                 format_function_signature(funcInfo, true));
+       }
+
+       if (cast->castcontext == 'a')
+               appendPQExpBuffer(defqry, " AS ASSIGNMENT");
+       else if (cast->castcontext == 'i')
+               appendPQExpBuffer(defqry, " AS IMPLICIT");
+       appendPQExpBuffer(defqry, ";\n");
+
+       appendPQExpBuffer(castsig, "CAST (%s AS %s)",
+                                         getFormattedTypeName(cast->castsource, zeroAsNone),
+                                         getFormattedTypeName(cast->casttarget, zeroAsNone));
+
+       ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId,
+                                castsig->data,
+                                "pg_catalog", NULL, "",
+                                false, "CAST", defqry->data, delqry->data, NULL,
+                                cast->dobj.dependencies, cast->dobj.nDeps,
+                                NULL, NULL);
+
+       /* Dump Cast Comments */
+       resetPQExpBuffer(defqry);
+       appendPQExpBuffer(defqry, "CAST (%s AS %s)",
+                                         getFormattedTypeName(cast->castsource, zeroAsNone),
+                                         getFormattedTypeName(cast->casttarget, zeroAsNone));
+       dumpComment(fout, defqry->data,
+                               NULL, "",
+                               cast->dobj.catId, 0, cast->dobj.dumpId);
 
-               /* OK, dump it */
-               dumpOneOpr(fout, &oprinfo[i],
-                                  oprinfo, numOperators);
-       }
+       destroyPQExpBuffer(defqry);
+       destroyPQExpBuffer(delqry);
+       destroyPQExpBuffer(castsig);
 }
 
 /*
- * dumpOneOpr
+ * dumpOpr
  *       write out a single operator definition
  */
 static void
-dumpOneOpr(Archive *fout, OprInfo *oprinfo,
-                  OprInfo *g_oprinfo, int numOperators)
+dumpOpr(Archive *fout, OprInfo *oprinfo)
 {
-       PQExpBuffer query = createPQExpBuffer();
-       PQExpBuffer q = createPQExpBuffer();
-       PQExpBuffer delq = createPQExpBuffer();
-       PQExpBuffer oprid = createPQExpBuffer();
-       PQExpBuffer details = createPQExpBuffer();
+       PQExpBuffer query;
+       PQExpBuffer q;
+       PQExpBuffer delq;
+       PQExpBuffer oprid;
+       PQExpBuffer details;
        const char *name;
        PGresult   *res;
        int                     ntups;
@@ -4066,8 +6291,25 @@ dumpOneOpr(Archive *fout, OprInfo *oprinfo,
        char       *oprltcmpop;
        char       *oprgtcmpop;
 
+       /* Skip if not to be dumped */
+       if (!oprinfo->dobj.dump || dataOnly)
+               return;
+
+       /*
+        * some operators are invalid because they were the result of user
+        * defining operators before commutators exist
+        */
+       if (!OidIsValid(oprinfo->oprcode))
+               return;
+
+       query = createPQExpBuffer();
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
+       oprid = createPQExpBuffer();
+       details = createPQExpBuffer();
+
        /* Make sure we are in proper schema so regoperator works correctly */
-       selectSourceSchema(oprinfo->oprnamespace->nspname);
+       selectSourceSchema(oprinfo->dobj.namespace->dobj.name);
 
        if (g_fout->remoteVersion >= 70300)
        {
@@ -4085,22 +6327,22 @@ dumpOneOpr(Archive *fout, OprInfo *oprinfo,
                                                  "oprltcmpop::pg_catalog.regoperator, "
                                                  "oprgtcmpop::pg_catalog.regoperator "
                                                  "from pg_catalog.pg_operator "
-                                                 "where oid = '%s'::pg_catalog.oid",
-                                                 oprinfo->oid);
+                                                 "where oid = '%u'::pg_catalog.oid",
+                                                 oprinfo->dobj.catId.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, "
+                                                 "ELSE format_type(oprleft, NULL) END as oprleft, "
                                                  "CASE WHEN oprright = 0 THEN '-' "
-                                        "ELSE format_type(oprright, NULL) END as oprright, "
+                                                 "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);
+                                                 "where oid = '%u'::oid",
+                                                 oprinfo->dobj.catId.oid);
        }
        else
        {
@@ -4113,17 +6355,12 @@ dumpOneOpr(Archive *fout, OprInfo *oprinfo,
                                                  "oprcanhash, oprlsortop, oprrsortop, "
                                                  "0 as oprltcmpop, 0 as oprgtcmpop "
                                                  "from pg_operator "
-                                                 "where oid = '%s'::oid",
-                                                 oprinfo->oid);
+                                                 "where oid = '%u'::oid",
+                                                 oprinfo->dobj.catId.oid);
        }
 
        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();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        /* Expecting a single result only */
        ntups = PQntuples(res);
@@ -4166,7 +6403,7 @@ dumpOneOpr(Archive *fout, OprInfo *oprinfo,
                                          convertRegProcReference(oprcode));
 
        appendPQExpBuffer(oprid, "%s (",
-                                         oprinfo->oprname);
+                                         oprinfo->dobj.name);
 
        /*
         * right unary means there's a left arg and left unary means there's a
@@ -4198,11 +6435,11 @@ dumpOneOpr(Archive *fout, OprInfo *oprinfo,
        else
                appendPQExpBuffer(oprid, ", NONE)");
 
-       name = convertOperatorReference(oprcom, g_oprinfo, numOperators);
+       name = convertOperatorReference(oprcom);
        if (name)
                appendPQExpBuffer(details, ",\n    COMMUTATOR = %s", name);
 
-       name = convertOperatorReference(oprnegate, g_oprinfo, numOperators);
+       name = convertOperatorReference(oprnegate);
        if (name)
                appendPQExpBuffer(details, ",\n    NEGATOR = %s", name);
 
@@ -4217,46 +6454,47 @@ dumpOneOpr(Archive *fout, OprInfo *oprinfo,
        if (name)
                appendPQExpBuffer(details, ",\n    JOIN = %s", name);
 
-       name = convertOperatorReference(oprlsortop, g_oprinfo, numOperators);
+       name = convertOperatorReference(oprlsortop);
        if (name)
                appendPQExpBuffer(details, ",\n    SORT1 = %s", name);
 
-       name = convertOperatorReference(oprrsortop, g_oprinfo, numOperators);
+       name = convertOperatorReference(oprrsortop);
        if (name)
                appendPQExpBuffer(details, ",\n    SORT2 = %s", name);
 
-       name = convertOperatorReference(oprltcmpop, g_oprinfo, numOperators);
+       name = convertOperatorReference(oprltcmpop);
        if (name)
                appendPQExpBuffer(details, ",\n    LTCMP = %s", name);
 
-       name = convertOperatorReference(oprgtcmpop, g_oprinfo, numOperators);
+       name = convertOperatorReference(oprgtcmpop);
        if (name)
                appendPQExpBuffer(details, ",\n    GTCMP = %s", name);
 
        /*
-        * DROP must be fully qualified in case same name appears in
-        * pg_catalog
+        * DROP must be fully qualified in case same name appears in pg_catalog
         */
        appendPQExpBuffer(delq, "DROP OPERATOR %s.%s;\n",
-                                         fmtId(oprinfo->oprnamespace->nspname),
+                                         fmtId(oprinfo->dobj.namespace->dobj.name),
                                          oprid->data);
 
        appendPQExpBuffer(q, "CREATE OPERATOR %s (\n%s\n);\n",
-                                         oprinfo->oprname, details->data);
+                                         oprinfo->dobj.name, details->data);
 
-       ArchiveEntry(fout, oprinfo->oid, oprinfo->oprname,
-                                oprinfo->oprnamespace->nspname, oprinfo->usename,
-                                "OPERATOR", NULL,
-                                q->data, delq->data,
-                                NULL, NULL, NULL);
+       ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId,
+                                oprinfo->dobj.name,
+                                oprinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                oprinfo->rolname,
+                                false, "OPERATOR", q->data, delq->data, NULL,
+                                oprinfo->dobj.dependencies, oprinfo->dobj.nDeps,
+                                NULL, NULL);
 
        /* Dump Operator Comments */
-
        resetPQExpBuffer(q);
        appendPQExpBuffer(q, "OPERATOR %s", oprid->data);
        dumpComment(fout, q->data,
-                               oprinfo->oprnamespace->nspname, oprinfo->usename,
-                               oprinfo->oid, "pg_operator", 0, NULL);
+                               oprinfo->dobj.namespace->dobj.name, oprinfo->rolname,
+                               oprinfo->dobj.catId, 0, oprinfo->dobj.dumpId);
 
        PQclear(res);
 
@@ -4313,15 +6551,15 @@ convertRegProcReference(const char *proc)
  *
  * 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.
+ * In 7.3 and up the input is a REGOPERATOR display; we have to strip the
+ * argument-types part, and add OPERATOR() decoration if the name is
+ * schema-qualified.  In older 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)
+convertOperatorReference(const char *opr)
 {
-       char       *name;
+       OprInfo    *oprInfo;
 
        /* In all cases "0" means a null reference */
        if (strcmp(opr, "0") == 0)
@@ -4329,64 +6567,57 @@ convertOperatorReference(const char *opr,
 
        if (g_fout->remoteVersion >= 70300)
        {
-               char       *paren;
+               char       *name;
+               char       *oname;
+               char       *ptr;
                bool            inquote;
+               bool            sawdot;
 
                name = strdup(opr);
-               /* find non-double-quoted left paren */
+               /* find non-double-quoted left paren, and check for non-quoted dot */
                inquote = false;
-               for (paren = name; *paren; paren++)
+               sawdot = false;
+               for (ptr = name; *ptr; ptr++)
                {
-                       if (*paren == '(' && !inquote)
+                       if (*ptr == '"')
+                               inquote = !inquote;
+                       else if (*ptr == '.' && !inquote)
+                               sawdot = true;
+                       else if (*ptr == '(' && !inquote)
                        {
-                               *paren = '\0';
+                               *ptr = '\0';
                                break;
                        }
-                       if (*paren == '"')
-                               inquote = !inquote;
                }
-               return name;
+               /* If not schema-qualified, don't need to add OPERATOR() */
+               if (!sawdot)
+                       return name;
+               oname = malloc(strlen(name) + 11);
+               sprintf(oname, "OPERATOR(%s)", name);
+               free(name);
+               return oname;
        }
 
-       name = findOprByOid(g_oprinfo, numOperators, opr);
-       if (name == NULL)
+       oprInfo = findOprByOid(atooid(opr));
+       if (oprInfo == NULL)
+       {
                write_msg(NULL, "WARNING: could not find operator with OID %s\n",
                                  opr);
-       return name;
-}
-
-
-/*
- * dumpOpclasses
- *       writes out to fout the queries to recreate all the user-defined
- *       operator classes
- */
-void
-dumpOpclasses(Archive *fout, OpclassInfo *opcinfo, int numOpclasses)
-{
-       int                     i;
-
-       for (i = 0; i < numOpclasses; i++)
-       {
-               /* Dump only opclasses in dumpable namespaces */
-               if (!opcinfo[i].opcnamespace->dump)
-                       continue;
-
-               /* OK, dump it */
-               dumpOneOpclass(fout, &opcinfo[i]);
+               return NULL;
        }
+       return oprInfo->dobj.name;
 }
 
 /*
- * dumpOneOpclass
+ * dumpOpclass
  *       write out a single operator class definition
  */
 static void
-dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo)
+dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
 {
-       PQExpBuffer query = createPQExpBuffer();
-       PQExpBuffer q = createPQExpBuffer();
-       PQExpBuffer delq = createPQExpBuffer();
+       PQExpBuffer query;
+       PQExpBuffer q;
+       PQExpBuffer delq;
        PGresult   *res;
        int                     ntups;
        int                     i_opcintype;
@@ -4410,6 +6641,10 @@ dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo)
        bool            needComma;
        int                     i;
 
+       /* Skip if not to be dumped */
+       if (!opcinfo->dobj.dump || dataOnly)
+               return;
+
        /*
         * XXX currently we do not implement dumping of operator classes from
         * pre-7.3 databases.  This could be done but it seems not worth the
@@ -4418,25 +6653,24 @@ dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo)
        if (g_fout->remoteVersion < 70300)
                return;
 
+       query = createPQExpBuffer();
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
+
        /* Make sure we are in proper schema so regoperator works correctly */
-       selectSourceSchema(opcinfo->opcnamespace->nspname);
+       selectSourceSchema(opcinfo->dobj.namespace->dobj.name);
 
        /* Get additional fields from the pg_opclass row */
        appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
                                          "opckeytype::pg_catalog.regtype, "
                                          "opcdefault, "
-       "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
+          "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
                                          "FROM pg_catalog.pg_opclass "
-                                         "WHERE oid = '%s'::pg_catalog.oid",
-                                         opcinfo->oid);
+                                         "WHERE oid = '%u'::pg_catalog.oid",
+                                         opcinfo->dobj.catId.oid);
 
        res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "query to obtain operator class details failed: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        /* Expecting a single result only */
        ntups = PQntuples(res);
@@ -4455,22 +6689,22 @@ dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo)
        opcintype = PQgetvalue(res, 0, i_opcintype);
        opckeytype = PQgetvalue(res, 0, i_opckeytype);
        opcdefault = PQgetvalue(res, 0, i_opcdefault);
-       amname = PQgetvalue(res, 0, i_amname);
+       /* amname will still be needed after we PQclear res */
+       amname = strdup(PQgetvalue(res, 0, i_amname));
 
        /*
-        * DROP must be fully qualified in case same name appears in
-        * pg_catalog
+        * DROP must be fully qualified in case same name appears in pg_catalog
         */
        appendPQExpBuffer(delq, "DROP OPERATOR CLASS %s",
-                                         fmtId(opcinfo->opcnamespace->nspname));
+                                         fmtId(opcinfo->dobj.namespace->dobj.name));
        appendPQExpBuffer(delq, ".%s",
-                                         fmtId(opcinfo->opcname));
+                                         fmtId(opcinfo->dobj.name));
        appendPQExpBuffer(delq, " USING %s;\n",
                                          fmtId(amname));
 
        /* Build the fixed portion of the CREATE command */
        appendPQExpBuffer(q, "CREATE OPERATOR CLASS %s\n    ",
-                                         fmtId(opcinfo->opcname));
+                                         fmtId(opcinfo->dobj.name));
        if (strcmp(opcdefault, "t") == 0)
                appendPQExpBuffer(q, "DEFAULT ");
        appendPQExpBuffer(q, "FOR TYPE %s USING %s AS\n    ",
@@ -4496,17 +6730,12 @@ dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo)
        appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
                                          "amopopr::pg_catalog.regoperator "
                                          "FROM pg_catalog.pg_amop "
-                                         "WHERE amopclaid = '%s'::pg_catalog.oid "
+                                         "WHERE amopclaid = '%u'::pg_catalog.oid "
                                          "ORDER BY amopstrategy",
-                                         opcinfo->oid);
+                                         opcinfo->dobj.catId.oid);
 
        res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "query to obtain operator class operators failed: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        ntups = PQntuples(res);
 
@@ -4541,17 +6770,12 @@ dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo)
        appendPQExpBuffer(query, "SELECT amprocnum, "
                                          "amproc::pg_catalog.regprocedure "
                                          "FROM pg_catalog.pg_amproc "
-                                         "WHERE amopclaid = '%s'::pg_catalog.oid "
+                                         "WHERE amopclaid = '%u'::pg_catalog.oid "
                                          "ORDER BY amprocnum",
-                                         opcinfo->oid);
+                                         opcinfo->dobj.catId.oid);
 
        res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "query to obtain operator class functions failed: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        ntups = PQntuples(res);
 
@@ -4572,44 +6796,145 @@ dumpOneOpclass(Archive *fout, OpclassInfo *opcinfo)
                needComma = true;
        }
 
-       PQclear(res);
+       PQclear(res);
+
+       appendPQExpBuffer(q, ";\n");
+
+       ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId,
+                                opcinfo->dobj.name,
+                                opcinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                opcinfo->rolname,
+                                false, "OPERATOR CLASS", q->data, delq->data, NULL,
+                                opcinfo->dobj.dependencies, opcinfo->dobj.nDeps,
+                                NULL, NULL);
+
+       /* Dump Operator Class Comments */
+       resetPQExpBuffer(q);
+       appendPQExpBuffer(q, "OPERATOR CLASS %s",
+                                         fmtId(opcinfo->dobj.name));
+       appendPQExpBuffer(q, " USING %s",
+                                         fmtId(amname));
+       dumpComment(fout, q->data,
+                               NULL, opcinfo->rolname,
+                               opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId);
+
+       free(amname);
+       destroyPQExpBuffer(query);
+       destroyPQExpBuffer(q);
+       destroyPQExpBuffer(delq);
+}
+
+/*
+ * dumpConversion
+ *       write out a single conversion definition
+ */
+static void
+dumpConversion(Archive *fout, ConvInfo *convinfo)
+{
+       PQExpBuffer query;
+       PQExpBuffer q;
+       PQExpBuffer delq;
+       PQExpBuffer details;
+       PGresult   *res;
+       int                     ntups;
+       int                     i_conname;
+       int                     i_conforencoding;
+       int                     i_contoencoding;
+       int                     i_conproc;
+       int                     i_condefault;
+       const char *conname;
+       const char *conforencoding;
+       const char *contoencoding;
+       const char *conproc;
+       bool            condefault;
+
+       /* Skip if not to be dumped */
+       if (!convinfo->dobj.dump || dataOnly)
+               return;
+
+       query = createPQExpBuffer();
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
+       details = createPQExpBuffer();
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema(convinfo->dobj.namespace->dobj.name);
+
+       /* Get conversion-specific details */
+       appendPQExpBuffer(query, "SELECT conname, "
+                "pg_catalog.pg_encoding_to_char(conforencoding) AS conforencoding, "
+                  "pg_catalog.pg_encoding_to_char(contoencoding) AS contoencoding, "
+                                         "conproc, condefault "
+                                         "FROM pg_catalog.pg_conversion c "
+                                         "WHERE c.oid = '%u'::pg_catalog.oid",
+                                         convinfo->dobj.catId.oid);
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       /* 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_conname = PQfnumber(res, "conname");
+       i_conforencoding = PQfnumber(res, "conforencoding");
+       i_contoencoding = PQfnumber(res, "contoencoding");
+       i_conproc = PQfnumber(res, "conproc");
+       i_condefault = PQfnumber(res, "condefault");
 
-       appendPQExpBuffer(q, ";\n");
+       conname = PQgetvalue(res, 0, i_conname);
+       conforencoding = PQgetvalue(res, 0, i_conforencoding);
+       contoencoding = PQgetvalue(res, 0, i_contoencoding);
+       conproc = PQgetvalue(res, 0, i_conproc);
+       condefault = (PQgetvalue(res, 0, i_condefault)[0] == 't');
+
+       /*
+        * DROP must be fully qualified in case same name appears in pg_catalog
+        */
+       appendPQExpBuffer(delq, "DROP CONVERSION %s",
+                                         fmtId(convinfo->dobj.namespace->dobj.name));
+       appendPQExpBuffer(delq, ".%s;\n",
+                                         fmtId(convinfo->dobj.name));
+
+       appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
+                                         (condefault) ? "DEFAULT " : "",
+                                         fmtId(convinfo->dobj.name));
+       appendStringLiteralAH(q, conforencoding, fout);
+       appendPQExpBuffer(q, " TO ");
+       appendStringLiteralAH(q, contoencoding, fout);
+       /* regproc is automatically quoted in 7.3 and above */
+       appendPQExpBuffer(q, " FROM %s;\n", conproc);
+
+       ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId,
+                                convinfo->dobj.name,
+                                convinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                convinfo->rolname,
+                                false, "CONVERSION", q->data, delq->data, NULL,
+                                convinfo->dobj.dependencies, convinfo->dobj.nDeps,
+                                NULL, NULL);
+
+       /* Dump Conversion Comments */
+       resetPQExpBuffer(q);
+       appendPQExpBuffer(q, "CONVERSION %s", fmtId(convinfo->dobj.name));
+       dumpComment(fout, q->data,
+                               convinfo->dobj.namespace->dobj.name, convinfo->rolname,
+                               convinfo->dobj.catId, 0, convinfo->dobj.dumpId);
 
-       ArchiveEntry(fout, opcinfo->oid, opcinfo->opcname,
-                                opcinfo->opcnamespace->nspname, opcinfo->usename,
-                                "OPERATOR CLASS", NULL,
-                                q->data, delq->data,
-                                NULL, NULL, NULL);
+       PQclear(res);
 
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(details);
 }
 
-
-/*
- * dumpAggs
- *       writes out to fout the queries to create all the user-defined aggregates
- */
-void
-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]);
-               if (!aclsSkip)
-                       dumpAggACL(fout, &agginfo[i]);
-       }
-}
-
-
 /*
  * format_aggregate_signature: generate aggregate name and argument list
  *
@@ -4620,131 +6945,127 @@ static char *
 format_aggregate_signature(AggInfo *agginfo, Archive *fout, bool honor_quotes)
 {
        PQExpBufferData buf;
+       int                     j;
 
        initPQExpBuffer(&buf);
        if (honor_quotes)
                appendPQExpBuffer(&buf, "%s",
-                                                 fmtId(agginfo->aggname));
+                                                 fmtId(agginfo->aggfn.dobj.name));
        else
-               appendPQExpBuffer(&buf, "%s", agginfo->aggname);
+               appendPQExpBuffer(&buf, "%s", agginfo->aggfn.dobj.name);
 
-       /* If using regtype or format_type, fmtbasetype is already quoted */
-       if (fout->remoteVersion >= 70100)
-       {
-               if (agginfo->anybasetype)
-                       appendPQExpBuffer(&buf, "(*)");
-               else
-                       appendPQExpBuffer(&buf, "(%s)", agginfo->fmtbasetype);
-       }
+       if (agginfo->aggfn.nargs == 0)
+               appendPQExpBuffer(&buf, "(*)");
        else
        {
-               if (agginfo->anybasetype)
-                       appendPQExpBuffer(&buf, "(*)");
-               else
-                       appendPQExpBuffer(&buf, "(%s)",
-                                                         fmtId(agginfo->fmtbasetype));
-       }
-
-       return buf.data;
-}
+               appendPQExpBuffer(&buf, "(");
+               for (j = 0; j < agginfo->aggfn.nargs; j++)
+               {
+                       char       *typname;
 
+                       typname = getFormattedTypeName(agginfo->aggfn.argtypes[j], zeroAsOpaque);
 
-static void
-dumpAggACL(Archive *fout, AggInfo *finfo)
-{
-       char       *aggsig,
-                          *aggsig_tag;
-
-       aggsig = format_aggregate_signature(finfo, fout, true);
-       aggsig_tag = format_aggregate_signature(finfo, fout, false);
-       dumpACL(fout, "FUNCTION", aggsig, aggsig_tag,
-                       finfo->aggnamespace->nspname,
-                       finfo->usename, finfo->aggacl, finfo->oid);
-       free(aggsig);
-       free(aggsig_tag);
+                       appendPQExpBuffer(&buf, "%s%s",
+                                                         (j > 0) ? ", " : "",
+                                                         typname);
+                       free(typname);
+               }
+               appendPQExpBuffer(&buf, ")");
+       }
+       return buf.data;
 }
 
-
 /*
- * dumpOneAgg
+ * dumpAgg
  *       write out a single aggregate definition
  */
 static void
-dumpOneAgg(Archive *fout, AggInfo *agginfo)
+dumpAgg(Archive *fout, AggInfo *agginfo)
 {
-       PQExpBuffer query = createPQExpBuffer();
-       PQExpBuffer q = createPQExpBuffer();
-       PQExpBuffer delq = createPQExpBuffer();
-       PQExpBuffer details = createPQExpBuffer();
+       PQExpBuffer query;
+       PQExpBuffer q;
+       PQExpBuffer delq;
+       PQExpBuffer details;
        char       *aggsig;
        char       *aggsig_tag;
        PGresult   *res;
        int                     ntups;
        int                     i_aggtransfn;
        int                     i_aggfinalfn;
+       int                     i_aggsortop;
        int                     i_aggtranstype;
        int                     i_agginitval;
-       int                     i_anybasetype;
-       int                     i_fmtbasetype;
        int                     i_convertok;
        const char *aggtransfn;
        const char *aggfinalfn;
+       const char *aggsortop;
        const char *aggtranstype;
        const char *agginitval;
        bool            convertok;
 
+       /* Skip if not to be dumped */
+       if (!agginfo->aggfn.dobj.dump || dataOnly)
+               return;
+
+       query = createPQExpBuffer();
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
+       details = createPQExpBuffer();
+
        /* Make sure we are in proper schema */
-       selectSourceSchema(agginfo->aggnamespace->nspname);
+       selectSourceSchema(agginfo->aggfn.dobj.namespace->dobj.name);
 
        /* Get aggregate-specific details */
-       if (g_fout->remoteVersion >= 70300)
+       if (g_fout->remoteVersion >= 80100)
+       {
+               appendPQExpBuffer(query, "SELECT aggtransfn, "
+                                                 "aggfinalfn, aggtranstype::pg_catalog.regtype, "
+                                                 "aggsortop::pg_catalog.regoperator, "
+                                                 "agginitval, "
+                                                 "'t'::boolean as convertok "
+                                         "from pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
+                                                 "where a.aggfnoid = p.oid "
+                                                 "and p.oid = '%u'::pg_catalog.oid",
+                                                 agginfo->aggfn.dobj.catId.oid);
+       }
+       else if (g_fout->remoteVersion >= 70300)
        {
                appendPQExpBuffer(query, "SELECT aggtransfn, "
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
+                                                 "0 as aggsortop, "
                                                  "agginitval, "
-                                                 "proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype as anybasetype, "
-                                       "proargtypes[0]::pg_catalog.regtype as fmtbasetype, "
                                                  "'t'::boolean as convertok "
-                                 "from pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
+                                         "from pg_catalog.pg_aggregate a, pg_catalog.pg_proc p "
                                                  "where a.aggfnoid = p.oid "
-                                                 "and p.oid = '%s'::pg_catalog.oid",
-                                                 agginfo->oid);
+                                                 "and p.oid = '%u'::pg_catalog.oid",
+                                                 agginfo->aggfn.dobj.catId.oid);
        }
        else if (g_fout->remoteVersion >= 70100)
        {
                appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, "
-                                         "format_type(aggtranstype, NULL) as aggtranstype, "
+                                                 "format_type(aggtranstype, NULL) as aggtranstype, "
+                                                 "0 as aggsortop, "
                                                  "agginitval, "
-                                                 "aggbasetype = 0 as anybasetype, "
-                                                 "CASE WHEN aggbasetype = 0 THEN '-' "
-                          "ELSE format_type(aggbasetype, NULL) END as fmtbasetype, "
                                                  "'t'::boolean as convertok "
                                                  "from pg_aggregate "
-                                                 "where oid = '%s'::oid",
-                                                 agginfo->oid);
+                                                 "where oid = '%u'::oid",
+                                                 agginfo->aggfn.dobj.catId.oid);
        }
        else
        {
                appendPQExpBuffer(query, "SELECT aggtransfn1 as aggtransfn, "
                                                  "aggfinalfn, "
                                                  "(select typname from pg_type where oid = aggtranstype1) as aggtranstype, "
+                                                 "0 as aggsortop, "
                                                  "agginitval1 as agginitval, "
-                                                 "aggbasetype = 0 as anybasetype, "
-                                                 "(select typname from pg_type where oid = aggbasetype) as fmtbasetype, "
                                                  "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) as convertok "
                                                  "from pg_aggregate "
-                                                 "where oid = '%s'::oid",
-                                                 agginfo->oid);
+                                                 "where oid = '%u'::oid",
+                                                 agginfo->aggfn.dobj.catId.oid);
        }
 
        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));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        /* Expecting a single result only */
        ntups = PQntuples(res);
@@ -4757,64 +7078,45 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
 
        i_aggtransfn = PQfnumber(res, "aggtransfn");
        i_aggfinalfn = PQfnumber(res, "aggfinalfn");
+       i_aggsortop = PQfnumber(res, "aggsortop");
        i_aggtranstype = PQfnumber(res, "aggtranstype");
        i_agginitval = PQfnumber(res, "agginitval");
-       i_anybasetype = PQfnumber(res, "anybasetype");
-       i_fmtbasetype = PQfnumber(res, "fmtbasetype");
        i_convertok = PQfnumber(res, "convertok");
 
        aggtransfn = PQgetvalue(res, 0, i_aggtransfn);
        aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
+       aggsortop = PQgetvalue(res, 0, i_aggsortop);
        aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
        agginitval = PQgetvalue(res, 0, i_agginitval);
-       /* we save anybasetype so that dumpAggACL can use it later */
-       agginfo->anybasetype = (PQgetvalue(res, 0, i_anybasetype)[0] == 't');
-       /* we save fmtbasetype so that dumpAggACL can use it later */
-       agginfo->fmtbasetype = strdup(PQgetvalue(res, 0, i_fmtbasetype));
        convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't');
 
-       aggsig = format_aggregate_signature(agginfo, g_fout, true);
-       aggsig_tag = format_aggregate_signature(agginfo, g_fout, false);
+       aggsig = format_aggregate_signature(agginfo, fout, true);
+       aggsig_tag = format_aggregate_signature(agginfo, fout, false);
 
        if (!convertok)
        {
                write_msg(NULL, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
                                  aggsig);
-
-               appendPQExpBuffer(q, "-- WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
-                                                 aggsig);
-               ArchiveEntry(fout, agginfo->oid, aggsig_tag,
-                                        agginfo->aggnamespace->nspname, agginfo->usename,
-                                        "WARNING", NULL,
-                                        q->data, "" /* Del */ ,
-                                        NULL, NULL, NULL);
                return;
        }
 
        if (g_fout->remoteVersion >= 70300)
        {
                /* If using 7.3's regproc or regtype, data is already quoted */
-               appendPQExpBuffer(details, "    BASETYPE = %s,\n    SFUNC = %s,\n    STYPE = %s",
-                                                 agginfo->anybasetype ? "'any'" :
-                                                 agginfo->fmtbasetype,
+               appendPQExpBuffer(details, "    SFUNC = %s,\n    STYPE = %s",
                                                  aggtransfn,
                                                  aggtranstype);
        }
        else if (g_fout->remoteVersion >= 70100)
        {
                /* format_type quotes, regproc does not */
-               appendPQExpBuffer(details, "    BASETYPE = %s,\n    SFUNC = %s,\n    STYPE = %s",
-                                                 agginfo->anybasetype ? "'any'" :
-                                                 agginfo->fmtbasetype,
+               appendPQExpBuffer(details, "    SFUNC = %s,\n    STYPE = %s",
                                                  fmtId(aggtransfn),
                                                  aggtranstype);
        }
        else
        {
                /* need quotes all around */
-               appendPQExpBuffer(details, "    BASETYPE = %s,\n",
-                                                 agginfo->anybasetype ? "'any'" :
-                                                 fmtId(agginfo->fmtbasetype));
                appendPQExpBuffer(details, "    SFUNC = %s,\n",
                                                  fmtId(aggtransfn));
                appendPQExpBuffer(details, "    STYPE = %s",
@@ -4824,7 +7126,7 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
        if (!PQgetisnull(res, 0, i_agginitval))
        {
                appendPQExpBuffer(details, ",\n    INITCOND = ");
-               appendStringLiteral(details, agginitval, true);
+               appendStringLiteralAH(details, agginitval, fout);
        }
 
        if (strcmp(aggfinalfn, "-") != 0)
@@ -4833,36 +7135,58 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
                                                  aggfinalfn);
        }
 
+       aggsortop = convertOperatorReference(aggsortop);
+       if (aggsortop)
+       {
+               appendPQExpBuffer(details, ",\n    SORTOP = %s",
+                                                 aggsortop);
+       }
+
        /*
-        * DROP must be fully qualified in case same name appears in
-        * pg_catalog
+        * DROP must be fully qualified in case same name appears in pg_catalog
         */
        appendPQExpBuffer(delq, "DROP AGGREGATE %s.%s;\n",
-                                         fmtId(agginfo->aggnamespace->nspname),
+                                         fmtId(agginfo->aggfn.dobj.namespace->dobj.name),
                                          aggsig);
 
        appendPQExpBuffer(q, "CREATE AGGREGATE %s (\n%s\n);\n",
-                                         fmtId(agginfo->aggname),
-                                         details->data);
+                                         aggsig, details->data);
 
-       ArchiveEntry(fout, agginfo->oid, aggsig_tag,
-                                agginfo->aggnamespace->nspname, agginfo->usename,
-                                "AGGREGATE", NULL,
-                                q->data, delq->data,
-                                NULL, NULL, NULL);
+       ArchiveEntry(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
+                                aggsig_tag,
+                                agginfo->aggfn.dobj.namespace->dobj.name,
+                                NULL,
+                                agginfo->aggfn.rolname,
+                                false, "AGGREGATE", q->data, delq->data, NULL,
+                                agginfo->aggfn.dobj.dependencies, agginfo->aggfn.dobj.nDeps,
+                                NULL, NULL);
 
        /* Dump Aggregate Comments */
-
        resetPQExpBuffer(q);
        appendPQExpBuffer(q, "AGGREGATE %s", aggsig);
-       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);
+       dumpComment(fout, q->data,
+                       agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname,
+                               agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
+
+       /*
+        * Since there is no GRANT ON AGGREGATE syntax, we have to make the ACL
+        * command look like a function's GRANT; in particular this affects the
+        * syntax for zero-argument aggregates.
+        */
+       free(aggsig);
+       free(aggsig_tag);
+
+       aggsig = format_function_signature(&agginfo->aggfn, true);
+       aggsig_tag = format_function_signature(&agginfo->aggfn, false);
+
+       dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
+                       "FUNCTION",
+                       aggsig, aggsig_tag,
+                       agginfo->aggfn.dobj.namespace->dobj.name,
+                       agginfo->aggfn.rolname, agginfo->aggfn.proacl);
+
+       free(aggsig);
+       free(aggsig_tag);
 
        PQclear(res);
 
@@ -4870,43 +7194,34 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo)
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
        destroyPQExpBuffer(details);
-       free(aggsig);
-       free(aggsig_tag);
 }
 
 
 /*----------
  * Write out grant/revoke information
  *
- * 'type' must be TABLE, FUNCTION, LANGUAGE, or SCHEMA.
+ * 'objCatId' is the catalog ID of the underlying object.
+ * 'objDumpId' is the dump ID of the underlying object.
+ * 'type' must be TABLE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, or TABLESPACE.
  * 'name' is the formatted name of the object. Must be quoted etc. already.
  * 'tag' is the tag for the archive entry (typ. unquoted name of object).
  * 'nspname' is the namespace the object is in (NULL if none).
  * 'owner' is the owner, NULL if there is no owner (for languages).
  * 'acls' is the string read out of the fooacl system catalog field;
  * it will be parsed here.
- * 'objoid' is the OID of the object for purposes of ordering.
  *----------
  */
 static void
-dumpACL(Archive *fout, const char *type, const char *name,
+dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
+               const char *type, const char *name,
                const char *tag, const char *nspname, const char *owner,
-               const char *acls, const char *objoid)
+               const char *acls)
 {
        PQExpBuffer sql;
 
-       /*
-        * acl_lang is a flag only true if we are dumping language's ACL, so
-        * we can set 'type' to a value that is suitable to build SQL requests
-        * as for other types.
-        */
-       bool            acl_lang = false;
-
-       if (!strcmp(type, "ACL LANGUAGE"))
-       {
-               type = "LANGUAGE";
-               acl_lang = true;
-       }
+       /* Do nothing if ACL dump is not enabled */
+       if (dataOnly || aclsSkip)
+               return;
 
        sql = createPQExpBuffer();
 
@@ -4918,131 +7233,65 @@ dumpACL(Archive *fout, const char *type, const char *name,
        }
 
        if (sql->len > 0)
-               ArchiveEntry(fout, objoid, tag, nspname,
+               ArchiveEntry(fout, nilCatalogId, createDumpId(),
+                                        tag, nspname,
+                                        NULL,
                                         owner ? owner : "",
-                                        acl_lang ? "ACL LANGUAGE" : "ACL",
-                                        NULL, sql->data, "", NULL, NULL, NULL);
+                                        false, "ACL", sql->data, "", NULL,
+                                        &(objDumpId), 1,
+                                        NULL, NULL);
 
        destroyPQExpBuffer(sql);
 }
 
-
-static void
-dumpTableACL(Archive *fout, TableInfo *tbinfo)
-{
-       char       *namecopy = strdup(fmtId(tbinfo->relname));
-       char       *dumpoid;
-
-       /*
-        * Choose OID to use for sorting ACL into position.  For a view, sort
-        * by the view OID; for a serial sequence, sort by the owning table's
-        * OID; otherwise use the table's own OID.
-        */
-       if (tbinfo->viewoid != NULL)
-               dumpoid = tbinfo->viewoid;
-       else if (tbinfo->owning_tab != NULL)
-               dumpoid = tbinfo->owning_tab;
-       else
-               dumpoid = tbinfo->oid;
-
-       dumpACL(fout, "TABLE", namecopy, tbinfo->relname,
-                 tbinfo->relnamespace->nspname, tbinfo->usename, tbinfo->relacl,
-                       dumpoid);
-
-       free(namecopy);
-}
-
-
 /*
- * dumpTables:
- *       write out to fout the declarations (not data) of all user-defined tables
+ * dumpTable
+ *       write out to fout the declarations (not data) of a user-defined table
  */
-void
-dumpTables(Archive *fout, TableInfo tblinfo[], int numTables,
-                const bool aclsSkip, const bool schemaOnly, const bool dataOnly)
+static void
+dumpTable(Archive *fout, TableInfo *tbinfo)
 {
-       int                     i;
-
-       /*
-        * Dump non-serial sequences first, in case they are referenced in
-        * table defn's
-        */
-       for (i = 0; i < numTables; i++)
-       {
-               TableInfo  *tbinfo = &tblinfo[i];
-
-               if (tbinfo->relkind != RELKIND_SEQUENCE)
-                       continue;
+       char       *namecopy;
 
-               if (tbinfo->dump && tbinfo->owning_tab == NULL)
-               {
-                       dumpOneSequence(fout, tbinfo, schemaOnly, dataOnly);
-                       if (!dataOnly && !aclsSkip)
-                               dumpTableACL(fout, tbinfo);
-               }
-       }
-
-       if (!dataOnly)
-       {
-               for (i = 0; i < numTables; i++)
-               {
-                       TableInfo  *tbinfo = &tblinfo[i];
-
-                       if (tbinfo->relkind == RELKIND_SEQUENCE)        /* already dumped */
-                               continue;
-
-                       if (tbinfo->dump)
-                       {
-                               dumpOneTable(fout, tbinfo, tblinfo);
-                               if (!aclsSkip)
-                                       dumpTableACL(fout, tbinfo);
-                       }
-               }
-       }
-
-       /*
-        * Dump serial sequences last (we will not emit any CREATE commands,
-        * but we do have to think about ACLs and setval operations).
-        */
-       for (i = 0; i < numTables; i++)
+       if (tbinfo->dobj.dump)
        {
-               TableInfo  *tbinfo = &tblinfo[i];
-
-               if (tbinfo->relkind != RELKIND_SEQUENCE)
-                       continue;
-
-               if (tbinfo->dump && tbinfo->owning_tab != NULL)
-               {
-                       dumpOneSequence(fout, tbinfo, schemaOnly, dataOnly);
-                       if (!dataOnly && !aclsSkip)
-                               dumpTableACL(fout, tbinfo);
-               }
+               if (tbinfo->relkind == RELKIND_SEQUENCE)
+                       dumpSequence(fout, tbinfo);
+               else if (!dataOnly)
+                       dumpTableSchema(fout, tbinfo);
+
+               /* Handle the ACL here */
+               namecopy = strdup(fmtId(tbinfo->dobj.name));
+               dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
+                               (tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" : "TABLE",
+                               namecopy, tbinfo->dobj.name,
+                               tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
+                               tbinfo->relacl);
+               free(namecopy);
        }
 }
 
 /*
- * dumpOneTable
+ * dumpTableSchema
  *       write the declaration (not data) of one user-defined table or view
  */
 static void
-dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
+dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 {
        PQExpBuffer query = createPQExpBuffer();
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
        PGresult   *res;
        int                     numParents;
-       int                *parentIndexes;
+       TableInfo **parents;
        int                     actual_atts;    /* number of attrs in this CREATE statment */
        char       *reltypename;
        char       *storage;
-       char       *objoid;
-       const char *((*commentDeps)[]);
        int                     j,
                                k;
 
        /* Make sure we are in proper schema */
-       selectSourceSchema(tbinfo->relnamespace->nspname);
+       selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
 
        /* Is it a table or a view? */
        if (tbinfo->relkind == RELKIND_VIEW)
@@ -5054,47 +7303,30 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
                /* Fetch the view definition */
                if (g_fout->remoteVersion >= 70300)
                {
-                       /* Beginning in 7.3, viewname is not unique; use OID */
-                       appendPQExpBuffer(query, "SELECT pg_catalog.pg_get_viewdef(ev_class) as viewdef, "
-                                                         "oid as view_oid"
-                                                         " from pg_catalog.pg_rewrite where"
-                                                         " ev_class = '%s'::pg_catalog.oid and"
-                                                         " rulename = '_RETURN';",
-                                                         tbinfo->oid);
+                       /* Beginning in 7.3, viewname is not unique; rely on OID */
+                       appendPQExpBuffer(query,
+                                                         "SELECT pg_catalog.pg_get_viewdef('%u'::pg_catalog.oid) as viewdef",
+                                                         tbinfo->dobj.catId.oid);
                }
                else
                {
-                       appendPQExpBuffer(query, "SELECT definition as viewdef, "
-                                                         "(select oid from pg_rewrite where "
-                                         " rulename=('_RET' || viewname)::name) as view_oid"
+                       appendPQExpBuffer(query, "SELECT definition as viewdef "
                                                          " from pg_views where viewname = ");
-                       appendStringLiteral(query, tbinfo->relname, true);
+                       appendStringLiteralAH(query, tbinfo->dobj.name, fout);
                        appendPQExpBuffer(query, ";");
                }
 
                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();
-               }
+               check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
                if (PQntuples(res) != 1)
                {
                        if (PQntuples(res) < 1)
                                write_msg(NULL, "query to obtain definition of view \"%s\" returned no data\n",
-                                                 tbinfo->relname);
+                                                 tbinfo->dobj.name);
                        else
                                write_msg(NULL, "query to obtain definition of view \"%s\" returned more than one definition\n",
-                                                 tbinfo->relname);
-                       exit_nicely();
-               }
-
-               if (PQgetisnull(res, 0, 1))
-               {
-                       write_msg(NULL, "query to obtain definition of view \"%s\" returned null OID\n",
-                                         tbinfo->relname);
+                                                 tbinfo->dobj.name);
                        exit_nicely();
                }
 
@@ -5103,69 +7335,41 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
                if (strlen(viewdef) == 0)
                {
                        write_msg(NULL, "definition of view \"%s\" appears to be empty (length zero)\n",
-                                         tbinfo->relname);
+                                         tbinfo->dobj.name);
                        exit_nicely();
                }
 
-               /* 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;
-
                /*
                 * DROP must be fully qualified in case same name appears in
                 * pg_catalog
                 */
                appendPQExpBuffer(delq, "DROP VIEW %s.",
-                                                 fmtId(tbinfo->relnamespace->nspname));
+                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
                appendPQExpBuffer(delq, "%s;\n",
-                                                 fmtId(tbinfo->relname));
+                                                 fmtId(tbinfo->dobj.name));
 
                appendPQExpBuffer(q, "CREATE VIEW %s AS\n    %s\n",
-                                                 fmtId(tbinfo->relname), viewdef);
+                                                 fmtId(tbinfo->dobj.name), viewdef);
 
                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));
-                               appendPQExpBuffer(q, "ALTER COLUMN %s SET DEFAULT %s;\n",
-                                                                 fmtId(tbinfo->attnames[j]),
-                                                                 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;
+               parents = tbinfo->parents;
 
                /*
                 * DROP must be fully qualified in case same name appears in
                 * pg_catalog
                 */
                appendPQExpBuffer(delq, "DROP TABLE %s.",
-                                                 fmtId(tbinfo->relnamespace->nspname));
+                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
                appendPQExpBuffer(delq, "%s;\n",
-                                                 fmtId(tbinfo->relname));
+                                                 fmtId(tbinfo->dobj.name));
 
                appendPQExpBuffer(q, "CREATE TABLE %s (",
-                                                 fmtId(tbinfo->relname));
+                                                 fmtId(tbinfo->dobj.name));
                actual_atts = 0;
                for (j = 0; j < tbinfo->numatts; j++)
                {
@@ -5184,16 +7388,8 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
                                /* Attribute type */
                                if (g_fout->remoteVersion >= 70100)
                                {
-                                       char       *typname = tbinfo->atttypnames[j];
-
-                                       if (tbinfo->attisserial[j])
-                                       {
-                                               if (strcmp(typname, "integer") == 0)
-                                                       typname = "serial";
-                                               else if (strcmp(typname, "bigint") == 0)
-                                                       typname = "bigserial";
-                                       }
-                                       appendPQExpBuffer(q, "%s", typname);
+                                       appendPQExpBuffer(q, "%s",
+                                                                         tbinfo->atttypnames[j]);
                                }
                                else
                                {
@@ -5203,21 +7399,18 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
                                                                                                   tbinfo->atttypmod[j]));
                                }
 
-                               /* Default value --- suppress if inherited or serial */
-                               if (tbinfo->adef_expr[j] != NULL &&
+                               /*
+                                * Default value --- suppress if inherited or to be
+                                * printed separately.
+                                */
+                               if (tbinfo->attrdefs[j] != NULL &&
                                        !tbinfo->inhAttrDef[j] &&
-                                       !tbinfo->attisserial[j])
+                                       !tbinfo->attrdefs[j]->separate)
                                        appendPQExpBuffer(q, " DEFAULT %s",
-                                                                         tbinfo->adef_expr[j]);
+                                                                         tbinfo->attrdefs[j]->adef_expr);
 
                                /*
                                 * Not Null constraint --- suppress if inherited
-                                *
-                                * Note: we could suppress this for serial columns since
-                                * SERIAL implies NOT NULL.  We choose not to for forward
-                                * compatibility, since there has been some talk of making
-                                * SERIAL not imply NOT NULL, in which case the explicit
-                                * specification would be needed.
                                 */
                                if (tbinfo->notnull[j] && !tbinfo->inhNotNull[j])
                                        appendPQExpBuffer(q, " NOT NULL");
@@ -5227,123 +7420,25 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
                }
 
                /*
-                * 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.
+                * Add non-inherited CHECK constraints, if any.
                 */
-               if (tbinfo->ncheck > 0)
+               for (j = 0; j < tbinfo->ncheck; j++)
                {
-                       PGresult   *res2;
-                       int                     i_conname,
-                                               i_consrc;
-                       int                     ntups2;
-
-                       if (g_verbose)
-                               write_msg(NULL, "finding check constraints for table \"%s\"\n",
-                                                 tbinfo->relname);
-
-                       resetPQExpBuffer(query);
-                       if (g_fout->remoteVersion >= 70400)
-                               appendPQExpBuffer(query, "SELECT conname, "
-                                       " pg_catalog.pg_get_constraintdef(c1.oid) AS consrc "
-                                                                 " from pg_catalog.pg_constraint c1 "
-                                                               " where conrelid = '%s'::pg_catalog.oid "
-                                                                 "   and contype = 'c' "
-                                                                 "   and not exists "
-                                                                 "  (select 1 from "
-                                                                 "    pg_catalog.pg_constraint c2, "
-                                                                 "    pg_catalog.pg_inherits i "
-                                                                 "    where i.inhrelid = c1.conrelid "
-                                                                 "      and (c2.conname = c1.conname "
-                                                                 "          or (c2.conname[0] = '$' "
-                                                                 "              and c1.conname[0] = '$')"
-                                                                 "          )"
-                                        "      and pg_catalog.pg_get_constraintdef(c2.oid) "
-                                                                 "                  = pg_catalog.pg_get_constraintdef(c1.oid) "
-                                                                 "      and c2.conrelid = i.inhparent) "
-                                                                 " order by conname ",
-                                                                 tbinfo->oid);
-                       else if (g_fout->remoteVersion >= 70300)
-                               appendPQExpBuffer(query, "SELECT conname, "
-                                                                 " 'CHECK (' || consrc || ')' AS consrc"
-                                                                 " from pg_catalog.pg_constraint c1"
-                                                               " where conrelid = '%s'::pg_catalog.oid "
-                                                                 "   and contype = 'c' "
-                                                                 "   and not exists "
-                                                                 "  (select 1 from "
-                                                                 "    pg_catalog.pg_constraint c2, "
-                                                                 "    pg_catalog.pg_inherits i "
-                                                                 "    where i.inhrelid = c1.conrelid "
-                                                                 "      and (c2.conname = c1.conname "
-                                                                 "          or (c2.conname[0] = '$' "
-                                                                 "              and c1.conname[0] = '$')"
-                                                                 "          )"
-                                                                 "      and c2.consrc = c1.consrc "
-                                                                 "      and c2.conrelid = i.inhparent) "
-                                                                 " order by conname ",
-                                                                 tbinfo->oid);
-                       else
-                               appendPQExpBuffer(query, "SELECT rcname as conname,"
-                                                                 " 'CHECK (' || rcsrc || ')' as consrc"
-                                                                 " from pg_relcheck c1"
-                                                                 " where rcrelid = '%s'::oid "
-                                                                 "   and not exists "
-                                                                 "  (select 1 from pg_relcheck c2, "
-                                                                 "    pg_inherits i "
-                                                                 "    where i.inhrelid = c1.rcrelid "
-                                                                 "      and (c2.rcname = c1.rcname "
-                                                                 "          or (c2.rcname[0] = '$' "
-                                                                 "              and c1.rcname[0] = '$')"
-                                                                 "          )"
-                                                                 "      and c2.rcsrc = c1.rcsrc "
-                                                                 "      and c2.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();
-                       }
-                       ntups2 = PQntuples(res2);
-                       if (ntups2 > tbinfo->ncheck)
-                       {
-                               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();
-                       }
+                       ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
 
-                       i_conname = PQfnumber(res2, "conname");
-                       i_consrc = PQfnumber(res2, "consrc");
+                       if (constr->coninherited || constr->separate)
+                               continue;
 
-                       for (j = 0; j < ntups2; j++)
-                       {
-                               const char *name = PQgetvalue(res2, j, i_conname);
-                               const char *expr = PQgetvalue(res2, j, i_consrc);
+                       if (actual_atts > 0)
+                               appendPQExpBuffer(q, ",\n    ");
 
-                               if (actual_atts + j > 0)
-                                       appendPQExpBuffer(q, ",\n    ");
+                       appendPQExpBuffer(q, "CONSTRAINT %s ",
+                                                         fmtId(constr->dobj.name));
+                       appendPQExpBuffer(q, "%s", constr->condef);
 
-                               appendPQExpBuffer(q, "CONSTRAINT %s ",
-                                                                 fmtId(name));
-                               appendPQExpBuffer(q, "%s", expr);
-                       }
-                       PQclear(res2);
+                       actual_atts++;
                }
 
-               /*
-                * 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.
-                */
-
                appendPQExpBuffer(q, "\n)");
 
                if (numParents > 0)
@@ -5351,21 +7446,21 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
                        appendPQExpBuffer(q, "\nINHERITS (");
                        for (k = 0; k < numParents; k++)
                        {
-                               TableInfo  *parentRel = &g_tblinfo[parentIndexes[k]];
+                               TableInfo  *parentRel = parents[k];
 
                                if (k > 0)
                                        appendPQExpBuffer(q, ", ");
-                               if (parentRel->relnamespace != tbinfo->relnamespace)
+                               if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
                                        appendPQExpBuffer(q, "%s.",
-                                                               fmtId(parentRel->relnamespace->nspname));
+                                                               fmtId(parentRel->dobj.namespace->dobj.name));
                                appendPQExpBuffer(q, "%s",
-                                                                 fmtId(parentRel->relname));
+                                                                 fmtId(parentRel->dobj.name));
                        }
                        appendPQExpBuffer(q, ")");
                }
 
-               if (!tbinfo->hasoids)
-                       appendPQExpBuffer(q, " WITHOUT OIDS");
+               if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
+                       appendPQExpBuffer(q, "\nWITH (%s)", tbinfo->reloptions);
 
                appendPQExpBuffer(q, ";\n");
 
@@ -5373,15 +7468,15 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
                for (j = 0; j < tbinfo->numatts; j++)
                {
                        /*
-                        * Dump per-column statistics information. We only issue an
-                        * ALTER TABLE statement if the attstattarget entry for this
-                        * column is non-negative (i.e. it's not the default value)
+                        * Dump per-column statistics information. We only issue an ALTER
+                        * TABLE statement if the attstattarget entry for this column is
+                        * non-negative (i.e. it's not the default value)
                         */
                        if (tbinfo->attstattarget[j] >= 0 &&
                                !tbinfo->attisdropped[j])
                        {
                                appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
-                                                                 fmtId(tbinfo->relname));
+                                                                 fmtId(tbinfo->dobj.name));
                                appendPQExpBuffer(q, "ALTER COLUMN %s ",
                                                                  fmtId(tbinfo->attnames[j]));
                                appendPQExpBuffer(q, "SET STATISTICS %d;\n",
@@ -5390,8 +7485,7 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
 
                        /*
                         * Dump per-column storage information.  The statement is only
-                        * dumped if the storage has been changed from the type's
-                        * default.
+                        * dumped if the storage has been changed from the type's default.
                         */
                        if (!tbinfo->attisdropped[j] && tbinfo->attstorage[j] != tbinfo->typstorage[j])
                        {
@@ -5414,13 +7508,12 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
                                }
 
                                /*
-                                * Only dump the statement if it's a storage type we
-                                * recognize
+                                * Only dump the statement if it's a storage type we recognize
                                 */
                                if (storage != NULL)
                                {
                                        appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
-                                                                         fmtId(tbinfo->relname));
+                                                                         fmtId(tbinfo->dobj.name));
                                        appendPQExpBuffer(q, "ALTER COLUMN %s ",
                                                                          fmtId(tbinfo->attnames[j]));
                                        appendPQExpBuffer(q, "SET STORAGE %s;\n",
@@ -5430,21 +7523,86 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
                }
        }
 
-       ArchiveEntry(fout, objoid, tbinfo->relname,
-                                tbinfo->relnamespace->nspname, tbinfo->usename,
-                                reltypename, NULL, q->data, delq->data,
-                                NULL, NULL, NULL);
+       ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
+                                tbinfo->dobj.name,
+                                tbinfo->dobj.namespace->dobj.name,
+                       (tbinfo->relkind == RELKIND_VIEW) ? NULL : tbinfo->reltablespace,
+                                tbinfo->rolname,
+                          (strcmp(reltypename, "TABLE") == 0) ? tbinfo->hasoids : false,
+                                reltypename, q->data, delq->data, NULL,
+                                tbinfo->dobj.dependencies, tbinfo->dobj.nDeps,
+                                NULL, NULL);
 
        /* Dump Table Comments */
-       dumpTableComment(fout, tbinfo, reltypename, commentDeps);
+       dumpTableComment(fout, tbinfo, reltypename);
+
+       /* Dump comments on inlined table constraints */
+       for (j = 0; j < tbinfo->ncheck; j++)
+       {
+               ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
+
+               if (constr->coninherited || constr->separate)
+                       continue;
 
-       /* commentDeps now belongs to the archive entry ... don't free it! */
+               dumpTableConstraintComment(fout, constr);
+       }
 
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
 }
 
+/*
+ * dumpAttrDef --- dump an attribute's default-value declaration
+ */
+static void
+dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
+{
+       TableInfo  *tbinfo = adinfo->adtable;
+       int                     adnum = adinfo->adnum;
+       PQExpBuffer q;
+       PQExpBuffer delq;
+
+       /* Only print it if "separate" mode is selected */
+       if (!tbinfo->dobj.dump || !adinfo->separate || dataOnly)
+               return;
+
+       /* Don't print inherited defaults, either */
+       if (tbinfo->inhAttrDef[adnum - 1])
+               return;
+
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
+
+       appendPQExpBuffer(q, "ALTER TABLE %s ",
+                                         fmtId(tbinfo->dobj.name));
+       appendPQExpBuffer(q, "ALTER COLUMN %s SET DEFAULT %s;\n",
+                                         fmtId(tbinfo->attnames[adnum - 1]),
+                                         adinfo->adef_expr);
+
+       /*
+        * DROP must be fully qualified in case same name appears in pg_catalog
+        */
+       appendPQExpBuffer(delq, "ALTER TABLE %s.",
+                                         fmtId(tbinfo->dobj.namespace->dobj.name));
+       appendPQExpBuffer(delq, "%s ",
+                                         fmtId(tbinfo->dobj.name));
+       appendPQExpBuffer(delq, "ALTER COLUMN %s DROP DEFAULT;\n",
+                                         fmtId(tbinfo->attnames[adnum - 1]));
+
+       ArchiveEntry(fout, adinfo->dobj.catId, adinfo->dobj.dumpId,
+                                tbinfo->attnames[adnum - 1],
+                                tbinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                tbinfo->rolname,
+                                false, "DEFAULT", q->data, delq->data, NULL,
+                                adinfo->dobj.dependencies, adinfo->dobj.nDeps,
+                                NULL, NULL);
+
+       destroyPQExpBuffer(q);
+       destroyPQExpBuffer(delq);
+}
+
 /*
  * getAttrName: extract the correct name for an attribute
  *
@@ -5475,319 +7633,317 @@ getAttrName(int attrnum, TableInfo *tblInfo)
                        return "tableoid";
        }
        write_msg(NULL, "invalid column number %d for table \"%s\"\n",
-                         attrnum, tblInfo->relname);
+                         attrnum, tblInfo->dobj.name);
        exit_nicely();
        return NULL;                            /* keep compiler quiet */
 }
 
 /*
- * dumpIndexes:
- *       write out to fout all the user-defined indexes for dumpable tables
+ * dumpIndex
+ *       write out to fout a user-defined index
  */
-void
-dumpIndexes(Archive *fout, TableInfo *tblinfo, int numTables)
+static void
+dumpIndex(Archive *fout, IndxInfo *indxinfo)
 {
-       int                     i,
-                               j;
-       PQExpBuffer query = createPQExpBuffer();
-       PQExpBuffer q = createPQExpBuffer();
-       PQExpBuffer delq = createPQExpBuffer();
-       PGresult   *res;
-       int                     ntups;
-       int                     i_indexreloid;
-       int                     i_indexrelname;
-       int                     i_indexdef;
-       int                     i_contype;
-       int                     i_conoid;
-       int                     i_indkey;
-       int                     i_indisclustered;
-       int                     i_indnkeys;
-
-       for (i = 0; i < numTables; i++)
-       {
-               TableInfo  *tbinfo = &tblinfo[i];
-
-               /* Only plain tables have indexes */
-               if (tbinfo->relkind != RELKIND_RELATION || !tbinfo->hasindex)
-                       continue;
+       TableInfo  *tbinfo = indxinfo->indextable;
+       PQExpBuffer q;
+       PQExpBuffer delq;
 
-               if (!tbinfo->dump)
-                       continue;
+       if (dataOnly)
+               return;
 
-               /* Make sure we are in proper schema so indexdef is right */
-               selectSourceSchema(tbinfo->relnamespace->nspname);
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
 
-               /*
-                * The point of the messy-looking outer join is to find a
-                * constraint that is related by an internal dependency link to
-                * the index. If we find one, we emit an ADD CONSTRAINT command
-                * instead of a CREATE INDEX command.  We assume an index won't
-                * have more than one internal dependency.
-                */
-               resetPQExpBuffer(query);
-               if (g_fout->remoteVersion >= 70300)
-                       appendPQExpBuffer(query,
-                                                         "SELECT i.indexrelid as indexreloid, "
-                                          "coalesce(c.conname, t.relname) as indexrelname, "
-                                "pg_catalog.pg_get_indexdef(i.indexrelid) as indexdef, "
-                                                         "i.indkey, i.indisclustered, "
-                                                         "t.relnatts as indnkeys, "
-                                                         "coalesce(c.contype, '0') as contype, "
-                                                         "coalesce(c.oid, '0') as conoid "
-                                                         "FROM pg_catalog.pg_index i "
-                                 "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
-                                                         "LEFT JOIN pg_catalog.pg_depend d "
-                                                         "ON (d.classid = t.tableoid "
-                                                         "AND d.objid = t.oid "
-                                                         "AND d.deptype = 'i') "
-                                                         "LEFT JOIN pg_catalog.pg_constraint c "
-                                                         "ON (d.refclassid = c.tableoid "
-                                                         "AND d.refobjid = c.oid) "
-                                                         "WHERE i.indrelid = '%s'::pg_catalog.oid "
-                                                         "ORDER BY indexrelname",
-                                                         tbinfo->oid);
-               else
-                       appendPQExpBuffer(query,
-                                                         "SELECT i.indexrelid as indexreloid, "
-                                                         "t.relname as indexrelname, "
-                                                       "pg_get_indexdef(i.indexrelid) as indexdef, "
-                                                         "i.indkey, false as indisclustered, "
-                                                         "t.relnatts as indnkeys, "
-                                                         "CASE WHEN i.indisprimary THEN 'p'::char "
-                                                         "ELSE '0'::char END as contype, "
-                                                         "0::oid as conoid "
-                                                         "FROM pg_index i, pg_class t "
-                                                         "WHERE t.oid = i.indexrelid "
-                                                         "AND i.indrelid = '%s'::oid "
-                                                         "ORDER BY indexrelname",
-                                                         tbinfo->oid);
+       /*
+        * If there's an associated constraint, don't dump the index per se, but
+        * do dump any comment for it.  (This is safe because dependency ordering
+        * will have ensured the constraint is emitted first.)
+        */
+       if (indxinfo->indexconstraint == 0)
+       {
+               /* Plain secondary index */
+               appendPQExpBuffer(q, "%s;\n", indxinfo->indexdef);
 
-               res = PQexec(g_conn, query->data);
-               if (!res ||
-                       PQresultStatus(res) != PGRES_TUPLES_OK)
+               /* If the index is clustered, we need to record that. */
+               if (indxinfo->indisclustered)
                {
-                       write_msg(NULL, "query to obtain list of indexes failed: %s", PQerrorMessage(g_conn));
-                       exit_nicely();
+                       appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
+                                                         fmtId(tbinfo->dobj.name));
+                       appendPQExpBuffer(q, " ON %s;\n",
+                                                         fmtId(indxinfo->dobj.name));
                }
 
-               ntups = PQntuples(res);
+               /*
+                * DROP must be fully qualified in case same name appears in
+                * pg_catalog
+                */
+               appendPQExpBuffer(delq, "DROP INDEX %s.",
+                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
+               appendPQExpBuffer(delq, "%s;\n",
+                                                 fmtId(indxinfo->dobj.name));
 
-               i_indexreloid = PQfnumber(res, "indexreloid");
-               i_indexrelname = PQfnumber(res, "indexrelname");
-               i_indexdef = PQfnumber(res, "indexdef");
-               i_contype = PQfnumber(res, "contype");
-               i_conoid = PQfnumber(res, "conoid");
-               i_indkey = PQfnumber(res, "indkey");
-               i_indisclustered = PQfnumber(res, "indisclustered");
-               i_indnkeys = PQfnumber(res, "indnkeys");
+               ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
+                                        indxinfo->dobj.name,
+                                        tbinfo->dobj.namespace->dobj.name,
+                                        indxinfo->tablespace,
+                                        tbinfo->rolname, false,
+                                        "INDEX", q->data, delq->data, NULL,
+                                        indxinfo->dobj.dependencies, indxinfo->dobj.nDeps,
+                                        NULL, NULL);
+       }
 
-               for (j = 0; j < ntups; j++)
-               {
-                       const char *indexreloid = PQgetvalue(res, j, i_indexreloid);
-                       const char *indexrelname = PQgetvalue(res, j, i_indexrelname);
-                       const char *indexdef = PQgetvalue(res, j, i_indexdef);
-                       char            contype = *(PQgetvalue(res, j, i_contype));
-                       const char *conoid = PQgetvalue(res, j, i_conoid);
-                       bool            indisclustered = (PQgetvalue(res, j, i_indisclustered)[0] == 't');
+       /* Dump Index Comments */
+       resetPQExpBuffer(q);
+       appendPQExpBuffer(q, "INDEX %s",
+                                         fmtId(indxinfo->dobj.name));
+       dumpComment(fout, q->data,
+                               tbinfo->dobj.namespace->dobj.name,
+                               tbinfo->rolname,
+                               indxinfo->dobj.catId, 0, indxinfo->dobj.dumpId);
 
-                       resetPQExpBuffer(q);
-                       resetPQExpBuffer(delq);
+       destroyPQExpBuffer(q);
+       destroyPQExpBuffer(delq);
+}
 
-                       if (contype == 'p' || contype == 'u')
-                       {
-                               /*
-                                * If we found a constraint matching the index, emit ADD
-                                * CONSTRAINT not CREATE INDEX.
-                                *
-                                * In a pre-7.3 database, we take this path iff the index was
-                                * marked indisprimary.
-                                */
-                               int                     indnkeys = atoi(PQgetvalue(res, j, i_indnkeys));
-                               char      **indkeys = (char **) malloc(indnkeys * sizeof(char *));
-                               int                     k;
+/*
+ * dumpConstraint
+ *       write out to fout a user-defined constraint
+ */
+static void
+dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
+{
+       TableInfo  *tbinfo = coninfo->contable;
+       PQExpBuffer q;
+       PQExpBuffer delq;
 
-                               parseNumericArray(PQgetvalue(res, j, i_indkey),
-                                                                 indkeys, indnkeys);
+       /* Skip if not to be dumped */
+       if (!coninfo->dobj.dump || dataOnly)
+               return;
 
-                               appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
-                                                                 fmtId(tbinfo->relname));
-                               appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s (",
-                                                                 fmtId(indexrelname),
-                                                         contype == 'p' ? "PRIMARY KEY" : "UNIQUE");
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
 
-                               for (k = 0; k < indnkeys; k++)
-                               {
-                                       int                     indkey = atoi(indkeys[k]);
-                                       const char *attname;
+       if (coninfo->contype == 'p' || coninfo->contype == 'u')
+       {
+               /* Index-related constraint */
+               IndxInfo   *indxinfo;
+               int                     k;
 
-                                       if (indkey == InvalidAttrNumber)
-                                               break;
-                                       attname = getAttrName(indkey, tbinfo);
+               indxinfo = (IndxInfo *) findObjectByDumpId(coninfo->conindex);
 
-                                       appendPQExpBuffer(q, "%s%s",
-                                                                         (k == 0) ? "" : ", ",
-                                                                         fmtId(attname));
-                               }
+               if (indxinfo == NULL)
+               {
+                       write_msg(NULL, "missing index for constraint \"%s\"\n",
+                                         coninfo->dobj.name);
+                       exit_nicely();
+               }
 
-                               appendPQExpBuffer(q, ");\n");
+               appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
+                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s (",
+                                                 fmtId(coninfo->dobj.name),
+                                                 coninfo->contype == 'p' ? "PRIMARY KEY" : "UNIQUE");
 
-                               /* If the index is clustered, we need to record that. */
-                               if (indisclustered)
-                               {
-                                       appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
-                                                                         fmtId(tbinfo->relname));
-                                       appendPQExpBuffer(q, " ON %s;\n",
-                                                                         fmtId(indexrelname));
-                               }
+               for (k = 0; k < indxinfo->indnkeys; k++)
+               {
+                       int                     indkey = (int) indxinfo->indkeys[k];
+                       const char *attname;
 
-                               /*
-                                * DROP must be fully qualified in case same name appears
-                                * in pg_catalog
-                                */
-                               appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.",
-                                                                 fmtId(tbinfo->relnamespace->nspname));
-                               appendPQExpBuffer(delq, "%s ",
-                                                                 fmtId(tbinfo->relname));
-                               appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
-                                                                 fmtId(indexrelname));
-
-                               ArchiveEntry(fout, indexreloid,
-                                                        indexrelname,
-                                                        tbinfo->relnamespace->nspname,
-                                                        tbinfo->usename,
-                                                        "CONSTRAINT", NULL,
-                                                        q->data, delq->data,
-                                                        NULL, NULL, NULL);
-
-                               for (k = 0; k < indnkeys; k++)
-                                       free(indkeys[k]);
-                               free(indkeys);
-
-                               /* Dump Constraint Comments */
-                               resetPQExpBuffer(q);
-                               appendPQExpBuffer(q, "CONSTRAINT %s ",
-                                                                 fmtId(indexrelname));
-                               appendPQExpBuffer(q, "ON %s",
-                                                                 fmtId(tbinfo->relname));
-                               dumpComment(fout, q->data,
-                                                       tbinfo->relnamespace->nspname,
-                                                       tbinfo->usename,
-                                                       conoid, "pg_constraint", 0, NULL);
-                       }
-                       else
-                       {
-                               /* Plain secondary index */
-                               appendPQExpBuffer(q, "%s;\n", indexdef);
+                       if (indkey == InvalidAttrNumber)
+                               break;
+                       attname = getAttrName(indkey, tbinfo);
 
-                               /* If the index is clustered, we need to record that. */
-                               if (indisclustered)
-                               {
-                                       appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
-                                                                         fmtId(tbinfo->relname));
-                                       appendPQExpBuffer(q, " ON %s;\n",
-                                                                         fmtId(indexrelname));
-                               }
+                       appendPQExpBuffer(q, "%s%s",
+                                                         (k == 0) ? "" : ", ",
+                                                         fmtId(attname));
+               }
 
-                               /*
-                                * DROP must be fully qualified in case same name appears
-                                * in pg_catalog
-                                */
-                               appendPQExpBuffer(delq, "DROP INDEX %s.",
-                                                                 fmtId(tbinfo->relnamespace->nspname));
-                               appendPQExpBuffer(delq, "%s;\n",
-                                                                 fmtId(indexrelname));
-
-                               ArchiveEntry(fout, indexreloid,
-                                                        indexrelname,
-                                                        tbinfo->relnamespace->nspname,
-                                                        tbinfo->usename,
-                                                        "INDEX", NULL,
-                                                        q->data, delq->data,
-                                                        NULL, NULL, NULL);
-                       }
+               appendPQExpBuffer(q, ")");
 
-                       /* Dump Index Comments */
-                       resetPQExpBuffer(q);
-                       appendPQExpBuffer(q, "INDEX %s",
-                                                         fmtId(indexrelname));
-                       dumpComment(fout, q->data,
-                                               tbinfo->relnamespace->nspname,
-                                               tbinfo->usename,
-                                               indexreloid, "pg_class", 0, NULL);
+               if (indxinfo->options && strlen(indxinfo->options) > 0)
+                       appendPQExpBuffer(q, " WITH (%s)", indxinfo->options);
+
+               appendPQExpBuffer(q, ";\n");
+
+               /* If the index is clustered, we need to record that. */
+               if (indxinfo->indisclustered)
+               {
+                       appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
+                                                         fmtId(tbinfo->dobj.name));
+                       appendPQExpBuffer(q, " ON %s;\n",
+                                                         fmtId(indxinfo->dobj.name));
                }
 
-               PQclear(res);
+               /*
+                * DROP must be fully qualified in case same name appears in
+                * pg_catalog
+                */
+               appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.",
+                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
+               appendPQExpBuffer(delq, "%s ",
+                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
+                                                 fmtId(coninfo->dobj.name));
+
+               ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
+                                        coninfo->dobj.name,
+                                        tbinfo->dobj.namespace->dobj.name,
+                                        indxinfo->tablespace,
+                                        tbinfo->rolname, false,
+                                        "CONSTRAINT", q->data, delq->data, NULL,
+                                        coninfo->dobj.dependencies, coninfo->dobj.nDeps,
+                                        NULL, NULL);
+       }
+       else if (coninfo->contype == 'f')
+       {
+               /*
+                * XXX Potentially wrap in a 'SET CONSTRAINTS OFF' block so that the
+                * current table data is not processed
+                */
+               appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
+                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
+                                                 fmtId(coninfo->dobj.name),
+                                                 coninfo->condef);
+
+               /*
+                * DROP must be fully qualified in case same name appears in
+                * pg_catalog
+                */
+               appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.",
+                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
+               appendPQExpBuffer(delq, "%s ",
+                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
+                                                 fmtId(coninfo->dobj.name));
+
+               ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
+                                        coninfo->dobj.name,
+                                        tbinfo->dobj.namespace->dobj.name,
+                                        NULL,
+                                        tbinfo->rolname, false,
+                                        "FK CONSTRAINT", q->data, delq->data, NULL,
+                                        coninfo->dobj.dependencies, coninfo->dobj.nDeps,
+                                        NULL, NULL);
+       }
+       else if (coninfo->contype == 'c' && tbinfo)
+       {
+               /* CHECK constraint on a table */
+
+               /* Ignore if not to be dumped separately */
+               if (coninfo->separate)
+               {
+                       /* not ONLY since we want it to propagate to children */
+                       appendPQExpBuffer(q, "ALTER TABLE %s\n",
+                                                         fmtId(tbinfo->dobj.name));
+                       appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
+                                                         fmtId(coninfo->dobj.name),
+                                                         coninfo->condef);
+
+                       /*
+                        * DROP must be fully qualified in case same name appears in
+                        * pg_catalog
+                        */
+                       appendPQExpBuffer(delq, "ALTER TABLE %s.",
+                                                         fmtId(tbinfo->dobj.namespace->dobj.name));
+                       appendPQExpBuffer(delq, "%s ",
+                                                         fmtId(tbinfo->dobj.name));
+                       appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
+                                                         fmtId(coninfo->dobj.name));
+
+                       ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
+                                                coninfo->dobj.name,
+                                                tbinfo->dobj.namespace->dobj.name,
+                                                NULL,
+                                                tbinfo->rolname, false,
+                                                "CHECK CONSTRAINT", q->data, delq->data, NULL,
+                                                coninfo->dobj.dependencies, coninfo->dobj.nDeps,
+                                                NULL, NULL);
+               }
        }
+       else if (coninfo->contype == 'c' && tbinfo == NULL)
+       {
+               /* CHECK constraint on a domain */
+               TypeInfo   *tinfo = coninfo->condomain;
+
+               /* Ignore if not to be dumped separately */
+               if (coninfo->separate)
+               {
+                       appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
+                                                         fmtId(tinfo->dobj.name));
+                       appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
+                                                         fmtId(coninfo->dobj.name),
+                                                         coninfo->condef);
+
+                       /*
+                        * DROP must be fully qualified in case same name appears in
+                        * pg_catalog
+                        */
+                       appendPQExpBuffer(delq, "ALTER DOMAIN %s.",
+                                                         fmtId(tinfo->dobj.namespace->dobj.name));
+                       appendPQExpBuffer(delq, "%s ",
+                                                         fmtId(tinfo->dobj.name));
+                       appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
+                                                         fmtId(coninfo->dobj.name));
+
+                       ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
+                                                coninfo->dobj.name,
+                                                tinfo->dobj.namespace->dobj.name,
+                                                NULL,
+                                                tinfo->rolname, false,
+                                                "CHECK CONSTRAINT", q->data, delq->data, NULL,
+                                                coninfo->dobj.dependencies, coninfo->dobj.nDeps,
+                                                NULL, NULL);
+               }
+       }
+       else
+       {
+               write_msg(NULL, "unrecognized constraint type: %c\n", coninfo->contype);
+               exit_nicely();
+       }
+
+       /* Dump Constraint Comments --- only works for table constraints */
+       if (tbinfo && coninfo->separate)
+               dumpTableConstraintComment(fout, coninfo);
 
-       destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
 }
 
 /*
- * setMaxOid -
- * find the maximum oid and generate a COPY statement to set it
-*/
-
+ * dumpTableConstraintComment --- dump a constraint's comment if any
+ *
+ * This is split out because we need the function in two different places
+ * depending on whether the constraint is dumped as part of CREATE TABLE
+ * or as a separate ALTER command.
+ */
 static void
-setMaxOid(Archive *fout)
+dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo)
 {
-       PGresult   *res;
-       Oid                     max_oid;
-       char            sql[1024];
+       TableInfo  *tbinfo = coninfo->contable;
+       PQExpBuffer q = createPQExpBuffer();
 
-       res = PQexec(g_conn, "CREATE TEMPORARY TABLE pgdump_oid (dummy integer)");
-       if (!res ||
-               PQresultStatus(res) != PGRES_COMMAND_OK)
-       {
-               write_msg(NULL, "could not create pgdump_oid table: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
-       PQclear(res);
-       res = PQexec(g_conn, "INSERT INTO pgdump_oid VALUES (0)");
-       if (!res ||
-               PQresultStatus(res) != PGRES_COMMAND_OK)
-       {
-               write_msg(NULL, "could not insert into pgdump_oid table: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
-       max_oid = PQoidValue(res);
-       if (max_oid == 0)
-       {
-               write_msg(NULL, "inserted invalid OID\n");
-               exit_nicely();
-       }
-       PQclear(res);
-       res = PQexec(g_conn, "DROP TABLE pgdump_oid;");
-       if (!res ||
-               PQresultStatus(res) != PGRES_COMMAND_OK)
-       {
-               write_msg(NULL, "could not drop pgdump_oid table: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
-       PQclear(res);
-       if (g_verbose)
-               write_msg(NULL, "maximum system OID is %u\n", max_oid);
-       snprintf(sql, sizeof(sql),
-                        "CREATE TEMPORARY TABLE pgdump_oid (dummy integer);\n"
-                        "COPY pgdump_oid WITH OIDS FROM stdin;\n"
-                        "%u\t0\n"
-                        "\\.\n"
-                        "DROP TABLE pgdump_oid;\n",
-                        max_oid);
-
-       ArchiveEntry(fout, "0", "Max OID", NULL, "",
-                                "<Init>", NULL,
-                                sql, "",
-                                NULL, NULL, NULL);
+       appendPQExpBuffer(q, "CONSTRAINT %s ",
+                                         fmtId(coninfo->dobj.name));
+       appendPQExpBuffer(q, "ON %s",
+                                         fmtId(tbinfo->dobj.name));
+       dumpComment(fout, q->data,
+                               tbinfo->dobj.namespace->dobj.name,
+                               tbinfo->rolname,
+                               coninfo->dobj.catId, 0,
+                        coninfo->separate ? coninfo->dobj.dumpId : tbinfo->dobj.dumpId);
+
+       destroyPQExpBuffer(q);
 }
 
 /*
  * findLastBuiltInOid -
  * find the last built in oid
- * we do this by retrieving datlastsysoid from the pg_database entry for this database,
+ *
+ * For 7.1 and 7.2, we do this by retrieving datlastsysoid from the
+ * pg_database entry for the current database
  */
-
 static Oid
 findLastBuiltinOid_V71(const char *dbname)
 {
@@ -5798,15 +7954,11 @@ findLastBuiltinOid_V71(const char *dbname)
 
        resetPQExpBuffer(query);
        appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = ");
-       appendStringLiteral(query, dbname, true);
+       appendStringLiteralAH(query, dbname, g_fout);
 
        res = PQexec(g_conn, query->data);
-       if (res == NULL ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "error in finding the last system OID: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
        ntups = PQntuples(res);
        if (ntups < 1)
        {
@@ -5827,10 +7979,11 @@ findLastBuiltinOid_V71(const char *dbname)
 /*
  * findLastBuiltInOid -
  * find the last built in oid
- * we do this by looking up the oid of 'template1' in pg_database,
- * this is probably not foolproof but comes close
-*/
-
+ *
+ * For 7.0, we do this by assuming that the last thing that initdb does is to
+ * create the pg_indexes view. This sucks in general, but seeing that 7.0.x
+ * initdb won't be changing anymore, it'll do.
+ */
 static Oid
 findLastBuiltinOid_V70(void)
 {
@@ -5839,22 +7992,19 @@ findLastBuiltinOid_V70(void)
        int                     last_oid;
 
        res = PQexec(g_conn,
-                         "SELECT oid from pg_database where datname = 'template1'");
-       if (res == NULL ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "error in finding the template1 database: %s", PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+                                "SELECT oid FROM pg_class WHERE relname = 'pg_indexes'");
+       check_sql_result(res, g_conn,
+                                        "SELECT oid FROM pg_class WHERE relname = 'pg_indexes'",
+                                        PGRES_TUPLES_OK);
        ntups = PQntuples(res);
        if (ntups < 1)
        {
-               write_msg(NULL, "could not find entry for database template1 in table pg_database\n");
+               write_msg(NULL, "could not find entry for pg_indexes in pg_class\n");
                exit_nicely();
        }
        if (ntups > 1)
        {
-               write_msg(NULL, "found more than one entry for database template1 in table pg_database\n");
+               write_msg(NULL, "found more than one entry for pg_indexes in pg_class\n");
                exit_nicely();
        }
        last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "oid")));
@@ -5863,8 +8013,7 @@ findLastBuiltinOid_V70(void)
 }
 
 static void
-dumpOneSequence(Archive *fout, TableInfo *tbinfo,
-                               const bool schemaOnly, const bool dataOnly)
+dumpSequence(Archive *fout, TableInfo *tbinfo)
 {
        PGresult   *res;
        char       *last,
@@ -5880,45 +8029,41 @@ dumpOneSequence(Archive *fout, TableInfo *tbinfo,
        PQExpBuffer delqry = createPQExpBuffer();
 
        /* Make sure we are in proper schema */
-       selectSourceSchema(tbinfo->relnamespace->nspname);
+       selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
 
        snprintf(bufm, sizeof(bufm), INT64_FORMAT, SEQ_MINVALUE);
        snprintf(bufx, sizeof(bufx), INT64_FORMAT, SEQ_MAXVALUE);
 
        appendPQExpBuffer(query,
                                          "SELECT sequence_name, last_value, increment_by, "
-                          "CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
-                          "     WHEN increment_by < 0 AND max_value = -1 THEN NULL "
+                                  "CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
+                                  "     WHEN increment_by < 0 AND max_value = -1 THEN NULL "
                                          "     ELSE max_value "
                                          "END AS max_value, "
-                               "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
-                          "     WHEN increment_by < 0 AND min_value = %s THEN NULL "
+                                       "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
+                                  "     WHEN increment_by < 0 AND min_value = %s THEN NULL "
                                          "     ELSE min_value "
                                          "END AS min_value, "
                                          "cache_value, is_cycled, is_called from %s",
                                          bufx, bufm,
-                                         fmtId(tbinfo->relname));
+                                         fmtId(tbinfo->dobj.name));
 
        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));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        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->dobj.name, 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->dobj.name) != 0)
        {
                write_msg(NULL, "query to get data of sequence \"%s\" returned name \"%s\"\n",
-                                 tbinfo->relname, PQgetvalue(res, 0, 0));
+                                 tbinfo->dobj.name, PQgetvalue(res, 0, 0));
                exit_nicely();
        }
 #endif
@@ -5936,15 +8081,14 @@ dumpOneSequence(Archive *fout, TableInfo *tbinfo,
        /*
         * The logic we use for restoring sequences is as follows:
         *
-        * Add a basic CREATE SEQUENCE statement (use last_val for start if
-        * called is false, else use min_val for start_val).  Skip this if the
-        * sequence came from a SERIAL column.
+        * Add a CREATE SEQUENCE statement as part of a "schema" dump
+        * (use last_val for start if called is false, else use min_val for
+        * start_val).  Also, if the sequence is owned by a column, add an
+        * ALTER SEQUENCE SET OWNED command for it.
         *
-        * Add a 'SETVAL(seq, last_val, iscalled)' at restore-time iff we load
-        * data.  We do this for serial sequences too.
+        * Add a 'SETVAL(seq, last_val, iscalled)' as part of a "data" dump.
         */
-
-       if (!dataOnly && tbinfo->owning_tab == NULL)
+       if (!dataOnly)
        {
                resetPQExpBuffer(delqry);
 
@@ -5953,14 +8097,14 @@ dumpOneSequence(Archive *fout, TableInfo *tbinfo,
                 * pg_catalog
                 */
                appendPQExpBuffer(delqry, "DROP SEQUENCE %s.",
-                                                 fmtId(tbinfo->relnamespace->nspname));
+                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
                appendPQExpBuffer(delqry, "%s;\n",
-                                                 fmtId(tbinfo->relname));
+                                                 fmtId(tbinfo->dobj.name));
 
                resetPQExpBuffer(query);
                appendPQExpBuffer(query,
                                                  "CREATE SEQUENCE %s\n",
-                                                 fmtId(tbinfo->relname));
+                                                 fmtId(tbinfo->dobj.name));
 
                if (!called)
                        appendPQExpBuffer(query, "    START WITH %s\n", last);
@@ -5978,40 +8122,81 @@ dumpOneSequence(Archive *fout, TableInfo *tbinfo,
                        appendPQExpBuffer(query, "    NO MINVALUE\n");
 
                appendPQExpBuffer(query,
-                                                 "    CACHE %s%s;\n",
+                                                 "    CACHE %s%s",
                                                  cache, (cycled ? "\n    CYCLE" : ""));
 
-               ArchiveEntry(fout, tbinfo->oid, tbinfo->relname,
-                                        tbinfo->relnamespace->nspname, tbinfo->usename,
-                                        "SEQUENCE", NULL,
-                                        query->data, delqry->data,
-                                        NULL, NULL, NULL);
+               appendPQExpBuffer(query, ";\n");
+
+               ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
+                                        tbinfo->dobj.name,
+                                        tbinfo->dobj.namespace->dobj.name,
+                                        NULL,
+                                        tbinfo->rolname,
+                                        false, "SEQUENCE", query->data, delqry->data, NULL,
+                                        tbinfo->dobj.dependencies, tbinfo->dobj.nDeps,
+                                        NULL, NULL);
+
+               /*
+                * If the sequence is owned by a table column, emit the ALTER for it
+                * as a separate TOC entry immediately following the sequence's own
+                * entry.  It's OK to do this rather than using full sorting logic,
+                * because the dependency that tells us it's owned will have forced
+                * the table to be created first.  We can't just include the ALTER
+                * in the TOC entry because it will fail if we haven't reassigned
+                * the sequence owner to match the table's owner.
+                *
+                * We need not schema-qualify the table reference because both
+                * sequence and table must be in the same schema.
+                */
+               if (OidIsValid(tbinfo->owning_tab))
+               {
+                       TableInfo  *owning_tab = findTableByOid(tbinfo->owning_tab);
+
+                       if (owning_tab)
+                       {
+                               resetPQExpBuffer(query);
+                               appendPQExpBuffer(query, "ALTER SEQUENCE %s",
+                                                                 fmtId(tbinfo->dobj.name));
+                               appendPQExpBuffer(query, " OWNED BY %s",
+                                                                 fmtId(owning_tab->dobj.name));
+                               appendPQExpBuffer(query, ".%s;\n",
+                                                                 fmtId(owning_tab->attnames[tbinfo->owning_col - 1]));
+
+                               ArchiveEntry(fout, nilCatalogId, createDumpId(),
+                                                        tbinfo->dobj.name,
+                                                        tbinfo->dobj.namespace->dobj.name,
+                                                        NULL,
+                                                        tbinfo->rolname,
+                                                        false, "SEQUENCE OWNED BY", query->data, "", NULL,
+                                                        &(tbinfo->dobj.dumpId), 1,
+                                                        NULL, NULL);
+                       }
+               }
+
+               /* Dump Sequence Comments */
+               resetPQExpBuffer(query);
+               appendPQExpBuffer(query, "SEQUENCE %s", fmtId(tbinfo->dobj.name));
+               dumpComment(fout, query->data,
+                                       tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
+                                       tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
        }
 
        if (!schemaOnly)
        {
                resetPQExpBuffer(query);
                appendPQExpBuffer(query, "SELECT pg_catalog.setval(");
-               appendStringLiteral(query, fmtId(tbinfo->relname), true);
+               appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout);
                appendPQExpBuffer(query, ", %s, %s);\n",
                                                  last, (called ? "true" : "false"));
 
-               ArchiveEntry(fout, tbinfo->oid, tbinfo->relname,
-                                        tbinfo->relnamespace->nspname, tbinfo->usename,
-                                        "SEQUENCE SET", NULL,
-                                        query->data, "" /* Del */ ,
-                                        NULL, NULL, NULL);
-       }
-
-       if (!dataOnly)
-       {
-               /* Dump Sequence Comments */
-
-               resetPQExpBuffer(query);
-               appendPQExpBuffer(query, "SEQUENCE %s", fmtId(tbinfo->relname));
-               dumpComment(fout, query->data,
-                                       tbinfo->relnamespace->nspname, tbinfo->usename,
-                                       tbinfo->oid, "pg_class", 0, NULL);
+               ArchiveEntry(fout, nilCatalogId, createDumpId(),
+                                        tbinfo->dobj.name,
+                                        tbinfo->dobj.namespace->dobj.name,
+                                        NULL,
+                                        tbinfo->rolname,
+                                        false, "SEQUENCE SET", query->data, "", NULL,
+                                        &(tbinfo->dobj.dumpId), 1,
+                                        NULL, NULL);
        }
 
        PQclear(res);
@@ -6020,538 +8205,398 @@ dumpOneSequence(Archive *fout, TableInfo *tbinfo,
        destroyPQExpBuffer(delqry);
 }
 
-/*
- * dumpConstraints
- *
- * Dump out constraints after all table creation statements in
- * an alter table format.  Currently handles foreign keys only.
- * (Unique and primary key constraints are handled with indexes,
- * while check constraints are merged into the table definition.)
- *
- * XXX Potentially wrap in a 'SET CONSTRAINTS OFF' block so that
- * the current table data is not processed
- */
 static void
-dumpConstraints(Archive *fout, TableInfo *tblinfo, int numTables)
+dumpTrigger(Archive *fout, TriggerInfo *tginfo)
 {
-       int                     i,
-                               j;
+       TableInfo  *tbinfo = tginfo->tgtable;
        PQExpBuffer query;
        PQExpBuffer delqry;
-       PGresult   *res;
-       int                     i_condef,
-                               i_conoid,
-                               i_conname;
-       int                     ntups;
+       const char *p;
+       int                     findx;
 
-       /* pg_constraint was created in 7.3, so nothing to do if older */
-       if (g_fout->remoteVersion < 70300)
+       if (dataOnly)
                return;
 
        query = createPQExpBuffer();
        delqry = createPQExpBuffer();
 
-       for (i = 0; i < numTables; i++)
-       {
-               TableInfo  *tbinfo = &tblinfo[i];
-
-               if (tbinfo->ntrig == 0 || !tbinfo->dump)
-                       continue;
-
-               if (g_verbose)
-                       write_msg(NULL, "dumping foreign key constraints for table \"%s\"\n",
-                                         tbinfo->relname);
-
-               /*
-                * select table schema to ensure regproc name is qualified if
-                * needed
-                */
-               selectSourceSchema(tbinfo->relnamespace->nspname);
-
-               resetPQExpBuffer(query);
-               appendPQExpBuffer(query,
-                                                 "SELECT oid, conname, "
-                                               "pg_catalog.pg_get_constraintdef(oid) as condef "
-                                                 "FROM pg_catalog.pg_constraint "
-                                                 "WHERE conrelid = '%s'::pg_catalog.oid "
-                                                 "AND contype = 'f'",
-                                                 tbinfo->oid);
-               res = PQexec(g_conn, query->data);
-               if (!res ||
-                       PQresultStatus(res) != PGRES_TUPLES_OK)
-               {
-                       write_msg(NULL, "query to obtain list of foreign key definitions failed: %s", PQerrorMessage(g_conn));
-                       exit_nicely();
-               }
-               ntups = PQntuples(res);
-
-               i_conoid = PQfnumber(res, "oid");
-               i_conname = PQfnumber(res, "conname");
-               i_condef = PQfnumber(res, "condef");
-
-               for (j = 0; j < ntups; j++)
-               {
-                       const char *conOid = PQgetvalue(res, j, i_conoid);
-                       const char *conName = PQgetvalue(res, j, i_conname);
-                       const char *conDef = PQgetvalue(res, j, i_condef);
-
-                       resetPQExpBuffer(query);
-                       appendPQExpBuffer(query, "ALTER TABLE ONLY %s\n",
-                                                         fmtId(tbinfo->relname));
-                       appendPQExpBuffer(query, "    ADD CONSTRAINT %s %s;\n",
-                                                         fmtId(conName),
-                                                         conDef);
-
-                       /*
-                        * DROP must be fully qualified in case same name appears in
-                        * pg_catalog
-                        */
-                       resetPQExpBuffer(delqry);
-                       appendPQExpBuffer(delqry, "ALTER TABLE ONLY %s.",
-                                                         fmtId(tbinfo->relnamespace->nspname));
-                       appendPQExpBuffer(delqry, "%s ",
-                                                         fmtId(tbinfo->relname));
-                       appendPQExpBuffer(delqry, "DROP CONSTRAINT %s;\n",
-                                                         fmtId(conName));
-
-                       ArchiveEntry(fout, conOid,
-                                                conName,
-                                                tbinfo->relnamespace->nspname,
-                                                tbinfo->usename,
-                                                "FK CONSTRAINT", NULL,
-                                                query->data, delqry->data,
-                                                NULL, NULL, NULL);
-
-                       resetPQExpBuffer(query);
-                       appendPQExpBuffer(query, "CONSTRAINT %s ",
-                                                         fmtId(conName));
-                       appendPQExpBuffer(query, "ON %s",
-                                                         fmtId(tbinfo->relname));
-
-                       dumpComment(fout, query->data,
-                                               tbinfo->relnamespace->nspname, tbinfo->usename,
-                                               conOid, "pg_constraint", 0, NULL);
-               }
+       /*
+        * DROP must be fully qualified in case same name appears in pg_catalog
+        */
+       appendPQExpBuffer(delqry, "DROP TRIGGER %s ",
+                                         fmtId(tginfo->dobj.name));
+       appendPQExpBuffer(delqry, "ON %s.",
+                                         fmtId(tbinfo->dobj.namespace->dobj.name));
+       appendPQExpBuffer(delqry, "%s;\n",
+                                         fmtId(tbinfo->dobj.name));
 
-               PQclear(res);
+       if (tginfo->tgisconstraint)
+       {
+               appendPQExpBuffer(query, "CREATE CONSTRAINT TRIGGER ");
+               appendPQExpBufferStr(query, fmtId(tginfo->tgconstrname));
        }
+       else
+       {
+               appendPQExpBuffer(query, "CREATE TRIGGER ");
+               appendPQExpBufferStr(query, fmtId(tginfo->dobj.name));
+       }
+       appendPQExpBuffer(query, "\n    ");
 
-       destroyPQExpBuffer(query);
-       destroyPQExpBuffer(delqry);
-}
-
-static void
-dumpTriggers(Archive *fout, TableInfo *tblinfo, int numTables)
-{
-       int                     i,
-                               j;
-       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;
+       /* Trigger type */
+       findx = 0;
+       if (TRIGGER_FOR_BEFORE(tginfo->tgtype))
+               appendPQExpBuffer(query, "BEFORE");
+       else
+               appendPQExpBuffer(query, "AFTER");
+       if (TRIGGER_FOR_INSERT(tginfo->tgtype))
+       {
+               appendPQExpBuffer(query, " INSERT");
+               findx++;
+       }
+       if (TRIGGER_FOR_DELETE(tginfo->tgtype))
+       {
+               if (findx > 0)
+                       appendPQExpBuffer(query, " OR DELETE");
+               else
+                       appendPQExpBuffer(query, " DELETE");
+               findx++;
+       }
+       if (TRIGGER_FOR_UPDATE(tginfo->tgtype))
+       {
+               if (findx > 0)
+                       appendPQExpBuffer(query, " OR UPDATE");
+               else
+                       appendPQExpBuffer(query, " UPDATE");
+       }
+       appendPQExpBuffer(query, " ON %s\n",
+                                         fmtId(tbinfo->dobj.name));
 
-       for (i = 0; i < numTables; i++)
+       if (tginfo->tgisconstraint)
        {
-               TableInfo  *tbinfo = &tblinfo[i];
+               if (OidIsValid(tginfo->tgconstrrelid))
+               {
+                       /* If we are using regclass, name is already quoted */
+                       if (g_fout->remoteVersion >= 70300)
+                               appendPQExpBuffer(query, "    FROM %s\n    ",
+                                                                 tginfo->tgconstrrelname);
+                       else
+                               appendPQExpBuffer(query, "    FROM %s\n    ",
+                                                                 fmtId(tginfo->tgconstrrelname));
+               }
+               if (!tginfo->tgdeferrable)
+                       appendPQExpBuffer(query, "NOT ");
+               appendPQExpBuffer(query, "DEFERRABLE INITIALLY ");
+               if (tginfo->tginitdeferred)
+                       appendPQExpBuffer(query, "DEFERRED\n");
+               else
+                       appendPQExpBuffer(query, "IMMEDIATE\n");
+       }
 
-               if (tbinfo->ntrig == 0 || !tbinfo->dump)
-                       continue;
+       if (TRIGGER_FOR_ROW(tginfo->tgtype))
+               appendPQExpBuffer(query, "    FOR EACH ROW\n    ");
+       else
+               appendPQExpBuffer(query, "    FOR EACH STATEMENT\n    ");
 
-               if (g_verbose)
-                       write_msg(NULL, "dumping triggers for table \"%s\"\n",
-                                         tbinfo->relname);
+       /* In 7.3, result of regproc is already quoted */
+       if (g_fout->remoteVersion >= 70300)
+               appendPQExpBuffer(query, "EXECUTE PROCEDURE %s(",
+                                                 tginfo->tgfname);
+       else
+               appendPQExpBuffer(query, "EXECUTE PROCEDURE %s(",
+                                                 fmtId(tginfo->tgfname));
 
-               /*
-                * select table schema to ensure regproc name is qualified if
-                * needed
-                */
-               selectSourceSchema(tbinfo->relnamespace->nspname);
+       p = tginfo->tgargs;
+       for (findx = 0; findx < tginfo->tgnargs; findx++)
+       {
+               const char *s = p;
 
-               resetPQExpBuffer(query);
-               if (g_fout->remoteVersion >= 70300)
-               {
-                       /*
-                        * We ignore triggers that are tied to a foreign-key
-                        * constraint
-                        */
-                       appendPQExpBuffer(query,
-                                                         "SELECT tgname, "
-                                                         "tgfoid::pg_catalog.regproc as tgfname, "
-                                                         "tgtype, tgnargs, tgargs, "
-                                                  "tgisconstraint, tgconstrname, tgdeferrable, "
-                                                         "tgconstrrelid, tginitdeferred, oid, "
-                                "tgconstrrelid::pg_catalog.regclass as tgconstrrelname "
-                                                         "from pg_catalog.pg_trigger t "
-                                                         "where tgrelid = '%s'::pg_catalog.oid "
-                                                         "and (not tgisconstraint "
-                                                         " OR NOT EXISTS"
-                                                         "  (SELECT 1 FROM pg_catalog.pg_depend d "
-                                                         "   JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) "
-                                                         "   WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))",
-                                                         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)
+               /* Set 'p' to end of arg string. marked by '\000' */
+               for (;;)
                {
-                       write_msg(NULL, "query to obtain list of triggers failed: %s", PQerrorMessage(g_conn));
-                       exit_nicely();
+                       p = strchr(p, '\\');
+                       if (p == NULL)
+                       {
+                               write_msg(NULL, "invalid argument string (%s) for trigger \"%s\" on table \"%s\"\n",
+                                                 tginfo->tgargs,
+                                                 tginfo->dobj.name,
+                                                 tbinfo->dobj.name);
+                               exit_nicely();
+                       }
+                       p++;
+                       if (*p == '\\')         /* is it '\\'? */
+                       {
+                               p++;
+                               continue;
+                       }
+                       if (p[0] == '0' && p[1] == '0' && p[2] == '0')          /* is it '\000'? */
+                               break;
                }
-               ntups = PQntuples(res);
+               p--;
 
-               /*
-                * We may have less triggers than recorded due to constraint
-                * triggers which are dumped by dumpConstraints
-                */
-               if (ntups > tbinfo->ntrig)
+               appendPQExpBufferChar(query, '\'');
+               while (s < p)
                {
-                       write_msg(NULL, "expected %d triggers on table \"%s\" but found %d\n",
-                                         tbinfo->ntrig, tbinfo->relname, ntups);
-                       exit_nicely();
+                       if (*s == '\'')
+                               appendPQExpBufferChar(query, '\'');
+                       /*
+                        *      bytea unconditionally doubles backslashes, so we suppress
+                        *      the doubling for standard_conforming_strings.
+                        */
+                       if (fout->std_strings && *s == '\\' && s[1] == '\\')
+                               s++;
+                       appendPQExpBufferChar(query, *s++);
                }
-               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++)
-               {
-                       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;
+               appendPQExpBufferChar(query, '\'');
+               appendPQExpBuffer(query,
+                                                 (findx < tginfo->tgnargs - 1) ? ", " : "");
+               p = p + 4;
+       }
+       appendPQExpBuffer(query, ");\n");
 
-                       if (strcmp(PQgetvalue(res, j, i_tgdeferrable), "f") == 0)
-                               tgdeferrable = 0;
-                       else
-                               tgdeferrable = 1;
+       if (!tginfo->tgenabled)
+       {
+               appendPQExpBuffer(query, "\nALTER TABLE %s ",
+                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(query, "DISABLE TRIGGER %s;\n",
+                                                 fmtId(tginfo->dobj.name));
+       }
 
-                       if (strcmp(PQgetvalue(res, j, i_tginitdeferred), "f") == 0)
-                               tginitdeferred = 0;
-                       else
-                               tginitdeferred = 1;
+       ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId,
+                                tginfo->dobj.name,
+                                tbinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                tbinfo->rolname, false,
+                                "TRIGGER", query->data, delqry->data, NULL,
+                                tginfo->dobj.dependencies, tginfo->dobj.nDeps,
+                                NULL, NULL);
 
-                       resetPQExpBuffer(delqry);
+       resetPQExpBuffer(query);
+       appendPQExpBuffer(query, "TRIGGER %s ",
+                                         fmtId(tginfo->dobj.name));
+       appendPQExpBuffer(query, "ON %s",
+                                         fmtId(tbinfo->dobj.name));
 
-                       /*
-                        * DROP must be fully qualified in case same name appears in
-                        * pg_catalog
-                        */
-                       appendPQExpBuffer(delqry, "DROP TRIGGER %s ",
-                                                         fmtId(tgname));
-                       appendPQExpBuffer(delqry, "ON %s.",
-                                                         fmtId(tbinfo->relnamespace->nspname));
-                       appendPQExpBuffer(delqry, "%s;\n",
-                                                         fmtId(tbinfo->relname));
+       dumpComment(fout, query->data,
+                               tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
+                               tginfo->dobj.catId, 0, tginfo->dobj.dumpId);
 
-                       resetPQExpBuffer(query);
-                       if (tgisconstraint)
-                       {
-                               appendPQExpBuffer(query, "CREATE CONSTRAINT TRIGGER ");
-                               appendPQExpBuffer(query, fmtId(PQgetvalue(res, j, i_tgconstrname)));
-                       }
-                       else
-                       {
-                               appendPQExpBuffer(query, "CREATE TRIGGER ");
-                               appendPQExpBuffer(query, fmtId(tgname));
-                       }
-                       appendPQExpBuffer(query, "\n    ");
-                       /* 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\n",
-                                                         fmtId(tbinfo->relname));
+       destroyPQExpBuffer(query);
+       destroyPQExpBuffer(delqry);
+}
 
-                       if (tgisconstraint)
-                       {
-                               tgconstrrelid = PQgetvalue(res, j, i_tgconstrrelid);
+/*
+ * dumpRule
+ *             Dump a rule
+ */
+static void
+dumpRule(Archive *fout, RuleInfo *rinfo)
+{
+       TableInfo  *tbinfo = rinfo->ruletable;
+       PQExpBuffer query;
+       PQExpBuffer cmd;
+       PQExpBuffer delcmd;
+       PGresult   *res;
 
-                               if (strcmp(tgconstrrelid, "0") != 0)
-                               {
+       /* Skip if not to be dumped */
+       if (!rinfo->dobj.dump || dataOnly)
+               return;
 
-                                       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 it is an ON SELECT rule that is created implicitly by CREATE VIEW,
+        * we do not want to dump it as a separate object.
+        */
+       if (!rinfo->separate)
+               return;
 
-                                       /* If we are using regclass, name is already quoted */
-                                       if (g_fout->remoteVersion >= 70300)
-                                               appendPQExpBuffer(query, "    FROM %s\n    ",
-                                                                 PQgetvalue(res, j, i_tgconstrrelname));
-                                       else
-                                               appendPQExpBuffer(query, "    FROM %s\n    ",
-                                                  fmtId(PQgetvalue(res, j, i_tgconstrrelname)));
-                               }
-                               if (!tgdeferrable)
-                                       appendPQExpBuffer(query, "NOT ");
-                               appendPQExpBuffer(query, "DEFERRABLE INITIALLY ");
-                               if (tginitdeferred)
-                                       appendPQExpBuffer(query, "DEFERRED\n");
-                               else
-                                       appendPQExpBuffer(query, "IMMEDIATE\n");
+       /*
+        * Make sure we are in proper schema.
+        */
+       selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
 
-                       }
+       query = createPQExpBuffer();
+       cmd = createPQExpBuffer();
+       delcmd = createPQExpBuffer();
 
-                       if (TRIGGER_FOR_ROW(tgtype))
-                               appendPQExpBuffer(query, "    FOR EACH ROW\n    ");
-                       else
-                               appendPQExpBuffer(query, "    FOR EACH STATEMENT\n    ");
+       if (g_fout->remoteVersion >= 70300)
+       {
+               appendPQExpBuffer(query,
+                                                 "SELECT pg_catalog.pg_get_ruledef('%u'::pg_catalog.oid) AS definition",
+                                                 rinfo->dobj.catId.oid);
+       }
+       else
+       {
+               /* Rule name was unique before 7.3 ... */
+               appendPQExpBuffer(query,
+                                                 "SELECT pg_get_ruledef('%s') AS definition",
+                                                 rinfo->dobj.name);
+       }
 
-                       /* 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));
-                       for (findx = 0; findx < tgnargs; findx++)
-                       {
-                               const char *s;
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
-                               for (p = tgargs;;)
-                               {
-                                       p = strchr(p, '\\');
-                                       if (p == NULL)
-                                       {
-                                               write_msg(NULL, "invalid 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");
+       if (PQntuples(res) != 1)
+       {
+               write_msg(NULL, "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned",
+                                 rinfo->dobj.name, tbinfo->dobj.name);
+               exit_nicely();
+       }
 
-                       ArchiveEntry(fout, tgoid,
-                                                tgname,
-                                                tbinfo->relnamespace->nspname,
-                                                tbinfo->usename,
-                                                "TRIGGER", NULL,
-                                                query->data, delqry->data,
-                                                NULL, NULL, NULL);
+       printfPQExpBuffer(cmd, "%s\n", PQgetvalue(res, 0, 0));
 
-                       resetPQExpBuffer(query);
-                       appendPQExpBuffer(query, "TRIGGER %s ",
-                                                         fmtId(tgname));
-                       appendPQExpBuffer(query, "ON %s",
-                                                         fmtId(tbinfo->relname));
-
-                       dumpComment(fout, query->data,
-                                               tbinfo->relnamespace->nspname, tbinfo->usename,
-                                               tgoid, "pg_trigger", 0, NULL);
-               }
+       /*
+        * DROP must be fully qualified in case same name appears in pg_catalog
+        */
+       appendPQExpBuffer(delcmd, "DROP RULE %s ",
+                                         fmtId(rinfo->dobj.name));
+       appendPQExpBuffer(delcmd, "ON %s.",
+                                         fmtId(tbinfo->dobj.namespace->dobj.name));
+       appendPQExpBuffer(delcmd, "%s;\n",
+                                         fmtId(tbinfo->dobj.name));
+
+       ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId,
+                                rinfo->dobj.name,
+                                tbinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                tbinfo->rolname, false,
+                                "RULE", cmd->data, delcmd->data, NULL,
+                                rinfo->dobj.dependencies, rinfo->dobj.nDeps,
+                                NULL, NULL);
+
+       /* Dump rule comments */
+       resetPQExpBuffer(query);
+       appendPQExpBuffer(query, "RULE %s",
+                                         fmtId(rinfo->dobj.name));
+       appendPQExpBuffer(query, " ON %s",
+                                         fmtId(tbinfo->dobj.name));
+       dumpComment(fout, query->data,
+                               tbinfo->dobj.namespace->dobj.name,
+                               tbinfo->rolname,
+                               rinfo->dobj.catId, 0, rinfo->dobj.dumpId);
 
-               PQclear(res);
-       }
+       PQclear(res);
 
        destroyPQExpBuffer(query);
-       destroyPQExpBuffer(delqry);
+       destroyPQExpBuffer(cmd);
+       destroyPQExpBuffer(delcmd);
 }
 
-
+/*
+ * getDependencies --- obtain available dependency data
+ */
 static void
-dumpRules(Archive *fout, TableInfo *tblinfo, int numTables)
+getDependencies(void)
 {
+       PQExpBuffer query;
        PGresult   *res;
-       int                     nrules;
-       int                     i,
-                               t;
-       PQExpBuffer query = createPQExpBuffer();
-       PQExpBuffer cmd = createPQExpBuffer();
-       int                     i_definition;
-       int                     i_oid;
-       int                     i_rulename;
+       int                     ntups,
+                               i;
+       int                     i_classid,
+                               i_objid,
+                               i_refclassid,
+                               i_refobjid,
+                               i_deptype;
+       DumpableObject *dobj,
+                          *refdobj;
+
+       /* No dependency info available before 7.3 */
+       if (g_fout->remoteVersion < 70300)
+               return;
 
        if (g_verbose)
-               write_msg(NULL, "dumping out rules\n");
+               write_msg(NULL, "reading dependency data\n");
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       query = createPQExpBuffer();
+
+       appendPQExpBuffer(query, "SELECT "
+                                         "classid, objid, refclassid, refobjid, deptype "
+                                         "FROM pg_depend "
+                                         "WHERE deptype != 'p' "
+                                         "ORDER BY 1,2");
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       ntups = PQntuples(res);
+
+       i_classid = PQfnumber(res, "classid");
+       i_objid = PQfnumber(res, "objid");
+       i_refclassid = PQfnumber(res, "refclassid");
+       i_refobjid = PQfnumber(res, "refobjid");
+       i_deptype = PQfnumber(res, "deptype");
 
        /*
-        * For each table we dump
+        * Since we ordered the SELECT by referencing ID, we can expect that
+        * multiple entries for the same object will appear together; this saves
+        * on searches.
         */
-       for (t = 0; t < numTables; t++)
+       dobj = NULL;
+
+       for (i = 0; i < ntups; i++)
        {
-               TableInfo  *tbinfo = &tblinfo[t];
+               CatalogId       objId;
+               CatalogId       refobjId;
+               char            deptype;
 
-               if (!tbinfo->hasrules || !tbinfo->dump)
-                       continue;
+               objId.tableoid = atooid(PQgetvalue(res, i, i_classid));
+               objId.oid = atooid(PQgetvalue(res, i, i_objid));
+               refobjId.tableoid = atooid(PQgetvalue(res, i, i_refclassid));
+               refobjId.oid = atooid(PQgetvalue(res, i, i_refobjid));
+               deptype = *(PQgetvalue(res, i, i_deptype));
 
-               /* Make sure we are in proper schema */
-               selectSourceSchema(tbinfo->relnamespace->nspname);
+               if (dobj == NULL ||
+                       dobj->catId.tableoid != objId.tableoid ||
+                       dobj->catId.oid != objId.oid)
+                       dobj = findObjectByCatalogId(objId);
 
                /*
-                * Get all rules defined for this table, except view select rules
+                * Failure to find objects mentioned in pg_depend is not unexpected,
+                * since for example we don't collect info about TOAST tables.
                 */
-               resetPQExpBuffer(query);
-
-               if (g_fout->remoteVersion >= 70300)
-               {
-                       appendPQExpBuffer(query,
-                                  "SELECT pg_catalog.pg_get_ruledef(oid) AS definition,"
-                                                         " oid, rulename "
-                                                         "FROM pg_catalog.pg_rewrite "
-                                                         "WHERE ev_class = '%s'::pg_catalog.oid "
-                                                         "AND rulename != '_RETURN' "
-                                                         "ORDER BY oid",
-                                                         tbinfo->oid);
-               }
-               else
+               if (dobj == NULL)
                {
-                       /*
-                        * We include pg_rules in the cross since it filters out all
-                        * view rules (pjw 15-Sep-2000).
-                        */
-                       appendPQExpBuffer(query, "SELECT definition,"
-                                                         "   pg_rewrite.oid, pg_rewrite.rulename "
-                                                         "FROM pg_rewrite, pg_class, pg_rules "
-                                                         "WHERE pg_class.relname = ");
-                       appendStringLiteral(query, tbinfo->relname, true);
-                       appendPQExpBuffer(query,
-                                                       "    AND pg_rewrite.ev_class = pg_class.oid "
-                                                "    AND pg_rules.tablename = pg_class.relname "
-                                          "    AND pg_rules.rulename = pg_rewrite.rulename "
-                                                         "ORDER BY pg_rewrite.oid");
+#ifdef NOT_USED
+                       fprintf(stderr, "no referencing object %u %u\n",
+                                       objId.tableoid, objId.oid);
+#endif
+                       continue;
                }
 
-               res = PQexec(g_conn, query->data);
-               if (!res ||
-                       PQresultStatus(res) != PGRES_TUPLES_OK)
+               refdobj = findObjectByCatalogId(refobjId);
+
+               if (refdobj == NULL)
                {
-                       write_msg(NULL, "query to get rules associated with table \"%s\" failed: %s",
-                                         tbinfo->relname, PQerrorMessage(g_conn));
-                       exit_nicely();
+#ifdef NOT_USED
+                       fprintf(stderr, "no referenced object %u %u\n",
+                                       refobjId.tableoid, refobjId.oid);
+#endif
+                       continue;
                }
 
-               nrules = PQntuples(res);
-               i_definition = PQfnumber(res, "definition");
-               i_oid = PQfnumber(res, "oid");
-               i_rulename = PQfnumber(res, "rulename");
-
                /*
-                * Dump them out
+                * Ordinarily, table rowtypes have implicit dependencies on their
+                * tables.      However, for a composite type the implicit dependency goes
+                * the other way in pg_depend; which is the right thing for DROP but
+                * it doesn't produce the dependency ordering we need. So in that one
+                * case, we reverse the direction of the dependency.
                 */
-
-               for (i = 0; i < nrules; i++)
-               {
-                       printfPQExpBuffer(cmd, "%s\n", PQgetvalue(res, i, i_definition));
-                       ArchiveEntry(fout, PQgetvalue(res, i, i_oid),
-                                                PQgetvalue(res, i, i_rulename),
-                                                tbinfo->relnamespace->nspname,
-                                                tbinfo->usename,
-                                                "RULE", NULL,
-                                                cmd->data,
-                                                "",    /* Del */
-                                                NULL, NULL, NULL);
-
-                       /* Dump rule comments */
-
-                       resetPQExpBuffer(query);
-                       appendPQExpBuffer(query, "RULE %s", fmtId(PQgetvalue(res, i, i_rulename)));
-                       appendPQExpBuffer(query, " ON %s", fmtId(tbinfo->relname));
-                       dumpComment(fout, query->data,
-                                               tbinfo->relnamespace->nspname,
-                                               tbinfo->usename,
-                                               PQgetvalue(res, i, i_oid), "pg_rewrite", 0, NULL);
-
-               }
-
-               PQclear(res);
+               if (deptype == 'i' &&
+                       dobj->objType == DO_TABLE &&
+                       refdobj->objType == DO_TYPE)
+                       addObjectDependency(refdobj, dobj->dumpId);
+               else
+                       /* normal case */
+                       addObjectDependency(dobj, refdobj->dumpId);
        }
 
+       PQclear(res);
+
        destroyPQExpBuffer(query);
-       destroyPQExpBuffer(cmd);
 }
 
+
 /*
  * selectSourceSchema - make the specified schema the active search path
  * in the source database.
@@ -6569,7 +8614,6 @@ 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)
@@ -6586,17 +8630,10 @@ selectSourceSchema(const char *schemaName)
                                          fmtId(schemaName));
        if (strcmp(schemaName, "pg_catalog") != 0)
                appendPQExpBuffer(query, ", pg_catalog");
-       res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_COMMAND_OK)
-       {
-               write_msg(NULL, "command to set search_path failed: %s",
-                                 PQerrorMessage(g_conn));
-               exit_nicely();
-       }
-       PQclear(res);
-       destroyPQExpBuffer(query);
 
+       do_sql_command(g_conn, query->data);
+
+       destroyPQExpBuffer(query);
        if (curSchemaName)
                free(curSchemaName);
        curSchemaName = strdup(schemaName);
@@ -6610,14 +8647,14 @@ selectSourceSchema(const char *schemaName)
  * schema; this is why we don't try to cache the names.
  */
 static char *
-getFormattedTypeName(const char *oid, OidOptions opts)
+getFormattedTypeName(Oid oid, OidOptions opts)
 {
        char       *result;
        PQExpBuffer query;
        PGresult   *res;
        int                     ntups;
 
-       if (atooid(oid) == 0)
+       if (oid == 0)
        {
                if ((opts & zeroAsOpaque) != 0)
                        return strdup(g_opaque_type);
@@ -6632,30 +8669,24 @@ getFormattedTypeName(const char *oid, OidOptions opts)
        query = createPQExpBuffer();
        if (g_fout->remoteVersion >= 70300)
        {
-               appendPQExpBuffer(query, "SELECT pg_catalog.format_type('%s'::pg_catalog.oid, NULL)",
+               appendPQExpBuffer(query, "SELECT pg_catalog.format_type('%u'::pg_catalog.oid, NULL)",
                                                  oid);
        }
        else if (g_fout->remoteVersion >= 70100)
        {
-               appendPQExpBuffer(query, "SELECT format_type('%s'::oid, NULL)",
+               appendPQExpBuffer(query, "SELECT format_type('%u'::oid, NULL)",
                                                  oid);
        }
        else
        {
                appendPQExpBuffer(query, "SELECT typname "
                                                  "FROM pg_type "
-                                                 "WHERE oid = '%s'::oid",
+                                                 "WHERE oid = '%u'::oid",
                                                  oid);
        }
 
        res = PQexec(g_conn, query->data);
-       if (!res ||
-               PQresultStatus(res) != PGRES_TUPLES_OK)
-       {
-               write_msg(NULL, "query to obtain name of data type %s failed: %s",
-                                 oid, PQerrorMessage(g_conn));
-               exit_nicely();
-       }
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
 
        /* Expecting a single result only */
        ntups = PQntuples(res);
@@ -6690,8 +8721,16 @@ static char *
 myFormatType(const char *typname, int32 typmod)
 {
        char       *result;
+       bool            isarray = false;
        PQExpBuffer buf = createPQExpBuffer();
 
+       /* Handle array types */
+       if (typname[0] == '_')
+       {
+               isarray = true;
+               typname++;
+       }
+
        /* Show lengths on bpchar and varchar */
        if (!strcmp(typname, "bpchar"))
        {
@@ -6727,14 +8766,18 @@ myFormatType(const char *typname, int32 typmod)
        }
 
        /*
-        * char is an internal single-byte data type; Let's make sure we force
-        * it through with quotes. - thomas 1998-12-13
+        * 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") == 0)
                appendPQExpBuffer(buf, "\"char\"");
        else
                appendPQExpBuffer(buf, "%s", fmtId(typname));
 
+       /* Append array qualifier for array types */
+       if (isarray)
+               appendPQExpBuffer(buf, "[]");
+
        result = strdup(buf->data);
        destroyPQExpBuffer(buf);
 
@@ -6808,3 +8851,40 @@ fmtCopyColumnList(const TableInfo *ti)
        appendPQExpBuffer(q, ")");
        return q->data;
 }
+
+/*
+ * Convenience subroutine to execute a SQL command and check for
+ * COMMAND_OK status.
+ */
+static void
+do_sql_command(PGconn *conn, const char *query)
+{
+       PGresult   *res;
+
+       res = PQexec(conn, query);
+       check_sql_result(res, conn, query, PGRES_COMMAND_OK);
+       PQclear(res);
+}
+
+/*
+ * Convenience subroutine to verify a SQL command succeeded,
+ * and exit with a useful error message if not.
+ */
+static void
+check_sql_result(PGresult *res, PGconn *conn, const char *query,
+                                ExecStatusType expected)
+{
+       const char *err;
+
+       if (res && PQresultStatus(res) == expected)
+               return;                                 /* A-OK */
+
+       write_msg(NULL, "SQL command failed\n");
+       if (res)
+               err = PQresultErrorMessage(res);
+       else
+               err = PQerrorMessage(conn);
+       write_msg(NULL, "Error message from server: %s", err);
+       write_msg(NULL, "The command was: %s\n", query);
+       exit_nicely();
+}