]> 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 102cbc0f4acc9ba1afaaed47692fef42c743d29e..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
- *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.361 2003/12/19 14:21:56 petere 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))
-
 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. */
@@ -80,11 +85,25 @@ 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 */
 
@@ -92,12 +111,15 @@ 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 };
+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);
@@ -105,12 +127,16 @@ 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);
@@ -126,6 +152,7 @@ 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,
@@ -135,28 +162,38 @@ static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
 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 setMaxOid(Archive *fout);
 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);
+                                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";
@@ -164,19 +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;
        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;
@@ -201,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;
 
@@ -242,10 +282,7 @@ main(int argc, char **argv)
 
        /* Set default options based on progname */
        if (strcmp(progname, "pg_backup") == 0)
-       {
                format = "c";
-               outputBlobs = true;
-       }
 
        if (argc > 1)
        {
@@ -261,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)
@@ -271,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;
 
@@ -293,6 +329,10 @@ main(int argc, char **argv)
                                attrNames = true;
                                break;
 
+                       case 'E':                       /* Dump encoding */
+                               dumpencoding = optarg;
+                               break;
+
                        case 'f':
                                filename = optarg;
                                break;
@@ -309,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 */
@@ -331,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);
@@ -364,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,
@@ -424,19 +496,8 @@ 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 (dumpInserts == true && oids == true)
        {
@@ -445,13 +506,6 @@ main(int argc, char **argv)
                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])
        {
@@ -499,12 +553,35 @@ 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);
+               }
+       }
+
+       /*
+        * Get the active encoding and the standard_conforming_strings setting,
+        * so we know how to escape strings.
+        */
+       g_fout->encoding = PQclientEncoding(g_conn);
+
+       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 */
+       do_sql_command(g_conn, "SET DATESTYLE = ISO");
+
        /*
         * Start serializable transaction to dump consistent data.
         */
@@ -512,8 +589,13 @@ main(int argc, char **argv)
 
        do_sql_command(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
 
-       /* Set the datestyle to ISO to ensure the dump's portability */
-       do_sql_command(g_conn, "SET DATESTYLE = ISO");
+       /* 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
@@ -533,15 +615,189 @@ main(int argc, char **argv)
                        write_msg(NULL, "last built-in OID is %u\n", g_last_builtin_oid);
        }
 
+
+       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;
+
+       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");
+               }
+       }
+
+       /* 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, schemaOnly, dataOnly);
+       tblinfo = getSchemaData(&numTables);
 
        if (!schemaOnly)
                getTableData(tblinfo, numTables, oids);
 
+       if (outputBlobs && hasBlobs(g_fout))
+       {
+               /* 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");
+       }
+
        /*
         * Collect dependency data to assist in ordering the objects.
         */
@@ -549,38 +805,38 @@ main(int argc, char **argv)
 
        /*
         * 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);
 
-       sortDumpableObjectsByType(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.
+        * Create archive TOC entries for all the objects to be dumped, in a safe
+        * order.
         */
 
-       /* The database item is always first. */
-       if (!dataOnly)
-               dumpDatabase(g_fout);
+       /* First the special ENCODING and STDSTRINGS entries. */
+       dumpEncoding(g_fout);
+       dumpStdStrings(g_fout);
 
-       /* Max OID is second. */
-       if (oids == true)
-               setMaxOid(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]);
-       }
-
-       /* BLOBs are always last. */
-       if (outputBlobs)
-               ArchiveEntry(g_fout, nilCatalogId, createDumpId(),
-                                        "BLOBS", NULL, "",
-                                        "BLOBS", "", "", NULL,
-                                        NULL, 0,
-                                        dumpBlobs, NULL);
 
        /*
         * And finally we can do the actual output.
@@ -595,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);
        }
@@ -633,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"));
@@ -679,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;
 }
 
 /*
@@ -708,21 +976,75 @@ 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;
 }
 
 /*
@@ -731,21 +1053,18 @@ selectDumpableTable(TableInfo *tbinfo)
  *       to be dumped.
  */
 
-#define COPYBUFSIZ             8192
-
 static int
 dumpTableData_copy(Archive *fout, void *dcontext)
 {
        TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
        TableInfo  *tbinfo = tdinfo->tdtable;
-       const char *classname = tbinfo->relname;
+       const char *classname = tbinfo->dobj.name;
        const bool      hasoids = tbinfo->hasoids;
        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)
@@ -753,17 +1072,17 @@ dumpTableData_copy(Archive *fout, void *dcontext)
 
        /*
         * 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);
@@ -773,101 +1092,90 @@ dumpTableData_copy(Archive *fout, void *dcontext)
        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);
        check_sql_result(res, g_conn, q->data, PGRES_COPY_OUT);
+       PQclear(res);
 
-       copydone = false;
-
-       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:
-                                       archputs("\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;
 }
@@ -877,7 +1185,7 @@ dumpTableData_insert(Archive *fout, void *dcontext)
 {
        TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
        TableInfo  *tbinfo = tdinfo->tdtable;
-       const char *classname = tbinfo->relname;
+       const char *classname = tbinfo->dobj.name;
        PQExpBuffer q = createPQExpBuffer();
        PGresult   *res;
        int                     tuple;
@@ -886,24 +1194,24 @@ dumpTableData_insert(Archive *fout, void *dcontext)
 
        /*
         * 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));
        }
 
@@ -935,10 +1243,10 @@ dumpTableData_insert(Archive *fout, void *dcontext)
                                {
                                        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++)
@@ -963,16 +1271,15 @@ dumpTableData_insert(Archive *fout, void *dcontext)
                                        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);
 
@@ -999,8 +1306,10 @@ dumpTableData_insert(Archive *fout, void *dcontext)
                                        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;
                                }
                        }
@@ -1039,10 +1348,10 @@ dumpTableData(Archive *fout, TableDataInfo *tdinfo)
                dumpFn = dumpTableData_copy;
                /* must use 2 steps here 'cause fmtId is nonreentrant */
                appendPQExpBuffer(copyBuf, "COPY %s ",
-                                                 fmtId(tbinfo->relname));
+                                                 fmtId(tbinfo->dobj.name));
                appendPQExpBuffer(copyBuf, "%s %sFROM stdin;\n",
                                                  fmtCopyColumnList(tbinfo),
-                                                 (tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : "");
+                                         (tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : "");
                copyStmt = copyBuf->data;
        }
        else
@@ -1053,9 +1362,10 @@ dumpTableData(Archive *fout, TableDataInfo *tdinfo)
        }
 
        ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
-                                tbinfo->relname,
-                                tbinfo->relnamespace->nspname,
-                                tbinfo->usename,
+                                tbinfo->dobj.name,
+                                tbinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                tbinfo->rolname, false,
                                 "TABLE DATA", "", "", copyStmt,
                                 tdinfo->dobj.dependencies, tdinfo->dobj.nDeps,
                                 dumpFn, tdinfo);
@@ -1081,20 +1391,23 @@ getTableData(TableInfo *tblinfo, int numTables, bool oids)
                if (tblinfo[i].relkind == RELKIND_SEQUENCE)
                        continue;
 
-               if (tblinfo[i].dump)
+               if (tblinfo[i].dobj.dump)
                {
                        TableDataInfo *tdinfo;
 
                        tdinfo = (TableDataInfo *) malloc(sizeof(TableDataInfo));
 
                        tdinfo->dobj.objType = DO_TABLE_DATA;
+
                        /*
-                        * Note: use tableoid 0 so that this object won't be mistaken
-                        * for something that pg_depend entries apply to.
+                        * 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);
@@ -1119,13 +1432,13 @@ dumpDatabase(Archive *AH)
                                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);
 
@@ -1136,27 +1449,53 @@ dumpDatabase(Archive *AH)
        selectSourceSchema("pg_catalog");
 
        /* Get the database owner and parameters from pg_database */
-       if (g_fout->remoteVersion >= 70100)
+       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)
        {
                appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
-                                                 "(SELECT usename FROM pg_user WHERE usesysid = datdba) as dba, "
+                                                 "(%s datdba) as dba, "
                                                  "pg_encoding_to_char(encoding) as encoding, "
-                                                 "datpath "
+                                                 "NULL as tablespace "
                                                  "FROM pg_database "
-                                                 "WHERE datname = ");
-               appendStringLiteral(dbQry, datname, true);
+                                                 "WHERE datname = ",
+                                                 username_subquery);
+               appendStringLiteralAH(dbQry, datname, AH);
        }
        else
        {
                appendPQExpBuffer(dbQry, "SELECT "
                                                  "(SELECT oid FROM pg_class WHERE relname = 'pg_database') AS tableoid, "
                                                  "oid, "
-                                                 "(SELECT usename FROM pg_user WHERE usesysid = datdba) as dba, "
+                                                 "(%s datdba) as dba, "
                                                  "pg_encoding_to_char(encoding) as encoding, "
-                                                 "datpath "
+                                                 "NULL as tablespace "
                                                  "FROM pg_database "
-                                                 "WHERE datname = ");
-               appendStringLiteral(dbQry, datname, true);
+                                                 "WHERE datname = ",
+                                                 username_subquery);
+               appendStringLiteralAH(dbQry, datname, AH);
        }
 
        res = PQexec(g_conn, dbQry->data);
@@ -1182,26 +1521,24 @@ dumpDatabase(Archive *AH)
        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",
@@ -1214,7 +1551,9 @@ dumpDatabase(Archive *AH)
                                 dbDumpId,              /* dump ID */
                                 datname,               /* Name */
                                 NULL,                  /* Namespace */
+                                NULL,                  /* Tablespace */
                                 dba,                   /* Owner */
+                                false,                 /* with oids */
                                 "DATABASE",    /* Desc */
                                 creaQry->data, /* Create */
                                 delQry->data,  /* Del */
@@ -1225,10 +1564,28 @@ dumpDatabase(Archive *AH)
                                 NULL);                 /* Dumper Arg */
 
        /* Dump DB comment if any */
-       resetPQExpBuffer(dbQry);
-       appendPQExpBuffer(dbQry, "DATABASE %s", fmtId(datname));
-       dumpComment(AH, dbQry->data, NULL, "",
+       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);
 
@@ -1239,57 +1596,135 @@ dumpDatabase(Archive *AH)
 
 
 /*
- * dumpBlobs:
- *     dump all blobs
- *
+ * dumpEncoding: put the correct encoding into the archive
  */
-
-#define loBufSize 16384
-#define loFetchSize 1000
-
-static int
-dumpBlobs(Archive *AH, void *arg)
+static void
+dumpEncoding(Archive *AH)
 {
-       PQExpBuffer oidQry = createPQExpBuffer();
-       PQExpBuffer oidFetchQry = createPQExpBuffer();
-       PGresult   *res;
-       int                     i;
-       int                     loFd;
-       char            buf[loBufSize];
-       int                     cnt;
-       Oid                     blobOid;
+       const char *encname = pg_encoding_to_char(AH->encoding);
+       PQExpBuffer qry = createPQExpBuffer();
 
        if (g_verbose)
-               write_msg(NULL, "saving large objects\n");
+               write_msg(NULL, "saving encoding = %s\n", encname);
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema("pg_catalog");
+       appendPQExpBuffer(qry, "SET client_encoding = ");
+       appendStringLiteralAH(qry, encname, AH);
+       appendPQExpBuffer(qry, ";\n");
 
-       /* Cursor to get all BLOB tables */
-       if (AH->remoteVersion >= 70100)
-               appendPQExpBuffer(oidQry, "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'");
+       ArchiveEntry(AH, nilCatalogId, createDumpId(),
+                                "ENCODING", NULL, NULL, "",
+                                false, "ENCODING", qry->data, "", NULL,
+                                NULL, 0,
+                                NULL, NULL);
 
-       res = PQexec(g_conn, oidQry->data);
-       check_sql_result(res, g_conn, oidQry->data, PGRES_COMMAND_OK);
+       destroyPQExpBuffer(qry);
+}
 
-       /* Fetch for cursor */
-       appendPQExpBuffer(oidFetchQry, "Fetch %d in blobOid", loFetchSize);
 
