]> 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 fc2633f27bc2860f6853ef9baeb13bc03d168a91..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-2005, 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.424 2005/12/03 21:06:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.447 2006/08/21 00:57:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,6 +25,7 @@
 #include "postgres.h"
 
 #include <unistd.h>
+
 #include <ctype.h>
 #ifdef ENABLE_NLS
 #include <locale.h>
 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"
 
@@ -93,8 +91,19 @@ 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 */
 
@@ -127,6 +136,7 @@ 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);
@@ -170,6 +180,7 @@ 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);
@@ -180,6 +191,9 @@ static void check_sql_result(PGresult *res, PGconn *conn, const char *query,
 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";
@@ -188,12 +202,14 @@ main(int argc, char **argv)
        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;
@@ -225,9 +241,11 @@ 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'},
@@ -280,7 +298,7 @@ main(int argc, char **argv)
                }
        }
 
-       while ((c = getopt_long(argc, argv, "abcCdDE:f: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)
@@ -331,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 */
@@ -360,10 +412,6 @@ main(int argc, char **argv)
                                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);
@@ -448,7 +496,7 @@ main(int argc, char **argv)
                exit(1);
        }
 
-       if (selectTableName != NULL || selectSchemaName != NULL)
+       if (matchingTables != NULL || matchingSchemas != NULL)
                outputBlobs = false;
 
        if (dumpInserts == true && oids == true)
@@ -511,25 +559,35 @@ main(int argc, char **argv)
        g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport,
                                                         username, force_password, ignore_version);
 
+       /* Set the client encoding if requested */
+       if (dumpencoding)
+       {
+               if (PQsetClientEncoding(g_conn, dumpencoding) < 0)
+               {
+                       write_msg(NULL, "invalid client encoding \"%s\" specified\n",
+                                         dumpencoding);
+                       exit(1);
+               }
+       }
+
        /*
-        * Start serializable transaction to dump consistent data.
+        * Get the active encoding and the standard_conforming_strings setting,
+        * so we know how to escape strings.
         */
-       do_sql_command(g_conn, "BEGIN");
+       g_fout->encoding = PQclientEncoding(g_conn);
 
-       do_sql_command(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
+       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");
 
-       /* Set the client encoding */
-       if (dumpencoding)
-       {
-               char       *cmd = malloc(strlen(dumpencoding) + 32);
+       /*
+        * Start serializable transaction to dump consistent data.
+        */
+       do_sql_command(g_conn, "BEGIN");
 
-               sprintf(cmd, "SET client_encoding='%s'", dumpencoding);
-               do_sql_command(g_conn, cmd);
-               free(cmd);
-       }
+       do_sql_command(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
 
        /* Select the appropriate subquery to convert user IDs to names */
        if (g_fout->remoteVersion >= 80100)
@@ -557,11 +615,167 @@ 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);
@@ -612,11 +826,12 @@ main(int argc, char **argv)
         * order.
         */
 
-       /* First the special encoding entry. */
+       /* First the special ENCODING and STDSTRINGS entries. */
        dumpEncoding(g_fout);
+       dumpStdStrings(g_fout);
 
-       /* The database item is always second, unless we don't want it at all */
-       if (!dataOnly && selectTableName == NULL && selectSchemaName == NULL)
+       /* 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. */
@@ -675,28 +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(_("  -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(_("  -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(_("  -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"));
+                        "                              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"));
+                        "                              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"));
@@ -726,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->dobj.name, 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->dobj.name, "pg_", 3) == 0 ||
-                        strcmp(nsinfo->dobj.name, "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;
 }
 
 /*
@@ -758,28 +979,80 @@ selectDumpableTable(TableInfo *tbinfo)
         * tablename has been specified, dump matching table name; else, do not
         * dump.
         */
-       tbinfo->dump = false;
-       if (tbinfo->dobj.namespace->dump)
-               tbinfo->dump = true;
-       else if (selectTableName != NULL &&
-                        strcmp(tbinfo->dobj.name, selectTableName) == 0)
-       {
-               /* If both -s and -t specified, must match both to dump */
-               if (selectSchemaName == NULL)
-                       tbinfo->dump = true;
-               else if (strcmp(tbinfo->dobj.namespace->dobj.name, selectSchemaName) == 0)
-                       tbinfo->dump = true;
+       tbinfo->dobj.dump = false;
+
+       if (matchingTables == NULL)
+       {
+               if (tbinfo->dobj.namespace->dobj.dump)
+                       tbinfo->dobj.dump = true;
+       }
+       else
+       {
+               char *search_oid = malloc(20);
+
+               sprintf(search_oid, " %d ", tbinfo->dobj.catId.oid);
+               if (strstr(matchingTables, search_oid) != NULL)
+                       tbinfo->dobj.dump = true;
+
+               free(search_oid);
        }
 }
 