-       do
-       {
-               /* Do a fetch */
-               PQclear(res);
+/*
+ * 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();
 
-               res = PQexec(g_conn, oidFetchQry->data);
-               check_sql_result(res, g_conn, oidFetchQry->data, PGRES_TUPLES_OK);
+       if (g_verbose)
+               write_msg(NULL, "saving standard_conforming_strings = %s\n",
+                                 stdstrings);
 
-               /* Process the tuples, if any */
-               for (i = 0; i < PQntuples(res); i++)
-               {
-                       blobOid = atooid(PQgetvalue(res, i, 0));
-                       /* Open the BLOB */
+       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;
+
+       /* 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, void *arg)
+{
+       const char *blobQry;
+       const char *blobFetchQry;
+       PGresult   *res;
+       char            buf[LOBBUFSIZE];
+       int                     i;
+       int                     cnt;
+
+       if (g_verbose)
+               write_msg(NULL, "saving large objects\n");
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       /* Cursor to get all BLOB OIDs */
+       if (AH->remoteVersion >= 70100)
+               blobQry = "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject";
+       else
+               blobQry = "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_class 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 1000 IN bloboid";
+
+       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;
+                       int                     loFd;
+
+                       blobOid = atooid(PQgetvalue(res, i, 0));
+                       /* Open the BLOB */
                        loFd = lo_open(g_conn, blobOid, INV_READ);
                        if (loFd == -1)
                        {
@@ -1303,7 +1738,7 @@ dumpBlobs(Archive *AH, void *arg)
                        /* 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",
@@ -1312,18 +1747,91 @@ dumpBlobs(Archive *AH, void *arg)
                                }
 
                                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;
 }
@@ -1346,12 +1854,12 @@ getNamespaces(int *numNamespaces)
        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)
        {
@@ -1361,8 +1869,8 @@ getNamespaces(int *numNamespaces)
                nsinfo[0].dobj.catId.tableoid = 0;
                nsinfo[0].dobj.catId.oid = 0;
                AssignDumpId(&nsinfo[0].dobj);
-               nsinfo[0].nspname = strdup("");
-               nsinfo[0].usename = strdup("");
+               nsinfo[0].dobj.name = strdup("public");
+               nsinfo[0].rolname = strdup("");
                nsinfo[0].nspacl = strdup("");
 
                selectDumpableNamespace(&nsinfo[0]);
@@ -1371,8 +1879,8 @@ getNamespaces(int *numNamespaces)
                nsinfo[1].dobj.catId.tableoid = 0;
                nsinfo[1].dobj.catId.oid = 1;
                AssignDumpId(&nsinfo[1].dobj);
-               nsinfo[1].nspname = strdup("pg_catalog");
-               nsinfo[1].usename = strdup("");
+               nsinfo[1].dobj.name = strdup("pg_catalog");
+               nsinfo[1].rolname = strdup("");
                nsinfo[1].nspacl = strdup("");
 
                selectDumpableNamespace(&nsinfo[1]);
@@ -1389,13 +1897,13 @@ 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 tableoid, oid, nspname, "
-       "(select usename from pg_user where nspowner = usesysid) as usename, "
-                                         "nspacl "
-                                         "FROM pg_namespace");
+                                         "(%s nspowner) as rolname, "
+                                         "nspacl FROM pg_namespace",
+                                         username_subquery);
 
        res = PQexec(g_conn, query->data);
        check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
@@ -1407,7 +1915,7 @@ getNamespaces(int *numNamespaces)
        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++)
@@ -1416,35 +1924,16 @@ getNamespaces(int *numNamespaces)
                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].nspname = strdup(PQgetvalue(res, i, i_nspname));
-               nsinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+               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);
@@ -1512,11 +2001,12 @@ 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;
@@ -1526,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
         *
@@ -1541,39 +2031,42 @@ getTypes(int *numTypes)
        {
                appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
                                                  "typnamespace, "
-                                                 "(select usename from pg_user where typowner = usesysid) as usename, "
+                                                 "(%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 if (g_fout->remoteVersion >= 70100)
        {
                appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
                                                  "0::oid as typnamespace, "
-                                                 "(select usename from pg_user where typowner = usesysid) as usename, "
+                                                 "(%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 "
-                                                 "(SELECT oid FROM pg_class WHERE relname = 'pg_type') AS tableoid, "
+                "(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, "
+                                                 "(%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);
@@ -1587,7 +2080,7 @@ getTypes(int *numTypes)
        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");
@@ -1598,29 +2091,35 @@ getTypes(int *numTypes)
 
        for (i = 0; i < ntups; i++)
        {
-               Oid                     typoutput;
-               FuncInfo   *funcInfo;
-
                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].typname = strdup(PQgetvalue(res, i, i_typname));
-               tinfo[i].typnamespace = findNamespace(atooid(PQgetvalue(res, i, i_typnamespace)),
-                                                                                         tinfo[i].dobj.catId.oid);
-               tinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
-               tinfo[i].typinput = atooid(PQgetvalue(res, i, i_typinput));
-               typoutput = atooid(PQgetvalue(res, i, i_typoutput));
+               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 (OidIsValid(tinfo[i].typelem) &&
-                       tinfo[i].typname[0] != '_')
+                       tinfo[i].dobj.name[0] != '_')
                        tinfo[i].isArray = true;
                else
                        tinfo[i].isArray = false;
@@ -1630,32 +2129,90 @@ getTypes(int *numTypes)
                else
                        tinfo[i].isDefined = false;
 
+               /* 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].typtype == 'd')
+               if (tinfo[i].dobj.dump && tinfo[i].typtype == 'd')
                        getDomainConstraints(&(tinfo[i]));
 
                /*
-                * Make sure there are dependencies from the type to its input and
-                * output functions.  (We don't worry about typsend/typreceive since
-                * those are only valid in 7.4 and later, wherein the standard
-                * dependency mechanism will pick them up.)
+                * 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.
                 */
-               funcInfo = findFuncByOid(tinfo[i].typinput);
-               if (funcInfo)
-                       addObjectDependency(&tinfo[i].dobj,
-                                                               funcInfo->dobj.dumpId);
-               funcInfo = findFuncByOid(typoutput);
-               if (funcInfo)
-                       addObjectDependency(&tinfo[i].dobj,
-                                                               funcInfo->dobj.dumpId);
-
-               if (strlen(tinfo[i].usename) == 0 && tinfo[i].isDefined)
+               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;
@@ -1686,7 +2243,7 @@ getOperators(int *numOprs)
        int                     i_oid;
        int                     i_oprname;
        int                     i_oprnamespace;
-       int                     i_usename;
+       int                     i_rolname;
        int                     i_oprcode;
 
        /*
@@ -1701,17 +2258,19 @@ getOperators(int *numOprs)
        {
                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, "
-                                                 "(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
        {
@@ -1719,9 +2278,10 @@ getOperators(int *numOprs)
                                                  "(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);
@@ -1736,7 +2296,7 @@ getOperators(int *numOprs)
        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++)
@@ -1745,15 +2305,18 @@ getOperators(int *numOprs)
                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].oprname = strdup(PQgetvalue(res, i, i_oprname));
-               oprinfo[i].oprnamespace = findNamespace(atooid(PQgetvalue(res, i, i_oprnamespace)),
-                                                                                               oprinfo[i].dobj.catId.oid);
-               oprinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+               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);
@@ -1777,15 +2340,16 @@ getConversions(int *numConversions)
        int                     ntups;
        int                     i;
        PQExpBuffer query = createPQExpBuffer();
-       ConvInfo *convinfo;
+       ConvInfo   *convinfo;
        int                     i_tableoid;
        int                     i_oid;
        int                     i_conname;
        int                     i_connamespace;
-       int                     i_usename;
+       int                     i_rolname;
 
        /* Conversions didn't exist pre-7.3 */
-       if (g_fout->remoteVersion < 70300) {
+       if (g_fout->remoteVersion < 70300)
+       {
                *numConversions = 0;
                return NULL;
        }
@@ -1800,8 +2364,9 @@ getConversions(int *numConversions)
 
        appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
                                          "connamespace, "
-                                         "(select usename from pg_user where conowner = usesysid) as usename "
-                                         "FROM pg_conversion");
+                                         "(%s conowner) as rolname "
+                                         "FROM pg_conversion",
+                                         username_subquery);
 
        res = PQexec(g_conn, query->data);
        check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
@@ -1815,7 +2380,7 @@ getConversions(int *numConversions)
        i_oid = PQfnumber(res, "oid");
        i_conname = PQfnumber(res, "conname");
        i_connamespace = PQfnumber(res, "connamespace");
-       i_usename = PQfnumber(res, "usename");
+       i_rolname = PQfnumber(res, "rolname");
 
        for (i = 0; i < ntups; i++)
        {
@@ -1823,10 +2388,13 @@ getConversions(int *numConversions)
                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].conname = strdup(PQgetvalue(res, i, i_conname));
-               convinfo[i].connamespace = findNamespace(atooid(PQgetvalue(res, i, i_connamespace)),
+               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].usename = strdup(PQgetvalue(res, i, i_usename));
+               convinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(convinfo[i].dobj));
        }
 
        PQclear(res);
@@ -1855,7 +2423,7 @@ getOpclasses(int *numOpclasses)
        int                     i_oid;
        int                     i_opcname;
        int                     i_opcnamespace;
-       int                     i_usename;
+       int                     i_rolname;
 
        /*
         * find all opclasses, including builtin opclasses; we filter out
@@ -1869,14 +2437,15 @@ getOpclasses(int *numOpclasses)
        {
                appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
                                                  "opcnamespace, "
-                                                 "(select usename from pg_user where opcowner = usesysid) as usename "
-                                                 "FROM pg_opclass");
+                                                 "(%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 usename "
+                                                 "''::name as rolname "
                                                  "FROM pg_opclass");
        }
        else
@@ -1885,7 +2454,7 @@ getOpclasses(int *numOpclasses)
                                                  "(SELECT oid FROM pg_class WHERE relname = 'pg_opclass') AS tableoid, "
                                                  "oid, opcname, "
                                                  "0::oid as opcnamespace, "
-                                                 "''::name as usename "
+                                                 "''::name as rolname "
                                                  "FROM pg_opclass");
        }
 
@@ -1901,7 +2470,7 @@ getOpclasses(int *numOpclasses)
        i_oid = PQfnumber(res, "oid");
        i_opcname = PQfnumber(res, "opcname");
        i_opcnamespace = PQfnumber(res, "opcnamespace");
-       i_usename = PQfnumber(res, "usename");
+       i_rolname = PQfnumber(res, "rolname");
 
        for (i = 0; i < ntups; i++)
        {
@@ -1909,16 +2478,19 @@ getOpclasses(int *numOpclasses)
                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].opcname = strdup(PQgetvalue(res, i, i_opcname));
-               opcinfo[i].opcnamespace = findNamespace(atooid(PQgetvalue(res, i, i_opcnamespace)),
-                                                                                               opcinfo[i].dobj.catId.oid);
-               opcinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+               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);
                }
        }
 
@@ -1948,8 +2520,9 @@ getAggregates(int *numAggs)
        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 */
@@ -1957,27 +2530,44 @@ 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 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, "
-                                                 "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 "
                                                  "where oid > '%u'::oid",
+                                                 username_subquery,
                                                  g_last_builtin_oid);
        }
        else
@@ -1986,11 +2576,13 @@ getAggregates(int *numAggs)
                                                  "(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 "
                                                  "where oid > '%u'::oid",
+                                                 username_subquery,
                                                  g_last_builtin_oid);
        }
 
@@ -2006,8 +2598,9 @@ getAggregates(int *numAggs)
        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++)
@@ -2016,21 +2609,32 @@ getAggregates(int *numAggs)
                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.proname = strdup(PQgetvalue(res, i, i_aggname));
-               agginfo[i].aggfn.pronamespace = findNamespace(atooid(PQgetvalue(res, i, i_aggnamespace)),
-                                                                                                         agginfo[i].aggfn.dobj.catId.oid);
-               agginfo[i].aggfn.usename = strdup(PQgetvalue(res, i, i_usename));
-               if (strlen(agginfo[i].aggfn.usename) == 0)
+               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].aggfn.proname);
-               agginfo[i].aggfn.lang = InvalidOid;     /* not currently interesting */
-               agginfo[i].aggfn.nargs = 1;
-               agginfo[i].aggfn.argtypes = (Oid *) malloc(sizeof(Oid));
-               agginfo[i].aggfn.argtypes[0] = atooid(PQgetvalue(res, i, i_aggbasetype));
-               agginfo[i].aggfn.prorettype = InvalidOid;       /* not saved */
+                                         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].anybasetype = false; /* computed when it's dumped */
-               agginfo[i].fmtbasetype = NULL;  /* computed when it's dumped */
+               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);
@@ -2059,7 +2663,7 @@ getFuncs(int *numFuncs)
        int                     i_oid;
        int                     i_proname;
        int                     i_pronamespace;
-       int                     i_usename;
+       int                     i_rolname;
        int                     i_prolang;
        int                     i_pronargs;
        int                     i_proargtypes;
@@ -2077,11 +2681,13 @@ getFuncs(int *numFuncs)
                                                  "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)
        {
@@ -2090,23 +2696,26 @@ getFuncs(int *numFuncs)
                                                  "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);
        }
        else
        {
                appendPQExpBuffer(query,
                                                  "SELECT "
-                                                 "(SELECT oid FROM pg_class WHERE relname = 'pg_proc') AS tableoid, "
+                                                 "(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);
        }
 
@@ -2123,7 +2732,7 @@ getFuncs(int *numFuncs)
        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");
@@ -2136,10 +2745,11 @@ getFuncs(int *numFuncs)
                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].proname = strdup(PQgetvalue(res, i, i_proname));
-               finfo[i].pronamespace = findNamespace(atooid(PQgetvalue(res, i, i_pronamespace)),
-                                                                                         finfo[i].dobj.catId.oid);
-               finfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+               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 = atooid(PQgetvalue(res, i, i_prorettype));
                finfo[i].proacl = strdup(PQgetvalue(res, i, i_proacl));
@@ -2153,9 +2763,13 @@ getFuncs(int *numFuncs)
                                                  finfo[i].argtypes, finfo[i].nargs);
                }
 
-               if (strlen(finfo[i].usename) == 0)
-                       write_msg(NULL, "WARNING: owner of function \"%s\" appears to be invalid\n",
-                                         finfo[i].proname);
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(finfo[i].dobj));
+
+               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);
@@ -2188,7 +2802,7 @@ getTables(int *numTables)
        int                     i_relnamespace;
        int                     i_relkind;
        int                     i_relacl;
-       int                     i_usename;
+       int                     i_rolname;
        int                     i_relchecks;
        int                     i_reltriggers;
        int                     i_relhasindex;
@@ -2196,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");
@@ -2206,99 +2822,174 @@ 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.tableoid, c.oid, relname, "
                                                  "relacl, relkind, relnamespace, "
-                                                 "(select usename from pg_user where relowner = usesysid) as usename, "
+                                                 "(%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 tableoid, 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 tableoid, 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 "
-                                                 "(SELECT oid FROM pg_class WHERE relname = 'pg_class') AS tableoid, "
+               "(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);
        }
 
@@ -2310,13 +3001,13 @@ getTables(int *numTables)
        *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 *) calloc(ntups, sizeof(TableInfo));
 
@@ -2326,7 +3017,7 @@ getTables(int *numTables)
        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");
@@ -2334,6 +3025,8 @@ 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++)
        {
@@ -2341,10 +3034,10 @@ getTables(int *numTables)
                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].relname = strdup(PQgetvalue(res, i, i_relname));
-               tblinfo[i].relnamespace = findNamespace(atooid(PQgetvalue(res, i, i_relnamespace)),
-                                                                                               tblinfo[i].dobj.catId.oid);
-               tblinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+               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);
@@ -2362,68 +3055,78 @@ getTables(int *numTables)
                        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 (OidIsValid(tblinfo[i].owning_tab))
-                       tblinfo[i].dump = false;
+               if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
+                       tblinfo[i].dobj.dump = false;
                else
                        selectDumpableTable(&tblinfo[i]);
-               tblinfo[i].interesting = tblinfo[i].dump;
+               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)
                {
                        resetPQExpBuffer(lockquery);
                        appendPQExpBuffer(lockquery,
                                                          "LOCK TABLE %s IN ACCESS SHARE MODE",
-                                                fmtQualifiedId(tblinfo[i].relnamespace->nspname,
-                                                                               tblinfo[i].relname));
+                                                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.  (This is a bit simplistic
-        * since we don't fully check the combination of -n and -t switches.)
+        * 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)
-                               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);
@@ -2508,7 +3211,9 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                i_contype,
                                i_conname,
                                i_contableoid,
-                               i_conoid;
+                               i_conoid,
+                               i_tablespace,
+                               i_options;
        int                     ntups;
 
        for (i = 0; i < numTables; i++)
@@ -2519,37 +3224,91 @@ getIndexes(TableInfo tblinfo[], int numTables)
                if (tbinfo->relkind != RELKIND_RELATION || !tbinfo->hasindex)
                        continue;
 
-               if (!tbinfo->dump)
+               /* Ignore indexes of tables not to be dumped */
+               if (!tbinfo->dobj.dump)
                        continue;
 
                if (g_verbose)
                        write_msg(NULL, "reading indexes for table \"%s\"\n",
-                                         tbinfo->relname);
+                                         tbinfo->dobj.name);
 
                /* Make sure we are in proper schema so indexdef is right */
-               selectSourceSchema(tbinfo->relnamespace->nspname);
+               selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
 
                /*
-                * 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.
+                * 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.
                 */
                resetPQExpBuffer(query);
-               if (g_fout->remoteVersion >= 70300)
+               if (g_fout->remoteVersion >= 80200)
+               {
+                       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 if (g_fout->remoteVersion >= 80000)
+               {
+                       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);
+               }
+               else if (g_fout->remoteVersion >= 70300)
                {
                        appendPQExpBuffer(query,
                                                          "SELECT t.tableoid, t.oid, "
                                                          "t.relname as indexname, "
-                                "pg_catalog.pg_get_indexdef(i.indexrelid) as indexdef, "
+                                        "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 "
+                                                         "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) "
+                                         "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 "
@@ -2573,7 +3332,9 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                                          "ELSE '0'::char END as contype, "
                                                          "t.relname as conname, "
                                                          "0::oid as contableoid, "
-                                                         "t.oid as conoid "
+                                                         "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 "
@@ -2594,7 +3355,9 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                                          "ELSE '0'::char END as contype, "
                                                          "t.relname as conname, "
                                                          "0::oid as contableoid, "
-                                                         "t.oid as conoid "
+                                                         "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 "
@@ -2618,6 +3381,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
                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));
@@ -2630,18 +3395,22 @@ getIndexes(TableInfo tblinfo[], int numTables)
                        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].indexname = strdup(PQgetvalue(res, j, i_indexname));
+                       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.
+                        * 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),
@@ -2662,8 +3431,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                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].conname = strdup(PQgetvalue(res, j, i_conname));
+                               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;
@@ -2671,7 +3440,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                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 */
@@ -2724,18 +3493,18 @@ getConstraints(TableInfo tblinfo[], int numTables)
        {
                TableInfo  *tbinfo = &tblinfo[i];
 
-               if (tbinfo->ntrig == 0 || !tbinfo->dump)
+               if (tbinfo->ntrig == 0 || !tbinfo->dobj.dump)
                        continue;
 
                if (g_verbose)
                        write_msg(NULL, "reading foreign key constraints for table \"%s\"\n",
-                                         tbinfo->relname);
+                                         tbinfo->dobj.name);
 
                /*
                 * select table schema to ensure constraint expr is qualified if
                 * needed
                 */
-               selectSourceSchema(tbinfo->relnamespace->nspname);
+               selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
 
                resetPQExpBuffer(query);
                appendPQExpBuffer(query,
@@ -2763,7 +3532,8 @@ getConstraints(TableInfo tblinfo[], int numTables)
                        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].conname = strdup(PQgetvalue(res, j, i_conname));
+                       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';
@@ -2805,7 +3575,7 @@ getDomainConstraints(TypeInfo *tinfo)
         * select appropriate schema to ensure names in constraint are properly
         * qualified
         */
-       selectSourceSchema(tinfo->typnamespace->nspname);
+       selectSourceSchema(tinfo->dobj.namespace->dobj.name);
 
        query = createPQExpBuffer();
 
@@ -2845,7 +3615,8 @@ getDomainConstraints(TypeInfo *tinfo)
                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].conname = strdup(PQgetvalue(res, i, i_conname));
+               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';
@@ -2853,9 +3624,10 @@ getDomainConstraints(TypeInfo *tinfo)
                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.
+                * 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);
@@ -2926,15 +3698,24 @@ getRules(int *numRules)
 
        for (i = 0; i < ntups; i++)
        {
-               Oid             ruletableoid;
+               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].rulename = strdup(PQgetvalue(res, i, i_rulename));
+               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)
@@ -2942,17 +3723,26 @@ getRules(int *numRules)
                        /*
                         * 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.
+                        * 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);
@@ -2988,6 +3778,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
                                i_tgconstrname,
                                i_tgconstrrelid,
                                i_tgconstrrelname,
+                               i_tgenabled,
                                i_tgdeferrable,
                                i_tginitdeferred;
        int                     ntups;
@@ -2996,33 +3787,31 @@ getTriggers(TableInfo tblinfo[], int numTables)
        {
                TableInfo  *tbinfo = &tblinfo[i];
 
-               if (tbinfo->ntrig == 0 || !tbinfo->dump)
+               if (tbinfo->ntrig == 0 || !tbinfo->dobj.dump)
                        continue;
 
                if (g_verbose)
                        write_msg(NULL, "reading triggers for table \"%s\"\n",
-                                         tbinfo->relname);
+                                         tbinfo->dobj.name);
 
                /*
-                * select table schema to ensure regproc name is qualified if
-                * needed
+                * select table schema to ensure regproc name is qualified if needed
                 */