+/*
+ * selectDumpableType: policy-setting subroutine
+ *             Mark a type as to be dumped or not
+ */
+static void
+selectDumpableType(TypeInfo *tinfo)
+{
+       /* Dump only types in dumpable namespaces */
+       if (!tinfo->dobj.namespace->dobj.dump)
+               tinfo->dobj.dump = false;
+
+       /* skip complex types, except for standalone composite types */
+       /* (note: this test should now be unnecessary) */
+       else if (OidIsValid(tinfo->typrelid) &&
+                        tinfo->typrelkind != RELKIND_COMPOSITE_TYPE)
+               tinfo->dobj.dump = false;
+
+       /* skip undefined placeholder types */
+       else if (!tinfo->isDefined)
+               tinfo->dobj.dump = false;
+
+       /* skip all array types that start w/ underscore */
+       else if ((tinfo->dobj.name[0] == '_') &&
+                        OidIsValid(tinfo->typelem))
+               tinfo->dobj.dump = false;
+
+       else
+               tinfo->dobj.dump = true;
+}
+
+/*
+ * selectDumpableObject: policy-setting subroutine
+ *             Mark a generic dumpable object as to be dumped or not
+ *
+ * Use this only for object types without a special-case routine above.
+ */
+static void
+selectDumpableObject(DumpableObject *dobj)
+{
+       /*
+        * Default policy is to dump if parent namespace is dumpable,
+        * or always for non-namespace-associated items.
+        */
+       if (dobj->namespace)
+               dobj->dump = dobj->namespace->dobj.dump;
+       else
+               dobj->dump = true;
+}
+
 /*
  *     Dump a table's contents for loading using the COPY command
  *     - this routine is called by the Archiver when it wants the table
  *       to be dumped.
  */
 
-#define COPYBUFSIZ             8192
-
 static int
 dumpTableData_copy(Archive *fout, void *dcontext)
 {
@@ -791,8 +1064,7 @@ dumpTableData_copy(Archive *fout, void *dcontext)
        PQExpBuffer q = createPQExpBuffer();
        PGresult   *res;
        int                     ret;
-       bool            copydone;
-       char            copybuf[COPYBUFSIZ];
+       char       *copybuf;
        const char *column_list;
 
        if (g_verbose)
@@ -833,33 +1105,19 @@ dumpTableData_copy(Archive *fout, void *dcontext)
        }
        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 (ret < 0)
+                       break;                          /* done or error */
 
-               if (copybuf[0] == '\\' &&
-                       copybuf[1] == '.' &&
-                       copybuf[2] == '\0')
+               if (copybuf)
                {
-                       copydone = true;        /* don't print this... */
-               }
-               else
-               {
-                       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);
                }
 
                /*
@@ -867,7 +1125,7 @@ dumpTableData_copy(Archive *fout, void *dcontext)
                 *
                 * 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
+                * 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
@@ -904,16 +1162,20 @@ dumpTableData_copy(Archive *fout, void *dcontext)
        }
        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;
 }
@@ -1044,7 +1306,9 @@ dumpTableData_insert(Archive *fout, void *dcontext)
                                        default:
                                                /* All other types are printed as string literals. */
                                                resetPQExpBuffer(q);
-                                               appendStringLiteral(q, PQgetvalue(res, tuple, field), false);
+                                               appendStringLiteralAH(q,
+                                                                                         PQgetvalue(res, tuple, field),
+                                                                                         fout);
                                                archputs(q->data, fout);
                                                break;
                                }
@@ -1127,7 +1391,7 @@ 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;
 
@@ -1185,7 +1449,20 @@ dumpDatabase(Archive *AH)
        selectSourceSchema("pg_catalog");
 
        /* Get the database owner and parameters from pg_database */
-       if (g_fout->remoteVersion >= 80000)
+       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, "
@@ -1194,7 +1471,7 @@ dumpDatabase(Archive *AH)
                                                  "FROM pg_database "
                                                  "WHERE datname = ",
                                                  username_subquery);
-               appendStringLiteral(dbQry, datname, true);
+               appendStringLiteralAH(dbQry, datname, AH);
        }
        else if (g_fout->remoteVersion >= 70100)
        {
@@ -1205,7 +1482,7 @@ dumpDatabase(Archive *AH)
                                                  "FROM pg_database "
                                                  "WHERE datname = ",
                                                  username_subquery);
-               appendStringLiteral(dbQry, datname, true);
+               appendStringLiteralAH(dbQry, datname, AH);
        }
        else
        {
@@ -1218,7 +1495,7 @@ dumpDatabase(Archive *AH)
                                                  "FROM pg_database "
                                                  "WHERE datname = ",
                                                  username_subquery);
-               appendStringLiteral(dbQry, datname, true);
+               appendStringLiteralAH(dbQry, datname, AH);
        }
 
        res = PQexec(g_conn, dbQry->data);
@@ -1257,7 +1534,7 @@ dumpDatabase(Archive *AH)
        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",
@@ -1287,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);
 
@@ -1306,28 +1601,14 @@ dumpDatabase(Archive *AH)
 static void
 dumpEncoding(Archive *AH)
 {
-       PQExpBuffer qry;
-       PGresult   *res;
-
-       /* Can't read the encoding from pre-7.3 servers (SHOW isn't a query) */
-       if (AH->remoteVersion < 70300)
-               return;
+       const char *encname = pg_encoding_to_char(AH->encoding);
+       PQExpBuffer qry = createPQExpBuffer();
 
        if (g_verbose)
-               write_msg(NULL, "saving encoding\n");
-
-       qry = createPQExpBuffer();
-
-       appendPQExpBuffer(qry, "SHOW client_encoding");
-
-       res = PQexec(g_conn, qry->data);
-
-       check_sql_result(res, g_conn, qry->data, PGRES_TUPLES_OK);
-
-       resetPQExpBuffer(qry);
+               write_msg(NULL, "saving encoding = %s\n", encname);
 
        appendPQExpBuffer(qry, "SET client_encoding = ");
-       appendStringLiteral(qry, PQgetvalue(res, 0, 0), true);
+       appendStringLiteralAH(qry, encname, AH);
        appendPQExpBuffer(qry, ";\n");
 
        ArchiveEntry(AH, nilCatalogId, createDumpId(),
@@ -1336,7 +1617,31 @@ dumpEncoding(Archive *AH)
                                 NULL, 0,
                                 NULL, NULL);
 
-       PQclear(res);
+       destroyPQExpBuffer(qry);
+}
+
+
+/*
+ * dumpStdStrings: put the correct escape string behavior into the archive
+ */
+static void
+dumpStdStrings(Archive *AH)
+{
+       const char *stdstrings = AH->std_strings ? "on" : "off";
+       PQExpBuffer qry = createPQExpBuffer();
+
+       if (g_verbose)
+               write_msg(NULL, "saving standard_conforming_strings = %s\n",
+                                 stdstrings);
+
+       appendPQExpBuffer(qry, "SET standard_conforming_strings = '%s';\n",
+                                         stdstrings);
+
+       ArchiveEntry(AH, nilCatalogId, createDumpId(),
+                                "STDSTRINGS", NULL, NULL, "",
+                                false, "STDSTRINGS", qry->data, "", NULL,
+                                NULL, 0,
+                                NULL, NULL);
 
        destroyPQExpBuffer(qry);
 }
@@ -1480,9 +1785,9 @@ dumpBlobComments(Archive *AH, void *arg)
 
        /* Cursor to get all BLOB comments */
        if (AH->remoteVersion >= 70200)
-               blobQry = "DECLARE blobcmt CURSOR FOR SELECT DISTINCT loid, obj_description(loid, 'pg_largeobject') FROM pg_largeobject";
+               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 DISTINCT loid, obj_description(loid) FROM pg_largeobject";
+               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'";
 
@@ -1515,7 +1820,7 @@ dumpBlobComments(Archive *AH, void *arg)
 
                        printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
                                                          blobOid);
-                       appendStringLiteral(commentcmd, comment, false);
+                       appendStringLiteralAH(commentcmd, comment, AH);
                        appendPQExpBuffer(commentcmd, ";\n");
 
                        archputs(commentcmd->data, AH);
@@ -1631,25 +1936,6 @@ getNamespaces(int *numNamespaces)
                                          nsinfo[i].dobj.name);
        }
 
-       /*
-        * 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].dobj.name, selectSchemaName) == 0)
-                               break;
-
-               /* Didn't find a match */
-               if (i == ntups)
-               {
-                       write_msg(NULL, "specified schema \"%s\" does not exist\n",
-                                         selectSchemaName);
-                       exit_nicely();
-               }
-       }
-
        PQclear(res);
        destroyPQExpBuffer(query);
 
@@ -1715,6 +2001,7 @@ getTypes(int *numTypes)
        int                     i;
        PQExpBuffer query = createPQExpBuffer();
        TypeInfo   *tinfo;
+       ShellTypeInfo *stinfo;
        int                     i_tableoid;
        int                     i_oid;
        int                     i_typname;
@@ -1804,9 +2091,6 @@ 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));
@@ -1815,12 +2099,11 @@ getTypes(int *numTypes)
                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].typinput = atooid(PQgetvalue(res, i, i_typinput));
-               typoutput = atooid(PQgetvalue(res, i, i_typoutput));
                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
@@ -1828,7 +2111,8 @@ getTypes(int *numTypes)
                 * 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 != 'c')