-               selectSourceSchema(tbinfo->relnamespace->nspname);
+               selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
 
                resetPQExpBuffer(query);
                if (g_fout->remoteVersion >= 70300)
                {
                        /*
-                        * We ignore triggers that are tied to a foreign-key
-                        * constraint
+                        * 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, "
+                                                         "tgtype, tgnargs, tgargs, tgenabled, "
+                                                         "tgisconstraint, tgconstrname, tgdeferrable, "
                                                          "tgconstrrelid, tginitdeferred, tableoid, oid, "
-                                "tgconstrrelid::pg_catalog.regclass as tgconstrrelname "
+                                        "tgconstrrelid::pg_catalog.regclass as tgconstrrelname "
                                                          "from pg_catalog.pg_trigger t "
                                                          "where tgrelid = '%u'::pg_catalog.oid "
                                                          "and (not tgisconstraint "
@@ -3035,11 +3824,11 @@ getTriggers(TableInfo tblinfo[], int numTables)
                else if (g_fout->remoteVersion >= 70100)
                {
                        appendPQExpBuffer(query,
-                                                       "SELECT tgname, tgfoid::regproc as tgfname, "
-                                                         "tgtype, tgnargs, tgargs, "
-                                                  "tgisconstraint, tgconstrname, tgdeferrable, "
+                                                         "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) "
+                                 "(select relname from pg_class where oid = tgconstrrelid) "
                                                          "             as tgconstrrelname "
                                                          "from pg_trigger "
                                                          "where tgrelid = '%u'::oid",
@@ -3048,14 +3837,14 @@ getTriggers(TableInfo tblinfo[], int numTables)
                else
                {
                        appendPQExpBuffer(query,
-                                                       "SELECT tgname, tgfoid::regproc as tgfname, "
-                                                         "tgtype, tgnargs, tgargs, "
-                                                  "tgisconstraint, tgconstrname, tgdeferrable, "
+                                                         "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) "
+                                 "(select relname from pg_class where oid = tgconstrrelid) "
                                                          "             as tgconstrrelname "
                                                          "from pg_trigger "
                                                          "where tgrelid = '%u'::oid",
@@ -3073,7 +3862,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
                if (ntups > tbinfo->ntrig)
                {
                        write_msg(NULL, "expected %d triggers on table \"%s\" but found %d\n",
-                                         tbinfo->ntrig, tbinfo->relname, ntups);
+                                         tbinfo->ntrig, tbinfo->dobj.name, ntups);
                        exit_nicely();
                }
                i_tableoid = PQfnumber(res, "tableoid");
@@ -3087,6 +3876,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
                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");
 
@@ -3098,13 +3888,15 @@ getTriggers(TableInfo tblinfo[], int numTables)
                        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].tgname = strdup(PQgetvalue(res, j, i_tgname));
                        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';
 
@@ -3117,7 +3909,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
                                        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].tgname, tbinfo->relname,
+                                                                 tginfo[j].dobj.name, tbinfo->dobj.name,
                                                                  tginfo[j].tgconstrrelid);
                                                exit_nicely();
                                        }
@@ -3162,14 +3954,36 @@ getProcLangs(int *numProcLangs)
        int                     i_lanname;
        int                     i_lanpltrusted;
        int                     i_lanplcallfoid;
-       int                     i_lanvalidator = -1;
-       int                     i_lanacl = -1;
+       int                     i_lanvalidator;
+       int                     i_lanacl;
+       int                     i_lanowner;
 
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
 
-       if (g_fout->remoteVersion >= 70100)
+       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");
@@ -3197,11 +4011,10 @@ getProcLangs(int *numProcLangs)
        i_lanname = PQfnumber(res, "lanname");
        i_lanpltrusted = PQfnumber(res, "lanpltrusted");
        i_lanplcallfoid = PQfnumber(res, "lanplcallfoid");
-       if (g_fout->remoteVersion >= 70300)
-       {
-               i_lanvalidator = PQfnumber(res, "lanvalidator");
-               i_lanacl = PQfnumber(res, "lanacl");
-       }
+       /* 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++)
        {
@@ -3210,26 +4023,31 @@ getProcLangs(int *numProcLangs)
                planginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
                AssignDumpId(&planginfo[i].dobj);
 
-               planginfo[i].lanname = strdup(PQgetvalue(res, i, i_lanname));
+               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 (g_fout->remoteVersion >= 70300)
-               {
+               if (i_lanvalidator >= 0)
                        planginfo[i].lanvalidator = atooid(PQgetvalue(res, i, i_lanvalidator));
-                       planginfo[i].lanacl = strdup(PQgetvalue(res, i, i_lanacl));
-               }
                else
-               {
-                       FuncInfo   *funcInfo;
-
                        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
+                        * 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 = findFuncByOid(planginfo[i].lanplcallfoid);
+                       FuncInfo   *funcInfo = findFuncByOid(planginfo[i].lanplcallfoid);
+
                        if (funcInfo)
                                addObjectDependency(&planginfo[i].dobj,
                                                                        funcInfo->dobj.dumpId);
@@ -3303,6 +4121,10 @@ getCasts(int *numCasts)
 
        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));
@@ -3312,11 +4134,24 @@ getCasts(int *numCasts)
                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
+                        * 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;
@@ -3352,8 +4187,7 @@ void
 getTableAttrs(TableInfo *tblinfo, int numTables)
 {
        int                     i,
-                               j,
-                               k;
+                               j;
        PQExpBuffer q = createPQExpBuffer();
        int                     i_attnum;
        int                     i_attname;
@@ -3386,21 +4220,20 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                 * 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);
+               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.
+                * 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->relname);
+                                         tbinfo->dobj.name);
 
                resetPQExpBuffer(q);
 
@@ -3408,9 +4241,9 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                {
                        /* 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 "
+                                 "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 "
@@ -3420,13 +4253,13 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                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.
+                        * 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 "
+                                                         "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 "
@@ -3473,7 +4306,6 @@ 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->attrdefs = (AttrDefInfo **) malloc(ntups * sizeof(AttrDefInfo *));
                tbinfo->inhAttrs = (bool *) malloc(ntups * sizeof(bool));
@@ -3486,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));
@@ -3497,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->attrdefs[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() */
@@ -3520,13 +4351,13 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 
                        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 tableoid, oid, adnum, "
-                                          "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc "
+                                                  "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc "
                                                                  "FROM pg_catalog.pg_attrdef "
                                                                  "WHERE adrelid = '%u'::pg_catalog.oid",
                                                                  tbinfo->dobj.catId.oid);
@@ -3566,7 +4397,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 
                        for (j = 0; j < numDefaults; j++)
                        {
-                               int             adnum;
+                               int                     adnum;
 
                                attrdefs[j].dobj.objType = DO_ATTRDEF;
                                attrdefs[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, 0));
@@ -3576,12 +4407,17 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                                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.
+                                * 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)
                                {
@@ -3600,7 +4436,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                                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->attrdefs[adnum - 1] = &attrdefs[j];
@@ -3618,13 +4454,13 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 
                        if (g_verbose)
                                write_msg(NULL, "finding check constraints for table \"%s\"\n",
-                                                 tbinfo->relname);
+                                                 tbinfo->dobj.name);
 
                        resetPQExpBuffer(q);
                        if (g_fout->remoteVersion >= 70400)
                        {
                                appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
-                                       "pg_catalog.pg_get_constraintdef(oid) AS consrc "
+                                                       "pg_catalog.pg_get_constraintdef(oid) AS consrc "
                                                                  "FROM pg_catalog.pg_constraint "
                                                                  "WHERE conrelid = '%u'::pg_catalog.oid "
                                                                  "   AND contype = 'c' "
@@ -3682,7 +4518,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                        if (numConstrs != tbinfo->ncheck)
                        {
                                write_msg(NULL, "expected %d check constraints on table \"%s\" but found %d\n",
-                                                 tbinfo->ncheck, tbinfo->relname, numConstrs);
+                                                 tbinfo->ncheck, tbinfo->dobj.name, numConstrs);
                                write_msg(NULL, "(The system catalogs might be corrupted.)\n");
                                exit_nicely();
                        }
@@ -3696,16 +4532,27 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                                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].conname = strdup(PQgetvalue(res, j, 2));
                                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
@@ -3714,45 +4561,6 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                        }
                        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.
-                */
-               for (j = 0; j < ntups; j++)
-               {
-                       /*
-                        * 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->attrdefs[j] == NULL)
-                               continue;
-                       for (k = 0; k < numTables; k++)
-                       {
-                               TableInfo  *seqinfo = &tblinfo[k];
-
-                               if (OidIsValid(seqinfo->owning_tab) &&
-                                       seqinfo->owning_tab == tbinfo->dobj.catId.oid &&
-                                       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;
-                               }
-                       }
-               }
        }
 
        destroyPQExpBuffer(q);
@@ -3769,163 +4577,112 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
  * 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.
+ *
+ * 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,
                        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();
+       /* Search for comments associated with catalogId, using table */
+       ncomments = findComments(fout, catalogId.tableoid, catalogId.oid,
+                                                        &comments);
 
-       if (fout->remoteVersion >= 70300)
-       {
-               appendPQExpBuffer(query,
-                                                 "SELECT description FROM pg_catalog.pg_description "
-                                                 "WHERE classoid = '%u'::pg_catalog.oid and "
-                                                 "objoid = '%u'::pg_catalog.oid and objsubid = %d",
-                                                 catalogId.tableoid, catalogId.oid, subid);
-       }
-       else if (fout->remoteVersion >= 70200)
-       {
-               appendPQExpBuffer(query,
-                                                 "SELECT description FROM pg_description "
-                                                 "WHERE classoid = '%u'::oid and "
-                                                 "objoid = '%u'::oid and objsubid = %d",
-                                                 catalogId.tableoid, catalogId.oid, subid);
-       }
-       else
+       /* Is there one matching the subid? */
+       while (ncomments > 0)
        {
-               /* Note: this will fail to find attribute comments in pre-7.2... */
-               appendPQExpBuffer(query, "SELECT description FROM pg_description WHERE objoid = '%u'::oid", catalogId.oid);
+               if (comments->objsubid == subid)
+                       break;
+               comments++;
+               ncomments--;
        }
 
-       /* Execute query */
-
-       res = PQexec(g_conn, query->data);
-       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
        /* 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, nilCatalogId, createDumpId(),
-                                        target, namespace, owner,
+                                        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)
 {
-       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 classoid = '%u'::pg_catalog.oid and "
-                                                 "objoid = '%u'::pg_catalog.oid "
-                                                 "ORDER BY objoid, classoid, objsubid",
-                                                 tbinfo->dobj.catId.tableoid, tbinfo->dobj.catId.oid);
-       }
-       else if (fout->remoteVersion >= 70200)
-       {
-               appendPQExpBuffer(query, "SELECT description, objsubid FROM pg_description "
-                                                 "WHERE classoid = '%u'::oid and "
-                                                 "objoid = '%u'::oid "
-                                                 "ORDER BY objoid, classoid, objsubid",
-                                                 tbinfo->dobj.catId.tableoid, tbinfo->dobj.catId.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 = '%u'::oid",
-                                                 tbinfo->dobj.catId.oid);
-       }
-
-       /* Execute query */
-
-       res = PQexec(g_conn, query->data);
-       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
-       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, nilCatalogId, createDumpId(),
                                                 target->data,
-                                                tbinfo->relnamespace->nspname, tbinfo->usename,
-                                                "COMMENT", query->data, "", NULL,
+                                                tbinfo->dobj.namespace->dobj.name,
+                                                NULL,
+                                                tbinfo->rolname,
+                                                false, "COMMENT", query->data, "", NULL,
                                                 &(tbinfo->dobj.dumpId), 1,
                                                 NULL, NULL);
                }
@@ -3933,29 +4690,201 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
                {
                        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, nilCatalogId, createDumpId(),
                                                 target->data,
-                                                tbinfo->relnamespace->nspname, tbinfo->usename,
-                                                "COMMENT", query->data, "", NULL,
+                                                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);
 }
 
+/*
+ * findComments --
+ *
+ * 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.
+ */
+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_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");
+       }
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       /* Construct lookup table containing OIDs in numeric form */
+
+       i_description = PQfnumber(res, "description");
+       i_classoid = PQfnumber(res, "classoid");
+       i_objoid = PQfnumber(res, "objoid");
+       i_objsubid = PQfnumber(res, "objsubid");
+
+       ntups = PQntuples(res);
+
+       comments = (CommentItem *) malloc(ntups * sizeof(CommentItem));
+
+       for (i = 0; i < ntups; i++)
+       {
+               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));
+       }
+
+       /* Do NOT free the PGresult since we are keeping pointers into it */
+       destroyPQExpBuffer(query);
+
+       *items = comments;
+       return ntups;
+}
+
 /*
  * dumpDumpableObject
  *
@@ -3973,6 +4902,9 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
                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;
@@ -4018,6 +4950,23 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
                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;
        }
 }
 
@@ -4032,57 +4981,41 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
        PQExpBuffer delq;
        char       *qnspname;
 
-       /* skip if not to be dumped */
-       if (!nspinfo->dump || dataOnly)
+       /* Skip if not to be dumped */
+       if (!nspinfo->dobj.dump || dataOnly)
                return;
 
        /* don't dump dummy namespace from pre-7.3 source */
-       if (strlen(nspinfo->nspname) == 0)
+       if (strlen(nspinfo->dobj.name) == 0)
                return;
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
 
-       qnspname = strdup(fmtId(nspinfo->nspname));
+       qnspname = strdup(fmtId(nspinfo->dobj.name));
 
-       /*
-        * If it's the PUBLIC namespace, suppress the CREATE SCHEMA record
-        * for it, since we expect PUBLIC to exist already in the
-        * destination database.  But do emit ACL in case it's not standard,
-        * likewise comment.
-        *
-        * Note that ownership is shown in the AUTHORIZATION clause,
-        * while the archive entry is listed with empty owner (causing
-        * it to be emitted with SET SESSION AUTHORIZATION DEFAULT).
-        * This seems the best way of dealing with schemas owned by
-        * users without CREATE SCHEMA privilege.  Further hacking has
-        * to be applied for --no-owner mode, though!
-        */
-       if (strcmp(nspinfo->nspname, "public") != 0)
-       {
-               appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
+       appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
 
-               appendPQExpBuffer(q, "CREATE SCHEMA %s AUTHORIZATION %s;\n",
-                                                 qnspname, fmtId(nspinfo->usename));
+       appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
 
-               ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
-                                        nspinfo->nspname,
-                                        NULL, "",
-                                        "SCHEMA", q->data, delq->data, NULL,
-                                        nspinfo->dobj.dependencies, nspinfo->dobj.nDeps,
-                                        NULL, NULL);
-       }
+       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);
 
        /* Dump Schema Comments */
        resetPQExpBuffer(q);
        appendPQExpBuffer(q, "SCHEMA %s", qnspname);
        dumpComment(fout, q->data,
-                               NULL, nspinfo->usename,
+                               NULL, nspinfo->rolname,
                                nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
 
        dumpACL(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, "SCHEMA",
-                       qnspname, nspinfo->nspname, NULL,
-                       nspinfo->usename, nspinfo->nspacl);
+                       qnspname, nspinfo->dobj.name, NULL,
+                       nspinfo->rolname, nspinfo->nspacl);
 
        free(qnspname);
 
@@ -4097,21 +5030,8 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 static void
 dumpType(Archive *fout, TypeInfo *tinfo)
 {
-       /* Dump only types in dumpable namespaces */
-       if (!tinfo->typnamespace->dump || dataOnly)
-               return;
-
-       /* skip complex types, except for standalone composite types */
-       if (OidIsValid(tinfo->typrelid) && tinfo->typrelkind != 'c')
-               return;
-
-       /* skip undefined placeholder types */
-       if (!tinfo->isDefined)
-               return;
-
-       /* skip all array types that start w/ underscore */
-       if ((tinfo->typname[0] == '_') &&
-               OidIsValid(tinfo->typelem))
+       /* Skip if not to be dumped */
+       if (!tinfo->dobj.dump || dataOnly)
                return;
 
        /* Dump out in proper style */
@@ -4140,30 +5060,51 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        char       *typoutput;
        char       *typreceive;
        char       *typsend;
+       char       *typanalyze;
        Oid                     typinputoid;
        Oid                     typoutputoid;
        Oid                     typreceiveoid;
        Oid                     typsendoid;
+       Oid                     typanalyzeoid;
        char       *typdelim;
-       char       *typdefault;
        char       *typbyval;
        char       *typalign;
        char       *typstorage;
+       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 = '%u'::pg_catalog.oid",
                                                  tinfo->dobj.catId.oid);
@@ -4173,16 +5114,18 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                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 = '%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,
@@ -4191,11 +5134,33 @@ dumpBaseType(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 = '%u'::oid",
                                                  tinfo->dobj.catId.oid);
@@ -4205,11 +5170,14 @@ dumpBaseType(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, "
-                                                 "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 = '%u'::oid",
                                                  tinfo->dobj.catId.oid);
@@ -4232,43 +5200,54 @@ dumpBaseType(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"));
+       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"));
+       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"));
+               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 (OidIsValid(typreceiveoid))
                        appendPQExpBuffer(q, ",\n    RECEIVE = %s", typreceive);
                if (OidIsValid(typsendoid))
                        appendPQExpBuffer(q, ",\n    SEND = %s", typsend);
+               if (OidIsValid(typanalyzeoid))
+                       appendPQExpBuffer(q, ",\n    ANALYZE = %s", typanalyze);
        }
        else
        {
@@ -4276,13 +5255,16 @@ dumpBaseType(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)
@@ -4290,7 +5272,7 @@ dumpBaseType(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);
@@ -4299,7 +5281,7 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        if (typdelim && strcmp(typdelim, ",") != 0)
        {
                appendPQExpBuffer(q, ",\n    DELIMITER = ");
-               appendStringLiteral(q, typdelim, true);
+               appendStringLiteralAH(q, typdelim, fout);
        }
 
        if (strcmp(typalign, "c") == 0)
@@ -4326,9 +5308,10 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        appendPQExpBuffer(q, "\n);\n");
 
        ArchiveEntry(fout, tinfo->dobj.catId, tinfo->dobj.dumpId,
-                                tinfo->typname,
-                                tinfo->typnamespace->nspname,
-                                tinfo->usename,
+                                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);
@@ -4336,9 +5319,9 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        /* 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->dobj.namespace->dobj.name, tinfo->rolname,
                                tinfo->dobj.catId, 0, tinfo->dobj.dumpId);
 
        PQclear(res);
@@ -4363,15 +5346,16 @@ dumpDomain(Archive *fout, TypeInfo *tinfo)
        char       *typnotnull;
        char       *typdefn;
        char       *typdefault;
+       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 "
+                               "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 = '%u'::pg_catalog.oid",
                                          tinfo->dobj.catId.oid);
@@ -4390,21 +5374,32 @@ dumpDomain(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"));
+               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);
 
        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);
 
@@ -4417,24 +5412,24 @@ dumpDomain(Archive *fout, TypeInfo *tinfo)
 
                if (!domcheck->separate)
                        appendPQExpBuffer(q, "\n\tCONSTRAINT %s %s",
-                                                         fmtId(domcheck->conname), domcheck->condef);
+                                                         fmtId(domcheck->dobj.name), domcheck->condef);
        }
 
        appendPQExpBuffer(q, ";\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 DOMAIN %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->typname,
-                                tinfo->typnamespace->nspname,
-                                tinfo->usename,
+                                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);
@@ -4442,9 +5437,9 @@ dumpDomain(Archive *fout, TypeInfo *tinfo)
        /* 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->dobj.namespace->dobj.name, tinfo->rolname,
                                tinfo->dobj.catId, 0, tinfo->dobj.dumpId);
 
        destroyPQExpBuffer(q);
@@ -4470,14 +5465,14 @@ dumpCompositeType(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 "
+                        "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 "
@@ -4499,7 +5494,7 @@ dumpCompositeType(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++)
        {
@@ -4516,18 +5511,18 @@ dumpCompositeType(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->typname,
-                                tinfo->typnamespace->nspname,
-                                tinfo->usename,
+                                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);
@@ -4536,9 +5531,9 @@ dumpCompositeType(Archive *fout, TypeInfo *tinfo)
        /* 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->dobj.namespace->dobj.name, tinfo->rolname,
                                tinfo->dobj.catId, 0, tinfo->dobj.dumpId);
 
        PQclear(res);
@@ -4547,6 +5542,70 @@ dumpCompositeType(Archive *fout, TypeInfo *tinfo)
        destroyPQExpBuffer(query);
 }
 
+/*
+ * 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.
+ */
+static void
+dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
+{
+       PQExpBuffer q;
+
+       /* Skip if not to be dumped */
+       if (!stinfo->dobj.dump || dataOnly)
+               return;
+
+       q = createPQExpBuffer();
+
+       /*
+        * 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.
+        */
+
+       appendPQExpBuffer(q, "CREATE TYPE %s;\n",
+                                         fmtId(stinfo->dobj.name));
+
+       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);
+}
+
+/*
+ * 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.
+ */
+static bool
+shouldDumpProcLangs(void)
+{
+       if (matchingTables != NULL || matchingSchemas != NULL)
+               return false;
+       /* And they're schema not data */
+       if (dataOnly)
+               return false;
+       return true;
+}
+
 /*
  * dumpProcLang
  *               writes out to fout the queries to recreate a user-defined
@@ -4557,7 +5616,9 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 {
        PQExpBuffer defqry;
        PQExpBuffer delqry;
+       bool            useParams;
        char       *qlanname;
+       char       *lanschema;
        FuncInfo   *funcInfo;
        FuncInfo   *validatorInfo = NULL;
 
@@ -4565,69 +5626,83 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
                return;
 
        /*
-        * 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 the underlying function is in the pg_catalog namespace,
-        * we won't have loaded it into finfo[] at all; therefore,
-        * treat failure to find it in finfo[] as indicating we shouldn't
-        * dump it, not as an error condition.  Ditto for the validator.
+        * 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.)
         */
 
        funcInfo = findFuncByOid(plang->lanplcallfoid);
-       if (funcInfo == NULL)
-               return;
-
-       if (!funcInfo->pronamespace->dump)
-               return;
+       if (funcInfo != NULL && !funcInfo->dobj.dump)
+               funcInfo = NULL;                /* treat not-dumped same as not-found */
 
        if (OidIsValid(plang->lanvalidator))
        {
                validatorInfo = findFuncByOid(plang->lanvalidator);
-               if (validatorInfo == NULL)
-                       return;
+               if (validatorInfo != NULL && !validatorInfo->dobj.dump)
+                       validatorInfo = NULL;
        }
 
+       /*
+        * 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)));
+
+       if (!useParams && !shouldDumpProcLangs())
+               return;
+
        defqry = createPQExpBuffer();
        delqry = createPQExpBuffer();
 
-       qlanname = strdup(fmtId(plang->lanname));
+       qlanname = strdup(fmtId(plang->dobj.name));
+
+       /*
+        * 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",
                                          qlanname);
 
        appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE %s",
-                                         plang->lanpltrusted ? "TRUSTED " : "",
+                                         (useParams && plang->lanpltrusted) ? "TRUSTED " : "",
                                          qlanname);
-       appendPQExpBuffer(defqry, " HANDLER %s",
-                                         fmtId(funcInfo->proname));
-       if (OidIsValid(plang->lanvalidator))
+       if (useParams)
        {
-               appendPQExpBuffer(defqry, " VALIDATOR ");
-               /* Cope with possibility that validator is in different schema */
-               if (validatorInfo->pronamespace != funcInfo->pronamespace)
-                       appendPQExpBuffer(defqry, "%s.",
-                                                         fmtId(validatorInfo->pronamespace->nspname));
-               appendPQExpBuffer(defqry, "%s",
-                                                 fmtId(validatorInfo->proname));
+               appendPQExpBuffer(defqry, " HANDLER %s",
+                                                 fmtId(funcInfo->dobj.name));
+               if (OidIsValid(plang->lanvalidator))
+               {
+                       appendPQExpBuffer(defqry, " VALIDATOR ");
+                       /* Cope with possibility that validator is in different schema */
+                       if (validatorInfo->dobj.namespace != funcInfo->dobj.namespace)
+                               appendPQExpBuffer(defqry, "%s.",
+                                                       fmtId(validatorInfo->dobj.namespace->dobj.name));
+                       appendPQExpBuffer(defqry, "%s",
+                                                         fmtId(validatorInfo->dobj.name));
+               }
        }
        appendPQExpBuffer(defqry, ";\n");
 
        ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
-                                plang->lanname,
-                                funcInfo->pronamespace->nspname, "",
-                                "PROCEDURAL LANGUAGE",
+                                plang->dobj.name,
+                                lanschema, NULL, plang->lanowner,
+                                false, "PROCEDURAL LANGUAGE",
                                 defqry->data, delqry->data, NULL,
                                 plang->dobj.dependencies, plang->dobj.nDeps,
                                 NULL, NULL);
 
        /* Dump Proc Lang Comments */
        resetPQExpBuffer(defqry);
-
        appendPQExpBuffer(defqry, "LANGUAGE %s", qlanname);
        dumpComment(fout, defqry->data,
                                NULL, "",
@@ -4635,9 +5710,9 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 
        if (plang->lanpltrusted)
                dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
-                               qlanname, plang->lanname,
-                               funcInfo->pronamespace->nspname,
-                               NULL, plang->lanacl);
+                               qlanname, plang->dobj.name,
+                               lanschema,
+                               plang->lanowner, plang->lanacl);
 
        free(qlanname);
 
@@ -4646,10 +5721,81 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 }
 
 /*
- * format_function_signature: generate function name and argument list
+ * 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.
+ */
+static char *
+format_function_arguments(FuncInfo *finfo, int nallargs,
+                                                 char **allargtypes,
+                                                 char **argmodes,
+                                                 char **argnames)
+{
+       PQExpBufferData fn;
+       int                     j;
+
+       initPQExpBuffer(&fn);
+       appendPQExpBuffer(&fn, "%s(", fmtId(finfo->dobj.name));
+       for (j = 0; j < nallargs; j++)
+       {
+               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;
+
+               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
+ *
+ * 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)
@@ -4659,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);
@@ -4695,14 +5842,21 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        char       *proretset;
        char       *prosrc;
        char       *probin;
+       char       *proallargtypes;
+       char       *proargmodes;
+       char       *proargnames;
        char       *provolatile;
        char       *proisstrict;
        char       *prosecdef;
        char       *lanname;
        char       *rettypename;
+       int                     nallargs;
+       char      **allargtypes = NULL;
+       char      **argmodes = NULL;
+       char      **argnames = NULL;
 
-       /* Dump only funcs in dumpable namespaces */
-       if (!finfo->pronamespace->dump || dataOnly)
+       /* Skip if not to be dumped */
+       if (!finfo->dobj.dump || dataOnly)
                return;
 
        query = createPQExpBuffer();
@@ -4711,13 +5865,40 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        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 "
                                                  "FROM pg_catalog.pg_proc "
@@ -4728,10 +5909,13 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        {
                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 "
+                 "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
                                                  "FROM pg_proc "
                                                  "WHERE oid = '%u'::oid",
                                                  finfo->dobj.catId.oid);