+               if (OidIsValid(tinfo[i].typrelid) &&
+                       tinfo[i].typrelkind != RELKIND_COMPOSITE_TYPE)
                        tinfo[i].dobj.objType = DO_TABLE_TYPE;
 
                /*
@@ -1845,28 +2129,86 @@ 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, or
-                * typanalyze 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 (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",
@@ -1969,6 +2311,9 @@ getOperators(int *numOprs)
                oprinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
                oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));
 
+               /* 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].dobj.name);
@@ -2047,6 +2392,9 @@ getConversions(int *numConversions)
                convinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_connamespace)),
                                                                                                 convinfo[i].dobj.catId.oid);
                convinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(convinfo[i].dobj));
        }
 
        PQclear(res);
@@ -2135,6 +2483,9 @@ getOpclasses(int *numOpclasses)
                                                                                                  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].rolname) == 0)
@@ -2169,7 +2520,8 @@ getAggregates(int *numAggs)
        int                     i_oid;
        int                     i_aggname;
        int                     i_aggnamespace;
-       int                     i_aggbasetype;
+       int                     i_pronargs;
+       int                     i_proargtypes;
        int                     i_rolname;
        int                     i_aggacl;
 
@@ -2178,11 +2530,25 @@ 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, "
-                                                 "proargtypes[0] as aggbasetype, "
+                                                 "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, "
+                                                 "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 "
@@ -2195,7 +2561,8 @@ getAggregates(int *numAggs)
        {
                appendPQExpBuffer(query, "SELECT tableoid, oid, aggname, "
                                                  "0::oid as aggnamespace, "
-                                                 "aggbasetype, "
+                                                 "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END as pronargs, "
+                                                 "aggbasetype as proargtypes, "
                                                  "(%s aggowner) as rolname, "
                                                  "'{=X}' as aggacl "
                                                  "FROM pg_aggregate "
@@ -2209,7 +2576,8 @@ getAggregates(int *numAggs)
                                                  "(SELECT oid FROM pg_class WHERE relname = 'pg_aggregate') AS tableoid, "
                                                  "oid, aggname, "
                                                  "0::oid as aggnamespace, "
-                                                 "aggbasetype, "
+                                                 "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END as pronargs, "
+                                                 "aggbasetype as proargtypes, "
                                                  "(%s aggowner) as rolname, "
                                                  "'{=X}' as aggacl "
                                                  "FROM pg_aggregate "
@@ -2230,7 +2598,8 @@ getAggregates(int *numAggs)
        i_oid = PQfnumber(res, "oid");
        i_aggname = PQfnumber(res, "aggname");
        i_aggnamespace = PQfnumber(res, "aggnamespace");
-       i_aggbasetype = PQfnumber(res, "aggbasetype");
+       i_pronargs = PQfnumber(res, "pronargs");
+       i_proargtypes = PQfnumber(res, "proargtypes");
        i_rolname = PQfnumber(res, "rolname");
        i_aggacl = PQfnumber(res, "aggacl");
 
@@ -2248,13 +2617,24 @@ getAggregates(int *numAggs)
                        write_msg(NULL, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n",
                                          agginfo[i].aggfn.dobj.name);
                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.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);
@@ -2383,6 +2763,9 @@ getFuncs(int *numFuncs)
                                                  finfo[i].argtypes, finfo[i].nargs);
                }
 
+               /* 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",
@@ -2428,6 +2811,7 @@ getTables(int *numTables)
        int                     i_owning_tab;
        int                     i_owning_col;
        int                     i_reltablespace;
+       int                     i_reloptions;
 
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
@@ -2449,14 +2833,14 @@ getTables(int *numTables)
         * 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.
+        * we cannot correctly identify inherited columns, owned sequences, etc.
         */
 
-       if (g_fout->remoteVersion >= 80000)
+       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, "
@@ -2466,7 +2850,37 @@ getTables(int *numTables)
                                                  "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 "
+                                                 "(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.objsubid = 0 and "
+                                                 "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 "
@@ -2484,7 +2898,7 @@ getTables(int *numTables)
        {
                /*
                 * Left join to pick up dependency info linking sequences to their
-                * serial column, if any
+                * owning column, if any
                 */
                appendPQExpBuffer(query,
                                                  "SELECT c.tableoid, c.oid, relname, "
@@ -2494,7 +2908,8 @@ getTables(int *numTables)
                                                  "relhasindex, relhasrules, relhasoids, "
                                                  "d.refobjid as owning_tab, "
                                                  "d.refobjsubid as owning_col, "
-                                                 "NULL as reltablespace "
+                                                 "NULL as reltablespace, "
+                                                 "NULL as reloptions "
                                                  "from pg_class c "
                                                  "left join pg_depend d on "
                                                  "(c.relkind = '%c' and "
@@ -2518,7 +2933,8 @@ getTables(int *numTables)
                                                  "relhasindex, relhasrules, relhasoids, "
                                                  "NULL::oid as owning_tab, "
                                                  "NULL::int4 as owning_col, "
-                                                 "NULL as reltablespace "
+                                                 "NULL as reltablespace, "
+                                                 "NULL as reloptions "
                                                  "from pg_class "
                                                  "where relkind in ('%c', '%c', '%c') "
                                                  "order by oid",
@@ -2537,7 +2953,8 @@ getTables(int *numTables)
                                                  "'t'::bool as relhasoids, "
                                                  "NULL::oid as owning_tab, "
                                                  "NULL::int4 as owning_col, "
-                                                 "NULL as reltablespace "
+                                                 "NULL as reltablespace, "
+                                                 "NULL as reloptions "
                                                  "from pg_class "
                                                  "where relkind in ('%c', '%c', '%c') "
                                                  "order by oid",
@@ -2566,7 +2983,8 @@ getTables(int *numTables)
                                                  "'t'::bool as relhasoids, "
                                                  "NULL::oid as owning_tab, "
                                                  "NULL::int4 as owning_col, "
-                                                 "NULL as reltablespace "
+                                                 "NULL as reltablespace, "
+                                                 "NULL as reloptions "
                                                  "from pg_class c "
                                                  "where relkind in ('%c', '%c') "
                                                  "order by oid",
@@ -2608,6 +3026,7 @@ getTables(int *numTables)
        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++)
        {
@@ -2637,21 +3056,18 @@ getTables(int *numTables)
                        tblinfo[i].owning_col = atoi(PQgetvalue(res, i, i_owning_col));
                }
                tblinfo[i].reltablespace = strdup(PQgetvalue(res, i, i_reltablespace));
+               tblinfo[i].reloptions = strdup(PQgetvalue(res, i, i_reloptions));
 
                /* other fields were zeroed above */
 
                /*
-                * Decide whether we want to dump this table.  Sequences owned by
-                * serial columns are never dumpable on their own; we will transpose
-                * their owning table's dump flag to them below.
+                * Decide whether we want to dump this table.
                 */
                if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
-                       tblinfo[i].dump = false;
-               else if (OidIsValid(tblinfo[i].owning_tab))
-                       tblinfo[i].dump = false;
+                       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
@@ -2664,7 +3080,7 @@ getTables(int *numTables)
                 * 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,
@@ -2680,27 +3096,37 @@ getTables(int *numTables)
                                          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].dobj.name, selectTableName) == 0)
-                               break;
+               TableInfo  *seqinfo = &tblinfo[i];
+               int             j;
+
+               if (!OidIsValid(seqinfo->owning_tab))
+                       continue;                       /* not an owned sequence */
+               if (seqinfo->dobj.dump)
+                       continue;                       /* no need to search */
 
-               /* Didn't find a match */
-               if (i == ntups)
+               /* 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);
@@ -2786,7 +3212,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                i_conname,
                                i_contableoid,
                                i_conoid,
-                               i_tablespace;
+                               i_tablespace,
+                               i_options;
        int                     ntups;
 
        for (i = 0; i < numTables; i++)
@@ -2797,7 +3224,8 @@ 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)
@@ -2814,7 +3242,33 @@ getIndexes(TableInfo tblinfo[], int numTables)
                 * assume an index won't have more than one internal dependency.
                 */
                resetPQExpBuffer(query);
-               if (g_fout->remoteVersion >= 80000)
+               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, "
@@ -2825,7 +3279,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                                          "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 "
+                                                         "(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 "
@@ -2850,7 +3305,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                                          "c.contype, c.conname, "
                                                          "c.tableoid as contableoid, "
                                                          "c.oid as conoid, "
-                                                         "NULL as tablespace "
+                                                         "NULL as tablespace, "
+                                                         "null as options "
                                                          "FROM pg_catalog.pg_index i "
                                          "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
                                                          "LEFT JOIN pg_catalog.pg_depend d "
@@ -2877,7 +3333,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                                          "t.relname as conname, "
                                                          "0::oid as contableoid, "
                                                          "t.oid as conoid, "
-                                                         "NULL as tablespace "
+                                                         "NULL as tablespace, "
+                                                         "null as options "
                                                          "FROM pg_index i, pg_class t "
                                                          "WHERE t.oid = i.indexrelid "
                                                          "AND i.indrelid = '%u'::oid "
@@ -2899,7 +3356,8 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                                          "t.relname as conname, "
                                                          "0::oid as contableoid, "
                                                          "t.oid as conoid, "
-                                                         "NULL as tablespace "
+                                                         "NULL as tablespace, "
+                                                         "null as options "
                                                          "FROM pg_index i, pg_class t "
                                                          "WHERE t.oid = i.indexrelid "
                                                          "AND i.indrelid = '%u'::oid "
@@ -2924,6 +3382,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
                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));
@@ -2942,6 +3401,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
                        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
@@ -3033,7 +3493,7 @@ 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)
@@ -3255,6 +3715,7 @@ getRules(int *numRules)
                        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)
@@ -3326,7 +3787,7 @@ 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)
@@ -3726,8 +4187,7 @@ void
 getTableAttrs(TableInfo *tblinfo, int numTables)
 {
        int                     i,
-                               j,
-                               k;
+                               j;
        PQExpBuffer q = createPQExpBuffer();
        int                     i_attnum;
        int                     i_attname;
@@ -3846,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));
@@ -3870,7 +4329,6 @@ 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 */
                        if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