@@ -4740,10 +5924,13 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        {
                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 "
+                 "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
                                                  "FROM pg_proc "
                                                  "WHERE oid = '%u'::oid",
                                                  finfo->dobj.catId.oid);
@@ -4764,6 +5951,9 @@ dumpFunc(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"));
@@ -4776,11 +5966,20 @@ dumpFunc(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
@@ -4788,19 +5987,69 @@ dumpFunc(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;
                }
        }
 
-       funcsig = format_function_signature(finfo, true);
+       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_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);
@@ -4823,7 +6072,7 @@ dumpFunc(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();
                }
        }
@@ -4838,8 +6087,9 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 
        ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
                                 funcsig_tag,
-                                finfo->pronamespace->nspname,
-                                finfo->usename,
+                                finfo->dobj.namespace->dobj.name,
+                                NULL,
+                                finfo->rolname, false,
                                 "FUNCTION", q->data, delqry->data, NULL,
                                 finfo->dobj.dependencies, finfo->dobj.nDeps,
                                 NULL, NULL);
@@ -4848,13 +6098,13 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        resetPQExpBuffer(q);
        appendPQExpBuffer(q, "FUNCTION %s", funcsig);
        dumpComment(fout, q->data,
-                               finfo->pronamespace->nspname, finfo->usename,
+                               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->pronamespace->nspname,
-                       finfo->usename, finfo->proacl);
+                       finfo->dobj.namespace->dobj.name,
+                       finfo->rolname, finfo->proacl);
 
        PQclear(res);
 
@@ -4864,6 +6114,12 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        destroyPQExpBuffer(asPart);
        free(funcsig);
        free(funcsig_tag);
+       if (allargtypes)
+               free(allargtypes);
+       if (argmodes)
+               free(argmodes);
+       if (argnames)
+               free(argnames);
 }
 
 
@@ -4893,9 +6149,8 @@ dumpCast(Archive *fout, CastInfo *cast)
        /*
         * 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 namespaces are
-        * included in the dump. Builtin meaning, the namespace name does
-        * not start with "pg_".
+        * 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);
@@ -4906,32 +6161,32 @@ dumpCast(Archive *fout, CastInfo *cast)
        /*
         * Skip this cast if all objects are from pg_
         */
-       if ((funcInfo == NULL || strncmp(funcInfo->pronamespace->nspname, "pg_", 3) == 0) &&
-               strncmp(sourceInfo->typnamespace->nspname, "pg_", 3) == 0 &&
-               strncmp(targetInfo->typnamespace->nspname, "pg_", 3) == 0)
+       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;
 
        /*
-        * Skip cast if function isn't from pg_ and that namespace is
-        * not dumped.
+        * Skip cast if function isn't from pg_ and is not to be dumped.
         */
-       if (funcInfo && 
-               strncmp(funcInfo->pronamespace->nspname, "pg_", 3) != 0 &&
-               !funcInfo->pronamespace->dump)
+       if (funcInfo &&
+               strncmp(funcInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
+               !funcInfo->dobj.dump)
                return;
 
        /*
-        * Same for the Source type
+        * Same for the source type
         */
-       if (strncmp(sourceInfo->typnamespace->nspname, "pg_", 3) != 0 &&
-               !sourceInfo->typnamespace->dump)
+       if (strncmp(sourceInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
+               !sourceInfo->dobj.dump)
                return;
 
        /*
         * and the target type.
         */
-       if (strncmp(targetInfo->typnamespace->nspname, "pg_", 3) != 0 &&
-               !targetInfo->typnamespace->dump)
+       if (strncmp(targetInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
+               !targetInfo->dobj.dump)
                return;
 
        /* Make sure we are in proper schema (needed for getFormattedTypeName) */
@@ -4952,8 +6207,16 @@ dumpCast(Archive *fout, CastInfo *cast)
        if (!OidIsValid(cast->castfunc))
                appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
        else
-               appendPQExpBuffer(defqry, "WITH FUNCTION %s",
+       {
+               /*
+                * Always qualify the function name, in case it is not in pg_catalog
+                * schema (format_function_signature won't qualify it).
+                */
+               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");
@@ -4967,8 +6230,8 @@ dumpCast(Archive *fout, CastInfo *cast)
 
        ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId,
                                 castsig->data,
-                                sourceInfo->typnamespace->nspname, "",
-                                "CAST", defqry->data, delqry->data, NULL,
+                                "pg_catalog", NULL, "",
+                                false, "CAST", defqry->data, delqry->data, NULL,
                                 cast->dobj.dependencies, cast->dobj.nDeps,
                                 NULL, NULL);
 
@@ -5028,8 +6291,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        char       *oprltcmpop;
        char       *oprgtcmpop;
 
-       /* Dump only operators in dumpable namespaces */
-       if (!oprinfo->oprnamespace->dump || dataOnly)
+       /* Skip if not to be dumped */
+       if (!oprinfo->dobj.dump || dataOnly)
                return;
 
        /*
@@ -5046,7 +6309,7 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        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)
        {
@@ -5071,9 +6334,9 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        {
                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 "
@@ -5140,7 +6403,7 @@ dumpOpr(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
@@ -5208,20 +6471,21 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
                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->dobj.catId, oprinfo->dobj.dumpId,
-                                oprinfo->oprname,
-                                oprinfo->oprnamespace->nspname, oprinfo->usename,
-                                "OPERATOR", q->data, delq->data, NULL,
+                                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);
 
@@ -5229,7 +6493,7 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        resetPQExpBuffer(q);
        appendPQExpBuffer(q, "OPERATOR %s", oprid->data);
        dumpComment(fout, q->data,
-                               oprinfo->oprnamespace->nspname, oprinfo->usename,
+                               oprinfo->dobj.namespace->dobj.name, oprinfo->rolname,
                                oprinfo->dobj.catId, 0, oprinfo->dobj.dumpId);
 
        PQclear(res);
@@ -5287,14 +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    *oprInfo;
+       OprInfo    *oprInfo;
 
        /* In all cases "0" means a null reference */
        if (strcmp(opr, "0") == 0)
@@ -5303,23 +6568,34 @@ convertOperatorReference(const char *opr)
        if (g_fout->remoteVersion >= 70300)
        {
                char       *name;
-               char       *paren;
+               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;
        }
 
        oprInfo = findOprByOid(atooid(opr));
@@ -5329,7 +6605,7 @@ convertOperatorReference(const char *opr)
                                  opr);
                return NULL;
        }
-       return oprInfo->oprname;
+       return oprInfo->dobj.name;
 }
 
 /*
@@ -5365,8 +6641,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        bool            needComma;
        int                     i;
 
-       /* Dump only opclasses in dumpable namespaces */
-       if (!opcinfo->opcnamespace->dump || dataOnly)
+       /* Skip if not to be dumped */
+       if (!opcinfo->dobj.dump || dataOnly)
                return;
 
        /*
@@ -5382,13 +6658,13 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        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 = '%u'::pg_catalog.oid",
                                          opcinfo->dobj.catId.oid);
@@ -5417,19 +6693,18 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        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    ",
@@ -5526,20 +6801,22 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        appendPQExpBuffer(q, ";\n");
 
        ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId,
-                                opcinfo->opcname,
-                                opcinfo->opcnamespace->nspname, opcinfo->usename,
-                                "OPERATOR CLASS", q->data, delq->data, NULL,
+                                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->opcname));
+                                         fmtId(opcinfo->dobj.name));
        appendPQExpBuffer(q, " USING %s",
                                          fmtId(amname));
        dumpComment(fout, q->data,
-                               NULL, opcinfo->usename,
+                               NULL, opcinfo->rolname,
                                opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId);
 
        free(amname);
@@ -5572,8 +6849,8 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        const char *conproc;
        bool            condefault;
 
-       /* Dump only conversions in dumpable namespaces */
-       if (!convinfo->connamespace->dump || dataOnly)
+       /* Skip if not to be dumped */
+       if (!convinfo->dobj.dump || dataOnly)
                return;
 
        query = createPQExpBuffer();
@@ -5582,12 +6859,12 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        details = createPQExpBuffer();
 
        /* Make sure we are in proper schema */
-       selectSourceSchema(convinfo->connamespace->nspname);
+       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, "
+                "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",
@@ -5618,35 +6895,36 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        condefault = (PQgetvalue(res, 0, i_condefault)[0] == 't');
 
        /*
-        * 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 CONVERSION %s",
-                                         fmtId(convinfo->connamespace->nspname));
+                                         fmtId(convinfo->dobj.namespace->dobj.name));
        appendPQExpBuffer(delq, ".%s;\n",
-                                         fmtId(convinfo->conname));
+                                         fmtId(convinfo->dobj.name));
 
        appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
-                                       (condefault) ? "DEFAULT " : "", 
-                                       fmtId(convinfo->conname));
-       appendStringLiteral(q, conforencoding, true);
+                                         (condefault) ? "DEFAULT " : "",
+                                         fmtId(convinfo->dobj.name));
+       appendStringLiteralAH(q, conforencoding, fout);
        appendPQExpBuffer(q, " TO ");
-       appendStringLiteral(q, contoencoding, true);
+       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->conname,
-                                convinfo->connamespace->nspname, convinfo->usename,
-                                "CONVERSION", q->data, delq->data, NULL,
+                                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->conname));
+       appendPQExpBuffer(q, "CONVERSION %s", fmtId(convinfo->dobj.name));
        dumpComment(fout, q->data,
-                               convinfo->connamespace->nspname, convinfo->usename,
+                               convinfo->dobj.namespace->dobj.name, convinfo->rolname,
                                convinfo->dobj.catId, 0, convinfo->dobj.dumpId);
 
        PQclear(res);
@@ -5667,31 +6945,33 @@ 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->aggfn.proname));
+                                                 fmtId(agginfo->aggfn.dobj.name));
        else
-               appendPQExpBuffer(&buf, "%s", agginfo->aggfn.proname);
+               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));
-       }
+               appendPQExpBuffer(&buf, "(");
+               for (j = 0; j < agginfo->aggfn.nargs; j++)
+               {
+                       char       *typname;
 
+                       typname = getFormattedTypeName(agginfo->aggfn.argtypes[j], zeroAsOpaque);
+
+                       appendPQExpBuffer(&buf, "%s%s",
+                                                         (j > 0) ? ", " : "",
+                                                         typname);
+                       free(typname);
+               }
+               appendPQExpBuffer(&buf, ")");
+       }
        return buf.data;
 }
 
@@ -5712,19 +6992,19 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        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;
 
-       /* Dump only aggs in dumpable namespaces */
-       if (!agginfo->aggfn.pronamespace->dump || dataOnly)
+       /* Skip if not to be dumped */
+       if (!agginfo->aggfn.dobj.dump || dataOnly)
                return;
 
        query = createPQExpBuffer();
@@ -5733,18 +7013,29 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        details = createPQExpBuffer();
 
        /* Make sure we are in proper schema */
-       selectSourceSchema(agginfo->aggfn.pronamespace->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 = '%u'::pg_catalog.oid",
                                                  agginfo->aggfn.dobj.catId.oid);
@@ -5752,11 +7043,9 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        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 = '%u'::oid",
@@ -5767,9 +7056,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                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 = '%u'::oid",
@@ -5790,20 +7078,16 @@ dumpAgg(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 for format_aggregate_signature */
-       agginfo->anybasetype = (PQgetvalue(res, 0, i_anybasetype)[0] == 't');
-       /* we save fmtbasetype for format_aggregate_signature */
-       agginfo->fmtbasetype = strdup(PQgetvalue(res, 0, i_fmtbasetype));
        convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't');
 
        aggsig = format_aggregate_signature(agginfo, fout, true);
@@ -5819,27 +7103,20 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        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",
@@ -5849,7 +7126,7 @@ dumpAgg(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)
@@ -5858,22 +7135,29 @@ dumpAgg(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->aggfn.pronamespace->nspname),
+                                         fmtId(agginfo->aggfn.dobj.namespace->dobj.name),
                                          aggsig);
 
        appendPQExpBuffer(q, "CREATE AGGREGATE %s (\n%s\n);\n",
-                                         fmtId(agginfo->aggfn.proname),
-                                         details->data);
+                                         aggsig, details->data);
 
        ArchiveEntry(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
                                 aggsig_tag,
-                                agginfo->aggfn.pronamespace->nspname, agginfo->aggfn.usename,
-                                "AGGREGATE", q->data, delq->data, NULL,
+                                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);
 