@@ -3952,6 +4410,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                                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
@@ -4082,6 +4542,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                                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
@@ -4099,44 +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);
@@ -4192,7 +4616,7 @@ dumpComment(Archive *fout, const char *target,
                PQExpBuffer query = createPQExpBuffer();
 
                appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
-               appendStringLiteral(query, comments->descr, false);
+               appendStringLiteralAH(query, comments->descr, fout);
                appendPQExpBuffer(query, ";\n");
 
                ArchiveEntry(fout, nilCatalogId, createDumpId(),
@@ -4250,7 +4674,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
 
                        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(),
@@ -4272,7 +4696,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
 
                        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(),
@@ -4478,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;
@@ -4554,8 +4981,8 @@ 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 */
@@ -4603,22 +5030,8 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 static void
 dumpType(Archive *fout, TypeInfo *tinfo)
 {
-       /* Dump only types in dumpable namespaces */
-       if (!tinfo->dobj.namespace->dump || dataOnly)
-               return;
-
-       /* skip complex types, except for standalone composite types */
-       /* (note: this test should now be unnecessary) */
-       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->dobj.name[0] == '_') &&
-               OidIsValid(tinfo->typelem))
+       /* Skip if not to be dumped */
+       if (!tinfo->dobj.dump || dataOnly)
                return;
 
        /* Dump out in proper style */
@@ -4654,10 +5067,11 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        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->dobj.namespace->dobj.name);
@@ -4673,8 +5087,8 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                                                  "typreceive::pg_catalog.oid as typreceiveoid, "
                                                  "typsend::pg_catalog.oid as typsendoid, "
                                                  "typanalyze::pg_catalog.oid as typanalyzeoid, "
-                                                 "typdelim, typdefault, typbyval, typalign, "
-                                                 "typstorage "
+                                                 "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);
@@ -4689,8 +5103,8 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                                                  "typreceive::pg_catalog.oid as typreceiveoid, "
                                                  "typsend::pg_catalog.oid as typsendoid, "
                                                  "0 as typanalyzeoid, "
-                                                 "typdelim, typdefault, typbyval, typalign, "
-                                                 "typstorage "
+                                                 "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);
@@ -4705,13 +5119,13 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                                                  "typoutput::pg_catalog.oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
                                                  "0 as typanalyzeoid, "
-                                                 "typdelim, typdefault, typbyval, typalign, "
-                                                 "typstorage "
+                                                 "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,
@@ -4725,8 +5139,28 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                                                  "typoutput::oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
                                                  "0 as typanalyzeoid, "
-                                                 "typdelim, typdefault, typbyval, typalign, "
-                                                 "typstorage "
+                                                 "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, "
+                                                 "0 as typanalyzeoid, "
+                                                 "typdelim, typbyval, typalign, typstorage, "
+                                                 "NULL as typdefaultbin, NULL as typdefault "
                                                  "FROM pg_type "
                                                  "WHERE oid = '%u'::oid",
                                                  tinfo->dobj.catId.oid);
@@ -4741,8 +5175,9 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                                                  "typoutput::oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
                                                  "0 as typanalyzeoid, "
-                                                 "typdelim, typdefault, typbyval, typalign, "
-                                                 "'p'::char as typstorage "
+                                                 "typdelim, typbyval, typalign, "
+                                                 "'p'::char as typstorage, "
+                                                 "NULL as typdefaultbin, NULL as typdefault "
                                                  "FROM pg_type "
                                                  "WHERE oid = '%u'::oid",
                                                  tinfo->dobj.catId.oid);
@@ -4772,16 +5207,24 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        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->dobj.namespace->dobj.name));
@@ -4818,7 +5261,10 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        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)
@@ -4835,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)
@@ -4900,6 +5346,7 @@ 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->dobj.namespace->dobj.name);
@@ -4908,7 +5355,7 @@ dumpDomain(Archive *fout, TypeInfo *tinfo)
        /* 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.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);
@@ -4927,10 +5374,15 @@ 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",
@@ -4940,8 +5392,14 @@ dumpDomain(Archive *fout, TypeInfo *tinfo)
        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);
 
@@ -5084,6 +5542,47 @@ 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
@@ -5099,7 +5598,7 @@ dumpCompositeType(Archive *fout, TypeInfo *tinfo)
 static bool
 shouldDumpProcLangs(void)
 {
-       if (selectTableName != NULL || selectSchemaName != NULL)
+       if (matchingTables != NULL || matchingSchemas != NULL)
                return false;
        /* And they're schema not data */
        if (dataOnly)
@@ -5135,13 +5634,13 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
         */
 
        funcInfo = findFuncByOid(plang->lanplcallfoid);
-       if (funcInfo != NULL && !funcInfo->dobj.namespace->dump)
+       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 && !validatorInfo->dobj.namespace->dump)
+               if (validatorInfo != NULL && !validatorInfo->dobj.dump)
                        validatorInfo = NULL;
        }
 
@@ -5356,8 +5855,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        char      **argmodes = NULL;
        char      **argnames = NULL;
 
-       /* Dump only funcs in dumpable namespaces */
-       if (!finfo->dobj.namespace->dump || dataOnly)
+       /* Skip if not to be dumped */
+       if (!finfo->dobj.dump || dataOnly)
                return;
 
        query = createPQExpBuffer();