@@ -5881,13 +7165,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        resetPQExpBuffer(q);
        appendPQExpBuffer(q, "AGGREGATE %s", aggsig);
        dumpComment(fout, q->data,
-                               agginfo->aggfn.pronamespace->nspname, agginfo->aggfn.usename,
+                       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 aggregates on ANY.
+        * 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);
@@ -5898,8 +7182,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
                        "FUNCTION",
                        aggsig, aggsig_tag,
-                       agginfo->aggfn.pronamespace->nspname,
-                       agginfo->aggfn.usename, agginfo->aggfn.proacl);
+                       agginfo->aggfn.dobj.namespace->dobj.name,
+                       agginfo->aggfn.rolname, agginfo->aggfn.proacl);
 
        free(aggsig);
        free(aggsig_tag);
@@ -5918,7 +7202,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
  *
  * 'objCatId' is the catalog ID of the underlying object.
  * 'objDumpId' is the dump ID of the underlying object.
- * 'type' must be TABLE, FUNCTION, LANGUAGE, or SCHEMA.
+ * '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).
@@ -5951,8 +7235,9 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
        if (sql->len > 0)
                ArchiveEntry(fout, nilCatalogId, createDumpId(),
                                         tag, nspname,
+                                        NULL,
                                         owner ? owner : "",
-                                        "ACL", sql->data, "", NULL,
+                                        false, "ACL", sql->data, "", NULL,
                                         &(objDumpId), 1,
                                         NULL, NULL);
 
@@ -5968,7 +7253,7 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
 {
        char       *namecopy;
 
-       if (tbinfo->dump)
+       if (tbinfo->dobj.dump)
        {
                if (tbinfo->relkind == RELKIND_SEQUENCE)
                        dumpSequence(fout, tbinfo);
@@ -5976,10 +7261,11 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
                        dumpTableSchema(fout, tbinfo);
 
                /* Handle the ACL here */
-               namecopy = strdup(fmtId(tbinfo->relname));
-               dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE",
-                               namecopy, tbinfo->relname,
-                               tbinfo->relnamespace->nspname, tbinfo->usename,
+               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);
        }
@@ -6005,7 +7291,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                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)
@@ -6026,7 +7312,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                {
                        appendPQExpBuffer(query, "SELECT definition as viewdef "
                                                          " from pg_views where viewname = ");
-                       appendStringLiteral(query, tbinfo->relname, true);
+                       appendStringLiteralAH(query, tbinfo->dobj.name, fout);
                        appendPQExpBuffer(query, ";");
                }
 
@@ -6037,10 +7323,10 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                {
                        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);
+                                                 tbinfo->dobj.name);
                        exit_nicely();
                }
 
@@ -6049,7 +7335,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                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();
                }
 
@@ -6058,12 +7344,12 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                 * 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);
        }
@@ -6078,12 +7364,12 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                 * 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++)
                {
@@ -6102,16 +7388,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                /* 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
                                {
@@ -6122,24 +7400,17 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                }
 
                                /*
-                                * Default value --- suppress if inherited, serial,
-                                * or to be printed separately.
+                                * 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->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");
@@ -6162,7 +7433,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                appendPQExpBuffer(q, ",\n    ");
 
                        appendPQExpBuffer(q, "CONSTRAINT %s ",
-                                                         fmtId(constr->conname));
+                                                         fmtId(constr->dobj.name));
                        appendPQExpBuffer(q, "%s", constr->condef);
 
                        actual_atts++;
@@ -6179,16 +7450,17 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 
                                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, ")");
                }
 
-               appendPQExpBuffer(q, tbinfo->hasoids ? " WITH OIDS" : " WITHOUT OIDS");
+               if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
+                       appendPQExpBuffer(q, "\nWITH (%s)", tbinfo->reloptions);
 
                appendPQExpBuffer(q, ";\n");
 
@@ -6196,15 +7468,15 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                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",
@@ -6213,8 +7485,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 
                        /*
                         * 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])
                        {
@@ -6237,13 +7508,12 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                }
 
                                /*
-                                * 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",
@@ -6254,8 +7524,11 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
        }
 
        ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
-                                tbinfo->relname,
-                                tbinfo->relnamespace->nspname, tbinfo->usename,
+                                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);
@@ -6263,6 +7536,17 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
        /* Dump Table Comments */
        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;
+
+               dumpTableConstraintComment(fout, constr);
+       }
+
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
@@ -6280,37 +7564,38 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
        PQExpBuffer delq;
 
        /* Only print it if "separate" mode is selected */
-       if (!tbinfo->dump || !adinfo->separate || dataOnly)
+       if (!tbinfo->dobj.dump || !adinfo->separate || dataOnly)
                return;
 
-       /* Don't print inherited or serial defaults, either */
-       if (tbinfo->inhAttrDef[adnum-1] || tbinfo->attisserial[adnum-1])
+       /* Don't print inherited defaults, either */
+       if (tbinfo->inhAttrDef[adnum - 1])
                return;
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
 
        appendPQExpBuffer(q, "ALTER TABLE %s ",
-                                         fmtId(tbinfo->relname));
+                                         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
+        * DROP must be fully qualified in case same name appears in pg_catalog
         */
        appendPQExpBuffer(delq, "ALTER TABLE %s.",
-                                         fmtId(tbinfo->relnamespace->nspname));
+                                         fmtId(tbinfo->dobj.namespace->dobj.name));
        appendPQExpBuffer(delq, "%s ",
-                                         fmtId(tbinfo->relname));
+                                         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->relnamespace->nspname, tbinfo->usename,
-                                "DEFAULT", q->data, delq->data, NULL,
+                                tbinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                tbinfo->rolname,
+                                false, "DEFAULT", q->data, delq->data, NULL,
                                 adinfo->dobj.dependencies, adinfo->dobj.nDeps,
                                 NULL, NULL);
 
@@ -6348,7 +7633,7 @@ 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 */
 }
@@ -6371,8 +7656,9 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
        delq = createPQExpBuffer();
 
        /*
-        * If there's an associated constraint, don't dump the index per se,
-        * but do dump any comment for it.
+        * 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)
        {
@@ -6383,24 +7669,25 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
                if (indxinfo->indisclustered)
                {
                        appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
-                                                         fmtId(tbinfo->relname));
+                                                         fmtId(tbinfo->dobj.name));
                        appendPQExpBuffer(q, " ON %s;\n",
-                                                         fmtId(indxinfo->indexname));
+                                                         fmtId(indxinfo->dobj.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 INDEX %s.",
-                                                 fmtId(tbinfo->relnamespace->nspname));
+                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
                appendPQExpBuffer(delq, "%s;\n",
-                                                 fmtId(indxinfo->indexname));
+                                                 fmtId(indxinfo->dobj.name));
 
                ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
-                                        indxinfo->indexname,
-                                        tbinfo->relnamespace->nspname,
-                                        tbinfo->usename,
+                                        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);
@@ -6409,10 +7696,10 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
        /* Dump Index Comments */
        resetPQExpBuffer(q);
        appendPQExpBuffer(q, "INDEX %s",
-                                         fmtId(indxinfo->indexname));
+                                         fmtId(indxinfo->dobj.name));
        dumpComment(fout, q->data,
-                               tbinfo->relnamespace->nspname,
-                               tbinfo->usename,
+                               tbinfo->dobj.namespace->dobj.name,
+                               tbinfo->rolname,
                                indxinfo->dobj.catId, 0, indxinfo->dobj.dumpId);
 
        destroyPQExpBuffer(q);
@@ -6430,9 +7717,8 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
        PQExpBuffer q;
        PQExpBuffer delq;
 
-       if (dataOnly)
-               return;
-       if (tbinfo && !tbinfo->dump)
+       /* Skip if not to be dumped */
+       if (!coninfo->dobj.dump || dataOnly)
                return;
 
        q = createPQExpBuffer();
@@ -6448,15 +7734,15 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
                if (indxinfo == NULL)
                {
-                       write_msg(NULL, "missing index for constraint %s\n",
-                                         coninfo->conname);
+                       write_msg(NULL, "missing index for constraint \"%s\"\n",
+                                         coninfo->dobj.name);
                        exit_nicely();
                }
 
                appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
-                                                 fmtId(tbinfo->relname));
+                                                 fmtId(tbinfo->dobj.name));
                appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s (",
-                                                 fmtId(coninfo->conname),
+                                                 fmtId(coninfo->dobj.name),
                                                  coninfo->contype == 'p' ? "PRIMARY KEY" : "UNIQUE");
 
                for (k = 0; k < indxinfo->indnkeys; k++)
@@ -6473,32 +7759,38 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                                                          fmtId(attname));
                }
 
-               appendPQExpBuffer(q, ");\n");
+               appendPQExpBuffer(q, ")");
+
+               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->relname));
+                                                         fmtId(tbinfo->dobj.name));
                        appendPQExpBuffer(q, " ON %s;\n",
-                                                         fmtId(indxinfo->indexname));
+                                                         fmtId(indxinfo->dobj.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, "ALTER TABLE ONLY %s.",
-                                                 fmtId(tbinfo->relnamespace->nspname));
+                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
                appendPQExpBuffer(delq, "%s ",
-                                                 fmtId(tbinfo->relname));
+                                                 fmtId(tbinfo->dobj.name));
                appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
-                                                 fmtId(coninfo->conname));
+                                                 fmtId(coninfo->dobj.name));
 
                ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-                                        coninfo->conname,
-                                        tbinfo->relnamespace->nspname,
-                                        tbinfo->usename,
+                                        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);
@@ -6506,13 +7798,13 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
        else if (coninfo->contype == 'f')
        {
                /*
-                * XXX Potentially wrap in a 'SET CONSTRAINTS OFF' block so that
-                * the current table data is not processed
+                * 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->relname));
+                                                 fmtId(tbinfo->dobj.name));
                appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
-                                                 fmtId(coninfo->conname),
+                                                 fmtId(coninfo->dobj.name),
                                                  coninfo->condef);
 
                /*
@@ -6520,16 +7812,17 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                 * pg_catalog
                 */
                appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.",
-                                                 fmtId(tbinfo->relnamespace->nspname));
+                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
                appendPQExpBuffer(delq, "%s ",
-                                                 fmtId(tbinfo->relname));
+                                                 fmtId(tbinfo->dobj.name));
                appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
-                                                 fmtId(coninfo->conname));
+                                                 fmtId(coninfo->dobj.name));
 
                ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-                                        coninfo->conname,
-                                        tbinfo->relnamespace->nspname,
-                                        tbinfo->usename,
+                                        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);
@@ -6543,9 +7836,9 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                {
                        /* not ONLY since we want it to propagate to children */
                        appendPQExpBuffer(q, "ALTER TABLE %s\n",
-                                                         fmtId(tbinfo->relname));
+                                                         fmtId(tbinfo->dobj.name));
                        appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
-                                                         fmtId(coninfo->conname),
+                                                         fmtId(coninfo->dobj.name),
                                                          coninfo->condef);
 
                        /*
@@ -6553,16 +7846,17 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                         * pg_catalog
                         */
                        appendPQExpBuffer(delq, "ALTER TABLE %s.",
-                                                         fmtId(tbinfo->relnamespace->nspname));
+                                                         fmtId(tbinfo->dobj.namespace->dobj.name));
                        appendPQExpBuffer(delq, "%s ",
-                                                         fmtId(tbinfo->relname));
+                                                         fmtId(tbinfo->dobj.name));
                        appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
-                                                         fmtId(coninfo->conname));
+                                                         fmtId(coninfo->dobj.name));
 
                        ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-                                                coninfo->conname,
-                                                tbinfo->relnamespace->nspname,
-                                                tbinfo->usename,
+                                                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);
@@ -6573,13 +7867,13 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                /* CHECK constraint on a domain */
                TypeInfo   *tinfo = coninfo->condomain;
 
-               /* Ignore if not to be dumped separately, or if not dumping domain */
-               if (coninfo->separate && tinfo->typnamespace->dump)
+               /* Ignore if not to be dumped separately */
+               if (coninfo->separate)
                {
                        appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
-                                                         fmtId(tinfo->typname));
+                                                         fmtId(tinfo->dobj.name));
                        appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