@@ -5467,7 +5966,7 @@ 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, ", ");
@@ -5476,10 +5975,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                         * where we have bin, use dollar quoting if allowed and src
                         * contains quote or backslash; else use regular quoting.
                         */
-                       if (disable_dollar_quoting)
-                               appendStringLiteral(asPart, prosrc, false);
+                       if (disable_dollar_quoting ||
+                               (strchr(prosrc, '\'') == NULL && strchr(prosrc, '\\') == NULL))
+                               appendStringLiteralAH(asPart, prosrc, fout);
                        else
-                               appendStringLiteralDQOpt(asPart, prosrc, false, NULL);
+                               appendStringLiteralDQ(asPart, prosrc, NULL);
                }
        }
        else
@@ -5489,7 +5989,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                        appendPQExpBuffer(asPart, "AS ");
                        /* with no bin, dollar quote src unconditionally if allowed */
                        if (disable_dollar_quoting)
-                               appendStringLiteral(asPart, prosrc, false);
+                               appendStringLiteralAH(asPart, prosrc, fout);
                        else
                                appendStringLiteralDQ(asPart, prosrc, NULL);
                }
@@ -5649,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);
@@ -5663,31 +6162,31 @@ dumpCast(Archive *fout, CastInfo *cast)
         * Skip this cast if all objects are from pg_
         */
        if ((funcInfo == NULL ||
-                strncmp(funcInfo->dobj.namespace->dobj.name, "pg_", 3) == 0) &&
+               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->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
-               !funcInfo->dobj.namespace->dump)
+               !funcInfo->dobj.dump)
                return;
 
        /*
-        * Same for the Source type
+        * Same for the source type
         */
        if (strncmp(sourceInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
-               !sourceInfo->dobj.namespace->dump)
+               !sourceInfo->dobj.dump)
                return;
 
        /*
         * and the target type.
         */
        if (strncmp(targetInfo->dobj.namespace->dobj.name, "pg_", 3) != 0 &&
-               !targetInfo->dobj.namespace->dump)
+               !targetInfo->dobj.dump)
                return;
 
        /* Make sure we are in proper schema (needed for getFormattedTypeName) */
@@ -5792,8 +6291,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        char       *oprltcmpop;
        char       *oprgtcmpop;
 
-       /* Dump only operators in dumpable namespaces */
-       if (!oprinfo->dobj.namespace->dump || dataOnly)
+       /* Skip if not to be dumped */
+       if (!oprinfo->dobj.dump || dataOnly)
                return;
 
        /*
@@ -6052,9 +6551,10 @@ 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)
@@ -6068,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));
@@ -6130,8 +6641,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        bool            needComma;
        int                     i;
 
-       /* Dump only opclasses in dumpable namespaces */
-       if (!opcinfo->dobj.namespace->dump || dataOnly)
+       /* Skip if not to be dumped */
+       if (!opcinfo->dobj.dump || dataOnly)
                return;
 
        /*
@@ -6338,8 +6849,8 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        const char *conproc;
        bool            condefault;
 
-       /* Dump only conversions in dumpable namespaces */
-       if (!convinfo->dobj.namespace->dump || dataOnly)
+       /* Skip if not to be dumped */
+       if (!convinfo->dobj.dump || dataOnly)
                return;
 
        query = createPQExpBuffer();
@@ -6394,9 +6905,9 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
                                          (condefault) ? "DEFAULT " : "",
                                          fmtId(convinfo->dobj.name));
-       appendStringLiteral(q, conforencoding, true);
+       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);
 
@@ -6434,6 +6945,7 @@ static char *
 format_aggregate_signature(AggInfo *agginfo, Archive *fout, bool honor_quotes)
 {
        PQExpBufferData buf;
+       int                     j;
 
        initPQExpBuffer(&buf);
        if (honor_quotes)
@@ -6442,23 +6954,24 @@ format_aggregate_signature(AggInfo *agginfo, Archive *fout, bool honor_quotes)
        else
                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;
 }
 
@@ -6482,8 +6995,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        int                     i_aggsortop;
        int                     i_aggtranstype;
        int                     i_agginitval;
-       int                     i_anybasetype;
-       int                     i_fmtbasetype;
        int                     i_convertok;
        const char *aggtransfn;
        const char *aggfinalfn;
@@ -6492,8 +7003,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        const char *agginitval;
        bool            convertok;
 
-       /* Dump only aggs in dumpable namespaces */
-       if (!agginfo->aggfn.dobj.namespace->dump || dataOnly)
+       /* Skip if not to be dumped */
+       if (!agginfo->aggfn.dobj.dump || dataOnly)
                return;
 
        query = createPQExpBuffer();
@@ -6511,8 +7022,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "aggfinalfn, aggtranstype::pg_catalog.regtype, "
                                                  "aggsortop::pg_catalog.regoperator, "
                                                  "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 "
                                                  "where a.aggfnoid = p.oid "
@@ -6525,8 +7034,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "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 "
                                                  "where a.aggfnoid = p.oid "