-                                                         fmtId(coninfo->conname),
+                                                         fmtId(coninfo->dobj.name),
                                                          coninfo->condef);
 
                        /*
@@ -6587,16 +7881,17 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                         * pg_catalog
                         */
                        appendPQExpBuffer(delq, "ALTER DOMAIN %s.",
-                                                         fmtId(tinfo->typnamespace->nspname));
+                                                         fmtId(tinfo->dobj.namespace->dobj.name));
                        appendPQExpBuffer(delq, "%s ",
-                                                         fmtId(tinfo->typname));
+                                                         fmtId(tinfo->dobj.name));
                        appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
-                                                         fmtId(coninfo->conname));
+                                                         fmtId(coninfo->dobj.name));
 
                        ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-                                                coninfo->conname,
-                                                tinfo->typnamespace->nspname,
-                                                tinfo->usename,
+                                                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);
@@ -6604,68 +7899,42 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
        }
        else
        {
-               write_msg(NULL, "unexpected constraint type\n");
+               write_msg(NULL, "unrecognized constraint type: %c\n", coninfo->contype);
                exit_nicely();
        }
 
        /* Dump Constraint Comments --- only works for table constraints */
-       if (tbinfo)
-       {
-               resetPQExpBuffer(q);
-               appendPQExpBuffer(q, "CONSTRAINT %s ",
-                                                 fmtId(coninfo->conname));
-               appendPQExpBuffer(q, "ON %s",
-                                                 fmtId(tbinfo->relname));
-               dumpComment(fout, q->data,
-                                       tbinfo->relnamespace->nspname,
-                                       tbinfo->usename,
-                                       coninfo->dobj.catId, 0, coninfo->dobj.dumpId);
-       }
+       if (tbinfo && coninfo->separate)
+               dumpTableConstraintComment(fout, coninfo);
 
        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];
-
-       do_sql_command(g_conn,
-                                  "CREATE TEMPORARY TABLE pgdump_oid (dummy integer)");
-       res = PQexec(g_conn, "INSERT INTO pgdump_oid VALUES (0)");
-       check_sql_result(res, g_conn, "INSERT INTO pgdump_oid VALUES (0)",
-                                        PGRES_COMMAND_OK);
-       max_oid = PQoidValue(res);
-       if (max_oid == 0)
-       {
-               write_msg(NULL, "inserted invalid OID\n");
-               exit_nicely();
-       }
-       PQclear(res);
-       do_sql_command(g_conn, "DROP TABLE pgdump_oid;");
-       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, nilCatalogId, createDumpId(),
-                                "Max OID", NULL, "",
-                                "<Init>", sql, "", NULL,
-                                NULL, 0,
-                                NULL, NULL);
+       TableInfo  *tbinfo = coninfo->contable;
+       PQExpBuffer q = createPQExpBuffer();
+
+       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);
 }
 
 /*
@@ -6685,7 +7954,7 @@ 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);
        check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
@@ -6712,7 +7981,7 @@ findLastBuiltinOid_V71(const char *dbname)
  * find the last built in oid
  *
  * 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
+ * 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
@@ -6760,24 +8029,24 @@ dumpSequence(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);
        check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
@@ -6785,16 +8054,16 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
        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
@@ -6812,15 +8081,14 @@ dumpSequence(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 && !OidIsValid(tbinfo->owning_tab))
+       if (!dataOnly)
        {
                resetPQExpBuffer(delqry);
 
@@ -6829,14 +8097,14 @@ dumpSequence(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);
@@ -6854,43 +8122,83 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
                        appendPQExpBuffer(query, "    NO MINVALUE\n");
 
                appendPQExpBuffer(query,
-                                                 "    CACHE %s%s;\n",
+                                                 "    CACHE %s%s",
                                                  cache, (cycled ? "\n    CYCLE" : ""));
 
+               appendPQExpBuffer(query, ";\n");
+
                ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
-                                        tbinfo->relname,
-                                        tbinfo->relnamespace->nspname, tbinfo->usename,
-                                        "SEQUENCE", query->data, delqry->data, NULL,
+                                        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, nilCatalogId, createDumpId(),
-                                        tbinfo->relname,
-                                        tbinfo->relnamespace->nspname, tbinfo->usename,
-                                        "SEQUENCE SET", query->data, "", NULL,
+                                        tbinfo->dobj.name,
+                                        tbinfo->dobj.namespace->dobj.name,
+                                        NULL,
+                                        tbinfo->rolname,
+                                        false, "SEQUENCE SET", query->data, "", NULL,
                                         &(tbinfo->dobj.dumpId), 1,
                                         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->dobj.catId, 0, tbinfo->dobj.dumpId);
-       }
-
        PQclear(res);
 
        destroyPQExpBuffer(query);
@@ -6913,25 +8221,24 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
        delqry = createPQExpBuffer();
 
        /*
-        * 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 TRIGGER %s ",
-                                         fmtId(tginfo->tgname));
+                                         fmtId(tginfo->dobj.name));
        appendPQExpBuffer(delqry, "ON %s.",
-                                         fmtId(tbinfo->relnamespace->nspname));
+                                         fmtId(tbinfo->dobj.namespace->dobj.name));
        appendPQExpBuffer(delqry, "%s;\n",
-                                         fmtId(tbinfo->relname));
+                                         fmtId(tbinfo->dobj.name));
 
        if (tginfo->tgisconstraint)
        {
                appendPQExpBuffer(query, "CREATE CONSTRAINT TRIGGER ");
-               appendPQExpBuffer(query, fmtId(tginfo->tgconstrname));
+               appendPQExpBufferStr(query, fmtId(tginfo->tgconstrname));
        }
        else
        {
                appendPQExpBuffer(query, "CREATE TRIGGER ");
-               appendPQExpBuffer(query, fmtId(tginfo->tgname));
+               appendPQExpBufferStr(query, fmtId(tginfo->dobj.name));
        }
        appendPQExpBuffer(query, "\n    ");
 
@@ -6962,7 +8269,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
                        appendPQExpBuffer(query, " UPDATE");
        }
        appendPQExpBuffer(query, " ON %s\n",
-                                         fmtId(tbinfo->relname));
+                                         fmtId(tbinfo->dobj.name));
 
        if (tginfo->tgisconstraint)
        {
@@ -7003,6 +8310,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
        {
                const char *s = p;
 
+               /* Set 'p' to end of arg string. marked by '\000' */
                for (;;)
                {
                        p = strchr(p, '\\');
@@ -7010,25 +8318,32 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
                        {
                                write_msg(NULL, "invalid argument string (%s) for trigger \"%s\" on table \"%s\"\n",
                                                  tginfo->tgargs,
-                                                 tginfo->tgname,
-                                                 tbinfo->relname);
+                                                 tginfo->dobj.name,
+                                                 tbinfo->dobj.name);
                                exit_nicely();
                        }
                        p++;
-                       if (*p == '\\')
+                       if (*p == '\\')         /* is it '\\'? */
                        {
                                p++;
                                continue;
                        }
-                       if (p[0] == '0' && p[1] == '0' && p[2] == '0')
+                       if (p[0] == '0' && p[1] == '0' && p[2] == '0')          /* is it '\000'? */
                                break;
                }
                p--;
+
                appendPQExpBufferChar(query, '\'');
                while (s < p)
                {
                        if (*s == '\'')
-                               appendPQExpBufferChar(query, '\\');
+                               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++);
                }
                appendPQExpBufferChar(query, '\'');
@@ -7038,22 +8353,31 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
        }
        appendPQExpBuffer(query, ");\n");
 
+       if (!tginfo->tgenabled)
+       {
+               appendPQExpBuffer(query, "\nALTER TABLE %s ",
+                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(query, "DISABLE TRIGGER %s;\n",
+                                                 fmtId(tginfo->dobj.name));
+       }
+
        ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId,
-                                tginfo->tgname,
-                                tbinfo->relnamespace->nspname,
-                                tbinfo->usename,
+                                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(query);
        appendPQExpBuffer(query, "TRIGGER %s ",
-                                         fmtId(tginfo->tgname));
+                                         fmtId(tginfo->dobj.name));
        appendPQExpBuffer(query, "ON %s",
-                                         fmtId(tbinfo->relname));
+                                         fmtId(tbinfo->dobj.name));
 
        dumpComment(fout, query->data,
-                               tbinfo->relnamespace->nspname, tbinfo->usename,
+                               tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                                tginfo->dobj.catId, 0, tginfo->dobj.dumpId);
 
        destroyPQExpBuffer(query);
@@ -7073,23 +8397,21 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
        PQExpBuffer delcmd;
        PGresult   *res;
 
-       /*
-        * Ignore rules for not-to-be-dumped tables
-        */
-       if (tbinfo == NULL || !tbinfo->dump || dataOnly)
+       /* Skip if not to be dumped */
+       if (!rinfo->dobj.dump || dataOnly)
                return;
 
        /*
-        * If it is an ON SELECT rule, we do not need to dump it because
-        * it will be handled via CREATE VIEW for the table.
+        * 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->ev_type == '1' && rinfo->is_instead)
+       if (!rinfo->separate)
                return;
 
        /*
         * Make sure we are in proper schema.
         */
-       selectSourceSchema(tbinfo->relnamespace->nspname);
+       selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
 
        query = createPQExpBuffer();
        cmd = createPQExpBuffer();
@@ -7106,7 +8428,7 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
                /* Rule name was unique before 7.3 ... */
                appendPQExpBuffer(query,
                                                  "SELECT pg_get_ruledef('%s') AS definition",
-                                                 rinfo->rulename);
+                                                 rinfo->dobj.name);
        }
 
        res = PQexec(g_conn, query->data);
@@ -7115,27 +8437,27 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
        if (PQntuples(res) != 1)
        {
                write_msg(NULL, "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned",
-                                 rinfo->rulename, tbinfo->relname);
+                                 rinfo->dobj.name, tbinfo->dobj.name);
                exit_nicely();
        }
 
        printfPQExpBuffer(cmd, "%s\n", PQgetvalue(res, 0, 0));
 
        /*
-        * 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(delcmd, "DROP RULE %s ",
-                                         fmtId(rinfo->rulename));
+                                         fmtId(rinfo->dobj.name));
        appendPQExpBuffer(delcmd, "ON %s.",
-                                         fmtId(tbinfo->relnamespace->nspname));
+                                         fmtId(tbinfo->dobj.namespace->dobj.name));
        appendPQExpBuffer(delcmd, "%s;\n",
-                                         fmtId(tbinfo->relname));
+                                         fmtId(tbinfo->dobj.name));
 
        ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId,
-                                rinfo->rulename,
-                                tbinfo->relnamespace->nspname,
-                                tbinfo->usename,
+                                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);
@@ -7143,12 +8465,12 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
        /* Dump rule comments */
        resetPQExpBuffer(query);
        appendPQExpBuffer(query, "RULE %s",
-                                         fmtId(rinfo->rulename));
+                                         fmtId(rinfo->dobj.name));
        appendPQExpBuffer(query, " ON %s",
-                                         fmtId(tbinfo->relname));
+                                         fmtId(tbinfo->dobj.name));
        dumpComment(fout, query->data,
-                               tbinfo->relnamespace->nspname,
-                               tbinfo->usename,
+                               tbinfo->dobj.namespace->dobj.name,
+                               tbinfo->rolname,
                                rinfo->dobj.catId, 0, rinfo->dobj.dumpId);
 
        PQclear(res);
@@ -7181,7 +8503,7 @@ getDependencies(void)
                return;
 
        if (g_verbose)
-               write_msg(NULL, "fetching dependency data\n");
+               write_msg(NULL, "reading dependency data\n");
 
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
@@ -7207,8 +8529,8 @@ getDependencies(void)
 
        /*
         * 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.
+        * multiple entries for the same object will appear together; this saves
+        * on searches.
         */
        dobj = NULL;
 
@@ -7253,7 +8575,20 @@ getDependencies(void)
                        continue;
                }
 
-               addObjectDependency(dobj, refdobj->dumpId);
+               /*
+                * 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.
+                */
+               if (deptype == 'i' &&
+                       dobj->objType == DO_TABLE &&
+                       refdobj->objType == DO_TYPE)
+                       addObjectDependency(refdobj, dobj->dumpId);
+               else
+                       /* normal case */
+                       addObjectDependency(dobj, refdobj->dumpId);
        }
 
        PQclear(res);
@@ -7386,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"))
        {
@@ -7423,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);