@@ -6539,9 +7046,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "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",
@@ -6554,8 +7058,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "(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",
@@ -6579,8 +7081,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        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);
@@ -6588,10 +7088,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        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);
@@ -6607,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",
@@ -6637,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)
@@ -6661,8 +7150,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                          aggsig);
 
        appendPQExpBuffer(q, "CREATE AGGREGATE %s (\n%s\n);\n",
-                                         fmtId(agginfo->aggfn.dobj.name),
-                                         details->data);
+                                         aggsig, details->data);
 
        ArchiveEntry(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
                                 aggsig_tag,
@@ -6683,7 +7171,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        /*
         * 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.
+        * syntax for zero-argument aggregates.
         */
        free(aggsig);
        free(aggsig_tag);
@@ -6765,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);
@@ -6774,7 +7262,8 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
 
                /* Handle the ACL here */
                namecopy = strdup(fmtId(tbinfo->dobj.name));
-               dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE",
+               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);
@@ -6823,7 +7312,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                {
                        appendPQExpBuffer(query, "SELECT definition as viewdef "
                                                          " from pg_views where viewname = ");
-                       appendStringLiteral(query, tbinfo->dobj.name, true);
+                       appendStringLiteralAH(query, tbinfo->dobj.name, fout);
                        appendPQExpBuffer(query, ";");
                }
 
@@ -6899,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
                                {
@@ -6919,24 +7400,17 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                }
 
                                /*
-                                * Default value --- suppress if inherited, serial, or to be
+                                * 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");
@@ -6985,6 +7459,9 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                        appendPQExpBuffer(q, ")");
                }
 
+               if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
+                       appendPQExpBuffer(q, "\nWITH (%s)", tbinfo->reloptions);
+
                appendPQExpBuffer(q, ";\n");
 
                /* Loop dumping statistics and storage statements */
@@ -7087,11 +7564,11 @@ 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();
@@ -7240,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();
@@ -7283,7 +7759,12 @@ 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)
@@ -7386,8 +7867,8 @@ 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->dobj.namespace->dump)
+               /* Ignore if not to be dumped separately */
+               if (coninfo->separate)
                {
                        appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
                                                          fmtId(tinfo->dobj.name));
@@ -7473,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);
@@ -7600,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);
 
@@ -7655,32 +8135,57 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
                                         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)
        {
-               TableInfo  *owning_tab;
-
                resetPQExpBuffer(query);
                appendPQExpBuffer(query, "SELECT pg_catalog.setval(");
-
-               /*
-                * If this is a SERIAL sequence, then use the pg_get_serial_sequence
-                * function to avoid hard-coding the sequence name.  Note that this
-                * implicitly assumes that the sequence and its owning table are in
-                * the same schema, because we don't schema-qualify the reference.
-                */
-               if (OidIsValid(tbinfo->owning_tab) &&
-                       (owning_tab = findTableByOid(tbinfo->owning_tab)) != NULL)
-               {
-                       appendPQExpBuffer(query, "pg_catalog.pg_get_serial_sequence(");
-                       appendStringLiteral(query, fmtId(owning_tab->dobj.name), true);
-                       appendPQExpBuffer(query, ", ");
-                       appendStringLiteral(query, owning_tab->attnames[tbinfo->owning_col - 1], true);
-                       appendPQExpBuffer(query, ")");
-               }
-               else
-                       appendStringLiteral(query, fmtId(tbinfo->dobj.name), true);
+               appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout);
                appendPQExpBuffer(query, ", %s, %s);\n",
                                                  last, (called ? "true" : "false"));
 
@@ -7694,16 +8199,6 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
                                         NULL, NULL);
        }
 
-       if (!dataOnly)
-       {
-               /* 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);
-       }
-
        PQclear(res);
 
        destroyPQExpBuffer(query);
@@ -7813,8 +8308,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
        p = tginfo->tgargs;
        for (findx = 0; findx < tginfo->tgnargs; findx++)
        {
-               const char *s = p,
-                                  *s2 = p;
+               const char *s = p;
 
                /* Set 'p' to end of arg string. marked by '\000' */
                for (;;)
@@ -7839,18 +8333,17 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
                }
                p--;
 
-               while (s2 < p)
-                       if (*s2++ == '\\')
-                       {
-                               appendPQExpBufferChar(query, ESCAPE_STRING_SYNTAX);
-                               break;
-                       }
-
                appendPQExpBufferChar(query, '\'');
                while (s < p)
                {
-                       if (*s == '\'')         /* bytea already doubles backslashes */
+                       if (*s == '\'')
                                appendPQExpBufferChar(query, '\'');
+                       /*
+                        *      bytea unconditionally doubles backslashes, so we suppress
+                        *      the doubling for standard_conforming_strings.
+                        */
+                       if (fout->std_strings && *s == '\\' && s[1] == '\\')
+                               s++;
                        appendPQExpBufferChar(query, *s++);
                }
                appendPQExpBufferChar(query, '\'');
@@ -7904,10 +8397,8 @@ 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;
 
        /*