OSDN Git Service

Add a "provariadic" column to pg_proc to eliminate the remarkably expensive
[pg-rex/syncrep.git] / src / bin / pg_dump / pg_dump.c
index 3dffc9b..c4602fd 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-2008, 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
  *     by PostgreSQL
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.427 2006/01/21 02:16:20 momjian Exp $
+ *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.495 2008/07/16 16:55:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
-/*
- * Although this is not a backend module, we must include postgres.h anyway
- * so that we can include a bunch of backend include files.  pg_dump has
- * never pretended to be very independent of the backend anyhow ...
- */
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include <unistd.h>
 #include <ctype.h>
 #include <termios.h>
 #endif
 
-#ifndef HAVE_STRDUP
-#include "strdup.h"
-#endif
-
 #include "getopt_long.h"
 
 #ifndef HAVE_INT_OPTRESET
@@ -44,19 +35,13 @@ int                 optreset;
 #endif
 
 #include "access/attnum.h"
-#include "access/htup.h"
+#include "access/sysattr.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 "pg_dump.h"
-#include "pg_backup.h"
 #include "pg_backup_archiver.h"
 #include "dumputils.h"
 
@@ -93,8 +78,24 @@ 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 */
+/*
+ * Object inclusion/exclusion lists
+ *
+ * The string lists record the patterns given by command-line switches,
+ * which we then convert to lists of OIDs of matching objects.
+ */
+static SimpleStringList schema_include_patterns = {NULL, NULL};
+static SimpleOidList schema_include_oids = {NULL, NULL};
+static SimpleStringList schema_exclude_patterns = {NULL, NULL};
+static SimpleOidList schema_exclude_oids = {NULL, NULL};
+
+static SimpleStringList table_include_patterns = {NULL, NULL};
+static SimpleOidList table_include_oids = {NULL, NULL};
+static SimpleStringList table_exclude_patterns = {NULL, NULL};
+static SimpleOidList table_exclude_oids = {NULL, NULL};
+
+/* default, if no "inclusion" switches appear, is to dump everything */
+static bool include_everything = true;
 
 char           g_opaque_type[10];      /* name for the opaque type */
 
@@ -113,8 +114,13 @@ static int disable_dollar_quoting = 0;
 
 
 static void help(const char *progname);
+static void expand_schema_name_patterns(SimpleStringList *patterns,
+                                                       SimpleOidList *oids);
+static void expand_table_name_patterns(SimpleStringList *patterns,
+                                                  SimpleOidList *oids);
 static NamespaceInfo *findNamespace(Oid nsoid, Oid objoid);
 static void dumpTableData(Archive *fout, TableDataInfo *tdinfo);
+static void guessConstraintInheritance(TableInfo *tblinfo, int numTables);
 static void dumpComment(Archive *fout, const char *target,
                        const char *namespace, const char *owner,
                        CatalogId catalogId, int subid, DumpId dumpId);
@@ -125,13 +131,16 @@ static void dumpDumpableObject(Archive *fout, DumpableObject *dobj);
 static void dumpNamespace(Archive *fout, NamespaceInfo *nspinfo);
 static void dumpType(Archive *fout, TypeInfo *tinfo);
 static void dumpBaseType(Archive *fout, TypeInfo *tinfo);
+static void dumpEnumType(Archive *fout, TypeInfo *tinfo);
 static void dumpDomain(Archive *fout, TypeInfo *tinfo);
 static void dumpCompositeType(Archive *fout, TypeInfo *tinfo);
+static void dumpShellType(Archive *fout, ShellTypeInfo *stinfo);
 static void dumpProcLang(Archive *fout, ProcLangInfo *plang);
 static void dumpFunc(Archive *fout, FuncInfo *finfo);
 static void dumpCast(Archive *fout, CastInfo *cast);
 static void dumpOpr(Archive *fout, OprInfo *oprinfo);
 static void dumpOpclass(Archive *fout, OpclassInfo *opcinfo);
+static void dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo);
 static void dumpConversion(Archive *fout, ConvInfo *convinfo);
 static void dumpRule(Archive *fout, RuleInfo *rinfo);
 static void dumpAgg(Archive *fout, AggInfo *agginfo);
@@ -143,6 +152,10 @@ static void dumpSequence(Archive *fout, TableInfo *tbinfo);
 static void dumpIndex(Archive *fout, IndxInfo *indxinfo);
 static void dumpConstraint(Archive *fout, ConstraintInfo *coninfo);
 static void dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo);
+static void dumpTSParser(Archive *fout, TSParserInfo *prsinfo);
+static void dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo);
+static void dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo);
+static void dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo);
 
 static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
                const char *type, const char *name,
@@ -159,6 +172,7 @@ static char *format_function_arguments(FuncInfo *finfo, int nallargs,
 static char *format_function_signature(FuncInfo *finfo, bool honor_quotes);
 static const char *convertRegProcReference(const char *proc);
 static const char *convertOperatorReference(const char *opr);
+static const char *convertTSFunction(Oid funcOid);
 static Oid     findLastBuiltinOid_V71(const char *);
 static Oid     findLastBuiltinOid_V70(void);
 static void selectSourceSchema(const char *schemaName);
@@ -170,6 +184,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);
@@ -188,6 +203,7 @@ 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;
@@ -196,18 +212,20 @@ main(int argc, char **argv)
        int                     i;
        bool            force_password = false;
        int                     compressLevel = -1;
-       bool            ignore_version = false;
        int                     plainText = 0;
        int                     outputClean = 0;
        int                     outputCreate = 0;
-       bool            outputBlobs = true;
+       bool            outputBlobs = false;
        int                     outputNoOwner = 0;
-       static int      use_setsessauth = 0;
-       static int      disable_triggers = 0;
        char       *outputSuperuser = NULL;
-
+       int                     my_version;
+       int                     optindex;
        RestoreOptions *ropt;
 
+       static int      disable_triggers = 0;
+       static int  outputNoTablespaces = 0;
+       static int      use_setsessauth = 0;
+
        static struct option long_options[] = {
                {"data-only", no_argument, NULL, 'a'},
                {"blobs", no_argument, NULL, 'b'},
@@ -225,9 +243,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'},
@@ -239,16 +259,15 @@ main(int argc, char **argv)
                {"version", no_argument, NULL, 'V'},
 
                /*
-                * the following options don't have an equivalent short option letter,
-                * but are available as '-X long-name'
+                * the following options don't have an equivalent short option letter
                 */
                {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
                {"disable-triggers", no_argument, &disable_triggers, 1},
+               {"no-tablespaces", no_argument, &outputNoTablespaces, 1},
                {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
 
                {NULL, 0, NULL, 0}
        };
-       int                     optindex;
 
        set_pglocale_pgservice(argv[0], "pg_dump");
 
@@ -280,7 +299,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:U:vWxX:Z:",
                                                        long_options, &optindex)) != -1)
        {
                switch (c)
@@ -290,7 +309,7 @@ main(int argc, char **argv)
                                break;
 
                        case 'b':                       /* Dump blobs */
-                               /* this is now default, so just ignore the switch */
+                               outputBlobs = true;
                                break;
 
                        case 'c':                       /* clean (i.e., drop) schema prior to create */
@@ -327,12 +346,17 @@ main(int argc, char **argv)
                                pghost = optarg;
                                break;
 
-                       case 'i':                       /* ignore database version mismatch */
-                               ignore_version = true;
+                       case 'i':
+                               /* ignored, deprecated option */
+                               break;
+
+                       case 'n':                       /* include schema(s) */
+                               simple_string_list_append(&schema_include_patterns, optarg);
+                               include_everything = false;
                                break;
 
-                       case 'n':                       /* Dump data for this schema only */
-                               selectSchemaName = strdup(optarg);
+                       case 'N':                       /* exclude schema(s) */
+                               simple_string_list_append(&schema_exclude_patterns, optarg);
                                break;
 
                        case 'o':                       /* Dump oids */
@@ -353,20 +377,19 @@ main(int argc, char **argv)
 
                        case 's':                       /* dump schema only */
                                schemaOnly = true;
-                               outputBlobs = false;
                                break;
 
                        case 'S':                       /* Username for superuser in plain text output */
                                outputSuperuser = strdup(optarg);
                                break;
 
-                       case 't':                       /* Dump data for this table only */
-                               selectTableName = strdup(optarg);
+                       case 't':                       /* include table(s) */
+                               simple_string_list_append(&table_include_patterns, optarg);
+                               include_everything = false;
                                break;
 
-                       case 'u':
-                               force_password = true;
-                               username = simple_prompt("User name: ", 100, true);
+                       case 'T':                       /* exclude table(s) */
+                               simple_string_list_append(&table_exclude_patterns, optarg);
                                break;
 
                        case 'U':
@@ -385,18 +408,14 @@ main(int argc, char **argv)
                                aclsSkip = true;
                                break;
 
-                               /*
-                                * Option letters were getting scarce, so I invented this new
-                                * scheme: '-X feature' turns on some feature. Compare to the
-                                * -f option in GCC.  You should also add an equivalent
-                                * GNU-style option --feature.  Features that require
-                                * arguments should use '-X feature=foo'.
-                                */
                        case 'X':
+                               /* -X is a deprecated alternative to long options */
                                if (strcmp(optarg, "disable-dollar-quoting") == 0)
                                        disable_dollar_quoting = 1;
                                else if (strcmp(optarg, "disable-triggers") == 0)
                                        disable_triggers = 1;
+                               else if (strcmp(optarg, "no-tablespaces") == 0)
+                                       outputNoTablespaces = 1;
                                else if (strcmp(optarg, "use-set-session-authorization") == 0)
                                        use_setsessauth = 1;
                                else
@@ -412,9 +431,9 @@ main(int argc, char **argv)
                        case 'Z':                       /* Compression Level */
                                compressLevel = atoi(optarg);
                                break;
-                               /* This covers the long options equivalent to -X xxx. */
 
                        case 0:
+                               /* This covers the long options equivalent to -X xxx. */
                                break;
 
                        default:
@@ -438,53 +457,51 @@ main(int argc, char **argv)
 
        if (dataOnly && schemaOnly)
        {
-               write_msg(NULL, "options \"schema only\" (-s) and \"data only\" (-a) cannot be used together\n");
+               write_msg(NULL, "options -s/--schema-only and -a/--data-only cannot be used together\n");
                exit(1);
        }
 
        if (dataOnly && outputClean)
        {
-               write_msg(NULL, "options \"clean\" (-c) and \"data only\" (-a) cannot be used together\n");
+               write_msg(NULL, "options -c/--clean and -a/--data-only cannot be used together\n");
                exit(1);
        }
 
-       if (selectTableName != NULL || selectSchemaName != NULL)
-               outputBlobs = false;
-
        if (dumpInserts == true && oids == true)
        {
-               write_msg(NULL, "INSERT (-d, -D) and OID (-o) options cannot be used together\n");
+               write_msg(NULL, "options -d/-D/--inserts/--column-inserts and -o/--oids cannot be used together\n");
                write_msg(NULL, "(The INSERT command cannot set OIDs.)\n");
                exit(1);
        }
 
        /* open the output file */
-       switch (format[0])
+       if (pg_strcasecmp(format, "a") == 0 || pg_strcasecmp(format, "append") == 0)
        {
-               case 'c':
-               case 'C':
-                       g_fout = CreateArchive(filename, archCustom, compressLevel);
-                       break;
-
-               case 'f':
-               case 'F':
-                       g_fout = CreateArchive(filename, archFiles, compressLevel);
-                       break;
-
-               case 'p':
-               case 'P':
-                       plainText = 1;
-                       g_fout = CreateArchive(filename, archNull, 0);
-                       break;
-
-               case 't':
-               case 'T':
-                       g_fout = CreateArchive(filename, archTar, compressLevel);
-                       break;
-
-               default:
-                       write_msg(NULL, "invalid output format \"%s\" specified\n", format);
-                       exit(1);
+               /* This is used by pg_dumpall, and is not documented */
+               plainText = 1;
+               g_fout = CreateArchive(filename, archNull, 0, archModeAppend);
+       }
+       else if (pg_strcasecmp(format, "c") == 0 || pg_strcasecmp(format, "custom") == 0)
+               g_fout = CreateArchive(filename, archCustom, compressLevel, archModeWrite);
+       else if (pg_strcasecmp(format, "f") == 0 || pg_strcasecmp(format, "file") == 0)
+       {
+               /*
+                * Dump files into the current directory; for demonstration only, not
+                * documented.
+                */
+               g_fout = CreateArchive(filename, archFiles, compressLevel, archModeWrite);
+       }
+       else if (pg_strcasecmp(format, "p") == 0 || pg_strcasecmp(format, "plain") == 0)
+       {
+               plainText = 1;
+               g_fout = CreateArchive(filename, archNull, 0, archModeWrite);
+       }
+       else if (pg_strcasecmp(format, "t") == 0 || pg_strcasecmp(format, "tar") == 0)
+               g_fout = CreateArchive(filename, archTar, compressLevel, archModeWrite);
+       else
+       {
+               write_msg(NULL, "invalid output format \"%s\" specified\n", format);
+               exit(1);
        }
 
        if (g_fout == NULL)
@@ -496,40 +513,76 @@ main(int argc, char **argv)
        /* Let the archiver know how noisy to be */
        g_fout->verbose = g_verbose;
 
-       g_fout->minRemoteVersion = 70000;       /* we can handle back to 7.0 */
-       g_fout->maxRemoteVersion = parse_version(PG_VERSION);
-       if (g_fout->maxRemoteVersion < 0)
+       my_version = parse_version(PG_VERSION);
+       if (my_version < 0)
        {
                write_msg(NULL, "could not parse version string \"%s\"\n", PG_VERSION);
                exit(1);
        }
 
        /*
+        * We allow the server to be back to 7.0, and up to any minor release
+        * of our own major version.  (See also version check in pg_dumpall.c.)
+        */
+       g_fout->minRemoteVersion = 70000;
+       g_fout->maxRemoteVersion = (my_version / 100) * 100 + 99;
+
+       /*
         * Open the database using the Archiver, so it knows about it. Errors mean
         * death.
         */
        g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport,
-                                                        username, force_password, ignore_version);
+                                                        username, force_password);
+
+       /* 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);
+       /*
+        * If supported, set extra_float_digits so that we can dump float data
+        * exactly (given correctly implemented float I/O code, anyway)
+        */
+       if (g_fout->remoteVersion >= 70400)
+               do_sql_command(g_conn, "SET extra_float_digits TO 2");
 
-               sprintf(cmd, "SET client_encoding='%s'", dumpencoding);
-               do_sql_command(g_conn, cmd);
-               free(cmd);
-       }
+       /*
+        * If synchronized scanning is supported, disable it, to prevent
+        * unpredictable changes in row ordering across a dump and reload.
+        */
+       if (g_fout->remoteVersion >= 80300)
+               do_sql_command(g_conn, "SET synchronize_seqscans TO off");
+
+       /*
+        * Disable timeouts if supported.
+        */
+       if (g_fout->remoteVersion >= 70300)
+               do_sql_command(g_conn, "SET statement_timeout = 0");
+         
+       /*
+        * Start serializable transaction to dump consistent data.
+        */
+       do_sql_command(g_conn, "BEGIN");
+
+       do_sql_command(g_conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
 
        /* Select the appropriate subquery to convert user IDs to names */
        if (g_fout->remoteVersion >= 80100)
@@ -539,13 +592,6 @@ main(int argc, char **argv)
        else
                username_subquery = "SELECT usename FROM pg_user WHERE usesysid =";
 
-       /*
-        * If supported, set extra_float_digits so that we can dump float data
-        * exactly (given correctly implemented float I/O code, anyway)
-        */
-       if (g_fout->remoteVersion >= 70400)
-               do_sql_command(g_conn, "SET extra_float_digits TO 2");
-
        /* Find the last built-in OID, if needed */
        if (g_fout->remoteVersion < 70300)
        {
@@ -557,11 +603,51 @@ main(int argc, char **argv)
                        write_msg(NULL, "last built-in OID is %u\n", g_last_builtin_oid);
        }
 
+       /* Expand schema selection patterns into OID lists */
+       if (schema_include_patterns.head != NULL)
+       {
+               expand_schema_name_patterns(&schema_include_patterns,
+                                                                       &schema_include_oids);
+               if (schema_include_oids.head == NULL)
+               {
+                       write_msg(NULL, "No matching schemas were found\n");
+                       exit_nicely();
+               }
+       }
+       expand_schema_name_patterns(&schema_exclude_patterns,
+                                                               &schema_exclude_oids);
+       /* non-matching exclusion patterns aren't an error */
+
+       /* Expand table selection patterns into OID lists */
+       if (table_include_patterns.head != NULL)
+       {
+               expand_table_name_patterns(&table_include_patterns,
+                                                                  &table_include_oids);
+               if (table_include_oids.head == NULL)
+               {
+                       write_msg(NULL, "No matching tables were found\n");
+                       exit_nicely();
+               }
+       }
+       expand_table_name_patterns(&table_exclude_patterns,
+                                                          &table_exclude_oids);
+       /* non-matching exclusion patterns aren't an error */
+
+       /*
+        * Dumping blobs is now default unless we saw an inclusion switch or -s
+        * ... but even if we did see one of these, -b turns it back on.
+        */
+       if (include_everything && !schemaOnly)
+               outputBlobs = true;
+
        /*
         * 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 (g_fout->remoteVersion < 80400)
+               guessConstraintInheritance(tblinfo, numTables);
 
        if (!schemaOnly)
                getTableData(tblinfo, numTables, oids);
@@ -612,11 +698,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 (include_everything && !dataOnly)
                dumpDatabase(g_fout);
 
        /* Now the rearrangeable objects. */
@@ -635,6 +722,7 @@ main(int argc, char **argv)
                ropt->superuser = outputSuperuser;
                ropt->create = outputCreate;
                ropt->noOwner = outputNoOwner;
+               ropt->noTablespace = outputNoTablespaces;
                ropt->disable_triggers = disable_triggers;
                ropt->use_setsessauth = use_setsessauth;
                ropt->dataOnly = dataOnly;
@@ -667,36 +755,36 @@ help(const char *progname)
        printf(_("\nGeneral options:\n"));
        printf(_("  -f, --file=FILENAME      output file name\n"));
        printf(_("  -F, --format=c|t|p       output file format (custom, tar, plain text)\n"));
-       printf(_("  -i, --ignore-version     proceed even when server version mismatches\n"
-                        "                           pg_dump version\n"));
        printf(_("  -v, --verbose            verbose mode\n"));
        printf(_("  -Z, --compress=0-9       compression level for compressed formats\n"));
        printf(_("  --help                   show this help, then exit\n"));
        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(_("  -X disable-dollar-quoting, --disable-dollar-quoting\n"
-                        "                           disable dollar quoting, use SQL standard quoting\n"));
-       printf(_("  -X disable-triggers, --disable-triggers\n"
-                        "                           disable triggers during data-only restore\n"));
-       printf(_("  -X use-set-session-authorization, --use-set-session-authorization\n"
-                        "                           use SESSION AUTHORIZATION commands instead of\n"
-                        "                           OWNER TO commands\n"));
+       printf(_("  -a, --data-only             dump only the data, not the schema\n"));
+       printf(_("  -b, --blobs                 include large objects in dump\n"));
+       printf(_("  -c, --clean                 clean (drop) schema prior to create\n"));
+       printf(_("  -C, --create                include commands to create database in dump\n"));
+       printf(_("  -d, --inserts               dump data as INSERT commands, rather than COPY\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(s) only\n"));
+       printf(_("  -N, --exclude-schema=SCHEMA do NOT dump the named schema(s)\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(s) only\n"));
+       printf(_("  -T, --exclude-table=TABLE   do NOT dump the named table(s)\n"));
+       printf(_("  -x, --no-privileges         do not dump privileges (grant/revoke)\n"));
+       printf(_("  --disable-dollar-quoting    disable dollar quoting, use SQL standard quoting\n"));
+       printf(_("  --disable-triggers          disable triggers during data-only restore\n"));
+       printf(_("  --no-tablespaces            do not dump tablespace assignments\n"));
+       printf(_("  --use-set-session-authorization\n"
+                        "                              use SESSION AUTHORIZATION commands instead of\n"
+       "                              ALTER OWNER commands to set ownership\n"));
 
        printf(_("\nConnection options:\n"));
        printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
@@ -719,6 +807,106 @@ exit_nicely(void)
 }
 
 /*
+ * Find the OIDs of all schemas matching the given list of patterns,
+ * and append them to the given OID list.
+ */
+static void
+expand_schema_name_patterns(SimpleStringList *patterns, SimpleOidList *oids)
+{
+       PQExpBuffer query;
+       PGresult   *res;
+       SimpleStringListCell *cell;
+       int                     i;
+
+       if (patterns->head == NULL)
+               return;                                 /* nothing to do */
+
+       if (g_fout->remoteVersion < 70300)
+       {
+               write_msg(NULL, "server version must be at least 7.3 to use schema selection switches\n");
+               exit_nicely();
+       }
+
+       query = createPQExpBuffer();
+
+       /*
+        * We use UNION ALL rather than UNION; this might sometimes result in
+        * duplicate entries in the OID list, but we don't care.
+        */
+
+       for (cell = patterns->head; cell; cell = cell->next)
+       {
+               if (cell != patterns->head)
+                       appendPQExpBuffer(query, "UNION ALL\n");
+               appendPQExpBuffer(query,
+                                                 "SELECT oid FROM pg_catalog.pg_namespace n\n");
+               processSQLNamePattern(g_conn, query, cell->val, false, false,
+                                                         NULL, "n.nspname", NULL,
+                                                         NULL);
+       }
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       for (i = 0; i < PQntuples(res); i++)
+       {
+               simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
+       }
+
+       PQclear(res);
+       destroyPQExpBuffer(query);
+}
+
+/*
+ * Find the OIDs of all tables matching the given list of patterns,
+ * and append them to the given OID list.
+ */
+static void
+expand_table_name_patterns(SimpleStringList *patterns, SimpleOidList *oids)
+{
+       PQExpBuffer query;
+       PGresult   *res;
+       SimpleStringListCell *cell;
+       int                     i;
+
+       if (patterns->head == NULL)
+               return;                                 /* nothing to do */
+
+       query = createPQExpBuffer();
+
+       /*
+        * We use UNION ALL rather than UNION; this might sometimes result in
+        * duplicate entries in the OID list, but we don't care.
+        */
+
+       for (cell = patterns->head; cell; cell = cell->next)
+       {
+               if (cell != patterns->head)
+                       appendPQExpBuffer(query, "UNION ALL\n");
+               appendPQExpBuffer(query,
+                                                 "SELECT c.oid"
+                                                 "\nFROM pg_catalog.pg_class c"
+               "\n     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
+                                                 "\nWHERE c.relkind in ('%c', '%c', '%c')\n",
+                                                 RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
+               processSQLNamePattern(g_conn, query, cell->val, true, false,
+                                                         "n.nspname", "c.relname", NULL,
+                                                         "pg_catalog.pg_table_is_visible(c.oid)");
+       }
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       for (i = 0; i < PQntuples(res); i++)
+       {
+               simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
+       }
+
+       PQclear(res);
+       destroyPQExpBuffer(query);
+}
+
+/*
  * selectDumpableNamespace: policy-setting subroutine
  *             Mark a namespace as to be dumped or not
  */
@@ -726,24 +914,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)
-       {
-               if (strcmp(nsinfo->dobj.name, selectSchemaName) == 0)
-                       nsinfo->dump = true;
-               else
-                       nsinfo->dump = false;
-       }
+       if (table_include_oids.head != NULL)
+               nsinfo->dobj.dump = false;
+       else if (schema_include_oids.head != NULL)
+               nsinfo->dobj.dump = simple_oid_list_member(&schema_include_oids,
+                                                                                                  nsinfo->dobj.catId.oid);
        else if (strncmp(nsinfo->dobj.name, "pg_", 3) == 0 ||
                         strcmp(nsinfo->dobj.name, "information_schema") == 0)
-               nsinfo->dump = false;
+               nsinfo->dobj.dump = false;
        else
-               nsinfo->dump = true;
+               nsinfo->dobj.dump = true;
+
+       /*
+        * In any case, a namespace can be excluded by an exclusion switch
+        */
+       if (nsinfo->dobj.dump &&
+               simple_oid_list_member(&schema_exclude_oids,
+                                                          nsinfo->dobj.catId.oid))
+               nsinfo->dobj.dump = false;
 }
 
 /*
@@ -754,22 +946,70 @@ static void
 selectDumpableTable(TableInfo *tbinfo)
 {
        /*
-        * Always dump if dumping parent namespace; else, if a particular
-        * tablename has been specified, dump matching table name; else, do not
-        * dump.
+        * If specific tables are being dumped, dump just those tables; else, dump
+        * according to the parent namespace's dump flag.
         */
-       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;
-       }
+       if (table_include_oids.head != NULL)
+               tbinfo->dobj.dump = simple_oid_list_member(&table_include_oids,
+                                                                                                  tbinfo->dobj.catId.oid);
+       else
+               tbinfo->dobj.dump = tbinfo->dobj.namespace->dobj.dump;
+
+       /*
+        * In any case, a table can be excluded by an exclusion switch
+        */
+       if (tbinfo->dobj.dump &&
+               simple_oid_list_member(&table_exclude_oids,
+                                                          tbinfo->dobj.catId.oid))
+               tbinfo->dobj.dump = false;
+}
+
+/*
+ * 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 auto-generated array types */
+       else if (tinfo->isArray)
+               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;
 }
 
 /*
@@ -778,8 +1018,6 @@ selectDumpableTable(TableInfo *tbinfo)
  *       to be dumped.
  */
 
-#define COPYBUFSIZ             8192
-
 static int
 dumpTableData_copy(Archive *fout, void *dcontext)
 {
@@ -791,8 +1029,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,41 +1070,27 @@ 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 (copybuf[0] == '\\' &&
-                       copybuf[1] == '.' &&
-                       copybuf[2] == '\0')
-               {
-                       copydone = true;        /* don't print this... */
-               }
-               else
+               if (ret < 0)
+                       break;                          /* done or error */
+
+               if (copybuf)
                {
-                       archputs(copybuf, fout);
-                       switch (ret)
-                       {
-                               case EOF:
-                                       copydone = true;
-                                       /* FALLTHROUGH */
-                               case 0:
-                                       archputs("\n", fout);
-                                       break;
-                               case 1:
-                                       break;
-                       }
+                       WriteData(fout, copybuf, ret);
+                       PQfreemem(copybuf);
                }
 
-               /*
+               /* ----------
                 * THROTTLE:
                 *
                 * There was considerable discussion in late July, 2000 regarding
                 * slowing down pg_dump when backing up large tables. Users with both
-                * slow & fast (muti-processor) machines experienced performance
+                * 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
@@ -875,9 +1098,14 @@ dumpTableData_copy(Archive *fout, void *dcontext)
                 * implementation was suggested. The latter failed because the loop
                 * was too tight. Finally, the following was implemented:
                 *
-                * If throttle is non-zero, then See how long since the last sleep.
-                * Work out how long to sleep (based on ratio). If sleep is more than
-                * 100ms, then sleep reset timer EndIf EndIf
+                * If throttle is non-zero, then
+                *              See how long since the last sleep.
+                *              Work out how long to sleep (based on ratio).
+                *              If sleep is more than 100ms, then
+                *                      sleep
+                *                      reset timer
+                *              EndIf
+                * EndIf
                 *
                 * where the throttle value was the number of ms to sleep per ms of
                 * work. The calculation was done in each loop.
@@ -900,20 +1128,25 @@ dumpTableData_copy(Archive *fout, void *dcontext)
                 *
                 * This will return after the interval specified in the structure tvi.
                 * Finally, call gettimeofday again to save the 'last sleep time'.
+                * ----------
                 */
        }
        archprintf(fout, "\\.\n\n\n");
 
-       ret = PQendcopy(g_conn);
-       if (ret != 0)
+       if (ret == -2)
        {
-               write_msg(NULL, "SQL command to dump the contents of table \"%s\" failed: PQendcopy() failed.\n", classname);
+               /* copy data transfer failed */
+               write_msg(NULL, "Dumping the contents of table \"%s\" failed: PQgetCopyData() failed.\n", classname);
                write_msg(NULL, "Error message from server: %s", PQerrorMessage(g_conn));
                write_msg(NULL, "The command was: %s\n", q->data);
                exit_nicely();
        }
 
+       /* Check command status and return to normal libpq state */
+       res = PQgetResult(g_conn);
+       check_sql_result(res, g_conn, q->data, PGRES_COMMAND_OK);
        PQclear(res);
+
        destroyPQExpBuffer(q);
        return 1;
 }
@@ -1044,7 +1277,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 +1362,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;
 
@@ -1153,6 +1388,81 @@ getTableData(TableInfo *tblinfo, int numTables, bool oids)
 
 
 /*
+ * guessConstraintInheritance:
+ *     In pre-8.4 databases, we can't tell for certain which constraints
+ *     are inherited.  We assume a CHECK constraint is inherited if its name
+ *     matches the name of any constraint in the parent.  Originally this code
+ *     tried to compare the expression texts, but that can fail for various
+ *     reasons --- for example, if the parent and child tables are in different
+ *     schemas, reverse-listing of function calls may produce different text
+ *     (schema-qualified or not) depending on search path.
+ *
+ *     In 8.4 and up we can rely on the conislocal field to decide which
+ *     constraints must be dumped; much safer.
+ *
+ *     This function assumes all conislocal flags were initialized to TRUE.
+ *     It clears the flag on anything that seems to be inherited.
+ */
+static void
+guessConstraintInheritance(TableInfo *tblinfo, int numTables)
+{
+       int                     i,
+                               j,
+                               k;
+
+       for (i = 0; i < numTables; i++)
+       {
+               TableInfo  *tbinfo = &(tblinfo[i]);
+               int                     numParents;
+               TableInfo **parents;
+               TableInfo  *parent;
+
+               /* Sequences and views never have parents */
+               if (tbinfo->relkind == RELKIND_SEQUENCE ||
+                       tbinfo->relkind == RELKIND_VIEW)
+                       continue;
+
+               /* Don't bother computing anything for non-target tables, either */
+               if (!tbinfo->dobj.dump)
+                       continue;
+
+               numParents = tbinfo->numParents;
+               parents = tbinfo->parents;
+
+               if (numParents == 0)
+                       continue;                       /* nothing to see here, move along */
+
+               /* scan for inherited CHECK constraints */
+               for (j = 0; j < tbinfo->ncheck; j++)
+               {
+                       ConstraintInfo *constr;
+
+                       constr = &(tbinfo->checkexprs[j]);
+
+                       for (k = 0; k < numParents; k++)
+                       {
+                               int                     l;
+
+                               parent = parents[k];
+                               for (l = 0; l < parent->ncheck; l++)
+                               {
+                                       ConstraintInfo *pconstr = &(parent->checkexprs[l]);
+
+                                       if (strcmp(pconstr->dobj.name, constr->dobj.name) == 0)
+                                       {
+                                               constr->conislocal = false;
+                                               break;
+                                       }
+                               }
+                               if (!constr->conislocal)
+                                       break;
+                       }
+               }
+       }
+}
+
+
+/*
  * dumpDatabase:
  *     dump the database definition
  */
@@ -1185,7 +1495,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 +1517,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 +1528,7 @@ dumpDatabase(Archive *AH)
                                                  "FROM pg_database "
                                                  "WHERE datname = ",
                                                  username_subquery);
-               appendStringLiteral(dbQry, datname, true);
+               appendStringLiteralAH(dbQry, datname, AH);
        }
        else
        {
@@ -1218,7 +1541,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 +1580,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 +1610,34 @@ dumpDatabase(Archive *AH)
                                 NULL);                 /* Dumper Arg */
 
        /* Dump DB comment if any */
-       resetPQExpBuffer(dbQry);
-       appendPQExpBuffer(dbQry, "DATABASE %s", fmtId(datname));
-       dumpComment(AH, dbQry->data, NULL, "",
-                               dbCatId, 0, dbDumpId);
+       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);
+                       /* Generates warning when loaded into a differently-named database.*/
+                       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 +1653,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 +1669,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 +1837,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 +1872,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 +1988,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 +2053,7 @@ getTypes(int *numTypes)
        int                     i;
        PQExpBuffer query = createPQExpBuffer();
        TypeInfo   *tinfo;
+       ShellTypeInfo *stinfo;
        int                     i_tableoid;
        int                     i_oid;
        int                     i_typname;
@@ -1727,6 +2066,7 @@ getTypes(int *numTypes)
        int                     i_typrelkind;
        int                     i_typtype;
        int                     i_typisdefined;
+       int                     i_isarray;
 
        /*
         * we include even the built-in types because those may be used as array
@@ -1734,13 +2074,35 @@ getTypes(int *numTypes)
         *
         * we filter out the built-in types when we dump out the types
         *
-        * same approach for undefined (shell) types
+        * same approach for undefined (shell) types and array types
+        *
+        * Note: as of 8.3 we can reliably detect whether a type is an
+        * auto-generated array type by checking the element type's typarray.
+        * (Before that the test is capable of generating false positives.) We
+        * still check for name beginning with '_', though, so as to avoid the
+        * cost of the subselect probe for all standard types.  This would have to
+        * be revisited if the backend ever allows renaming of array types.
         */
 
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
 
-       if (g_fout->remoteVersion >= 70300)
+       if (g_fout->remoteVersion >= 80300)
+       {
+               appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
+                                                 "typnamespace, "
+                                                 "(%s typowner) as rolname, "
+                                                 "typinput::oid as typinput, "
+                                                 "typoutput::oid as typoutput, typelem, typrelid, "
+                                                 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
+                                                 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
+                                                 "typtype, typisdefined, "
+                                                 "typname[0] = '_' AND typelem != 0 AND "
+                                                 "(SELECT typarray FROM pg_type te WHERE oid = pg_type.typelem) = oid AS isarray "
+                                                 "FROM pg_type",
+                                                 username_subquery);
+       }
+       else if (g_fout->remoteVersion >= 70300)
        {
                appendPQExpBuffer(query, "SELECT tableoid, oid, typname, "
                                                  "typnamespace, "
@@ -1749,7 +2111,8 @@ getTypes(int *numTypes)
                                                  "typoutput::oid as typoutput, typelem, typrelid, "
                                                  "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
                                                  "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
-                                                 "typtype, typisdefined "
+                                                 "typtype, typisdefined, "
+                                                 "typname[0] = '_' AND typelem != 0 AS isarray "
                                                  "FROM pg_type",
                                                  username_subquery);
        }
@@ -1762,7 +2125,8 @@ getTypes(int *numTypes)
                                                  "typoutput::oid as typoutput, typelem, typrelid, "
                                                  "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
                                                  "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
-                                                 "typtype, typisdefined "
+                                                 "typtype, typisdefined, "
+                                                 "typname[0] = '_' AND typelem != 0 AS isarray "
                                                  "FROM pg_type",
                                                  username_subquery);
        }
@@ -1777,7 +2141,8 @@ getTypes(int *numTypes)
                                                  "typoutput::oid as typoutput, typelem, typrelid, "
                                                  "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
                                                  "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
-                                                 "typtype, typisdefined "
+                                                 "typtype, typisdefined, "
+                                                 "typname[0] = '_' AND typelem != 0 AS isarray "
                                                  "FROM pg_type",
                                                  username_subquery);
        }
@@ -1801,12 +2166,10 @@ getTypes(int *numTypes)
        i_typrelkind = PQfnumber(res, "typrelkind");
        i_typtype = PQfnumber(res, "typtype");
        i_typisdefined = PQfnumber(res, "typisdefined");
+       i_isarray = PQfnumber(res, "isarray");
 
        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 +2178,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
@@ -1832,42 +2194,96 @@ getTypes(int *numTypes)
                        tinfo[i].typrelkind != RELKIND_COMPOSITE_TYPE)
                        tinfo[i].dobj.objType = DO_TABLE_TYPE;
 
-               /*
-                * check for user-defined array types, omit system generated ones
-                */
-               if (OidIsValid(tinfo[i].typelem) &&
-                       tinfo[i].dobj.name[0] != '_')
-                       tinfo[i].isArray = true;
-               else
-                       tinfo[i].isArray = false;
-
                if (strcmp(PQgetvalue(res, i, i_typisdefined), "t") == 0)
                        tinfo[i].isDefined = true;
                else
                        tinfo[i].isDefined = false;
 
+               if (strcmp(PQgetvalue(res, i, i_isarray), "t") == 0)
+                       tinfo[i].isArray = true;
+               else
+                       tinfo[i].isArray = 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 == TYPTYPE_DOMAIN)
                        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 == TYPTYPE_BASE)
+               {
+                       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",
@@ -1970,6 +2386,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);
@@ -2048,6 +2467,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);
@@ -2136,6 +2558,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)
@@ -2152,6 +2577,93 @@ getOpclasses(int *numOpclasses)
 }
 
 /*
+ * getOpfamilies:
+ *       read all opfamilies in the system catalogs and return them in the
+ * OpfamilyInfo* structure
+ *
+ *     numOpfamilies is set to the number of opfamilies read in
+ */
+OpfamilyInfo *
+getOpfamilies(int *numOpfamilies)
+{
+       PGresult   *res;
+       int                     ntups;
+       int                     i;
+       PQExpBuffer query;
+       OpfamilyInfo *opfinfo;
+       int                     i_tableoid;
+       int                     i_oid;
+       int                     i_opfname;
+       int                     i_opfnamespace;
+       int                     i_rolname;
+
+       /* Before 8.3, there is no separate concept of opfamilies */
+       if (g_fout->remoteVersion < 80300)
+       {
+               *numOpfamilies = 0;
+               return NULL;
+       }
+
+       query = createPQExpBuffer();
+
+       /*
+        * find all opfamilies, including builtin opfamilies; we filter out
+        * system-defined opfamilies at dump-out time.
+        */
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       appendPQExpBuffer(query, "SELECT tableoid, oid, opfname, "
+                                         "opfnamespace, "
+                                         "(%s opfowner) as rolname "
+                                         "FROM pg_opfamily",
+                                         username_subquery);
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       ntups = PQntuples(res);
+       *numOpfamilies = ntups;
+
+       opfinfo = (OpfamilyInfo *) malloc(ntups * sizeof(OpfamilyInfo));
+
+       i_tableoid = PQfnumber(res, "tableoid");
+       i_oid = PQfnumber(res, "oid");
+       i_opfname = PQfnumber(res, "opfname");
+       i_opfnamespace = PQfnumber(res, "opfnamespace");
+       i_rolname = PQfnumber(res, "rolname");
+
+       for (i = 0; i < ntups; i++)
+       {
+               opfinfo[i].dobj.objType = DO_OPFAMILY;
+               opfinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               opfinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&opfinfo[i].dobj);
+               opfinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_opfname));
+               opfinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_opfnamespace)),
+                                                                                                 opfinfo[i].dobj.catId.oid);
+               opfinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(opfinfo[i].dobj));
+
+               if (g_fout->remoteVersion >= 70300)
+               {
+                       if (strlen(opfinfo[i].rolname) == 0)
+                               write_msg(NULL, "WARNING: owner of operator family \"%s\" appears to be invalid\n",
+                                                 opfinfo[i].dobj.name);
+               }
+       }
+
+       PQclear(res);
+
+       destroyPQExpBuffer(query);
+
+       return opfinfo;
+}
+
+/*
  * getAggregates:
  *       read all the user-defined aggregates in the system catalogs and
  * return them in the AggInfo* structure
@@ -2170,7 +2682,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;
 
@@ -2179,11 +2692,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, "
+                                                 "pronargs, proargtypes, "
+                                                 "(%s proowner) as rolname, "
+                                                 "proacl as aggacl "
+                                                 "FROM pg_proc "
+                                                 "WHERE proisagg "
+                                                 "AND pronamespace != "
+                          "(select oid from pg_namespace where nspname = 'pg_catalog')",
+                                                 username_subquery);
+       }
+       else if (g_fout->remoteVersion >= 70300)
        {
                appendPQExpBuffer(query, "SELECT tableoid, oid, proname as aggname, "
                                                  "pronamespace as aggnamespace, "
-                                                 "proargtypes[0] as aggbasetype, "
+                                                 "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 "
@@ -2196,7 +2723,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 "
@@ -2210,7 +2738,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 "
@@ -2231,7 +2760,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");
 
@@ -2249,13 +2779,25 @@ 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);
@@ -2384,6 +2926,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",
@@ -2429,6 +2974,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");
@@ -2450,14 +2996,43 @@ 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
+                * owning column, if any (note this dependency is AUTO as of 8.2)
+                */
+               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, "
+                                                 "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
-                * serial column, if any
+                * owning column, if any
                 */
                appendPQExpBuffer(query,
                                                  "SELECT c.tableoid, c.oid, relname, "
@@ -2467,7 +3042,8 @@ 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, "
+                                                 "NULL as reloptions "
                                                  "from pg_class c "
                                                  "left join pg_depend d on "
                                                  "(c.relkind = '%c' and "
@@ -2485,7 +3061,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, "
@@ -2495,7 +3071,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 "
@@ -2519,7 +3096,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",
@@ -2538,7 +3116,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",
@@ -2567,7 +3146,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",
@@ -2609,6 +3189,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++)
        {
@@ -2638,21 +3219,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
@@ -2665,7 +3243,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,
@@ -2681,27 +3259,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);
@@ -2787,7 +3375,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++)
@@ -2798,7 +3387,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)
@@ -2815,7 +3405,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, "
@@ -2826,7 +3442,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 "
@@ -2851,7 +3468,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 "
@@ -2878,7 +3496,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 "
@@ -2900,7 +3519,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 "
@@ -2925,6 +3545,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));
@@ -2943,6 +3564,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
@@ -2979,7 +3601,7 @@ getIndexes(TableInfo tblinfo[], int numTables)
                                constrinfo[j].contype = contype;
                                constrinfo[j].condef = NULL;
                                constrinfo[j].conindex = indxinfo[j].dobj.dumpId;
-                               constrinfo[j].coninherited = false;
+                               constrinfo[j].conislocal = true;
                                constrinfo[j].separate = true;
 
                                indxinfo[j].indexconstraint = constrinfo[j].dobj.dumpId;
@@ -3034,7 +3656,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)
@@ -3080,7 +3702,7 @@ getConstraints(TableInfo tblinfo[], int numTables)
                        constrinfo[j].contype = 'f';
                        constrinfo[j].condef = strdup(PQgetvalue(res, j, i_condef));
                        constrinfo[j].conindex = 0;
-                       constrinfo[j].coninherited = false;
+                       constrinfo[j].conislocal = true;
                        constrinfo[j].separate = true;
                }
 
@@ -3163,7 +3785,7 @@ getDomainConstraints(TypeInfo *tinfo)
                constrinfo[i].contype = 'c';
                constrinfo[i].condef = strdup(PQgetvalue(res, i, i_consrc));
                constrinfo[i].conindex = 0;
-               constrinfo[i].coninherited = false;
+               constrinfo[i].conislocal = true;
                constrinfo[i].separate = false;
 
                /*
@@ -3199,15 +3821,26 @@ getRules(int *numRules)
        int                     i_ruletable;
        int                     i_ev_type;
        int                     i_is_instead;
+       int                     i_ev_enabled;
 
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
 
-       if (g_fout->remoteVersion >= 70100)
+       if (g_fout->remoteVersion >= 80300)
+       {
+               appendPQExpBuffer(query, "SELECT "
+                                                 "tableoid, oid, rulename, "
+                                                 "ev_class as ruletable, ev_type, is_instead, "
+                                                 "ev_enabled "
+                                                 "FROM pg_rewrite "
+                                                 "ORDER BY oid");
+       }
+       else if (g_fout->remoteVersion >= 70100)
        {
                appendPQExpBuffer(query, "SELECT "
                                                  "tableoid, oid, rulename, "
-                                                 "ev_class as ruletable, ev_type, is_instead "
+                                                 "ev_class as ruletable, ev_type, is_instead, "
+                                                 "'O'::char as ev_enabled "
                                                  "FROM pg_rewrite "
                                                  "ORDER BY oid");
        }
@@ -3216,7 +3849,8 @@ getRules(int *numRules)
                appendPQExpBuffer(query, "SELECT "
                                                  "(SELECT oid FROM pg_class WHERE relname = 'pg_rewrite') AS tableoid, "
                                                  "oid, rulename, "
-                                                 "ev_class as ruletable, ev_type, is_instead "
+                                                 "ev_class as ruletable, ev_type, is_instead, "
+                                                 "'O'::char as ev_enabled "
                                                  "FROM pg_rewrite "
                                                  "ORDER BY oid");
        }
@@ -3236,6 +3870,7 @@ getRules(int *numRules)
        i_ruletable = PQfnumber(res, "ruletable");
        i_ev_type = PQfnumber(res, "ev_type");
        i_is_instead = PQfnumber(res, "is_instead");
+       i_ev_enabled = PQfnumber(res, "ev_enabled");
 
        for (i = 0; i < ntups; i++)
        {
@@ -3256,8 +3891,10 @@ 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';
+               ruleinfo[i].ev_enabled = *(PQgetvalue(res, i, i_ev_enabled));
                if (ruleinfo[i].ruletable)
                {
                        /*
@@ -3327,7 +3964,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)
@@ -3340,7 +3977,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
                selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
 
                resetPQExpBuffer(query);
-               if (g_fout->remoteVersion >= 70300)
+               if (g_fout->remoteVersion >= 80300)
                {
                        /*
                         * We ignore triggers that are tied to a foreign-key constraint
@@ -3354,14 +3991,33 @@ getTriggers(TableInfo tblinfo[], int numTables)
                                         "tgconstrrelid::pg_catalog.regclass as tgconstrrelname "
                                                          "from pg_catalog.pg_trigger t "
                                                          "where tgrelid = '%u'::pg_catalog.oid "
-                                                         "and (not tgisconstraint "
-                                                         " OR NOT EXISTS"
-                                                         "  (SELECT 1 FROM pg_catalog.pg_depend d "
-                                                         "   JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) "
-                                                         "   WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))",
+                                                         "and tgconstraint = 0",
                                                          tbinfo->dobj.catId.oid);
                }
-               else if (g_fout->remoteVersion >= 70100)
+               else if (g_fout->remoteVersion >= 70300)
+               {
+                       /*
+                        * We ignore triggers that are tied to a foreign-key constraint,
+                        * but in these versions we have to grovel through pg_constraint
+                        * to find out
+                        */
+                       appendPQExpBuffer(query,
+                                                         "SELECT tgname, "
+                                                         "tgfoid::pg_catalog.regproc as tgfname, "
+                                                         "tgtype, tgnargs, tgargs, tgenabled, "
+                                                         "tgisconstraint, tgconstrname, tgdeferrable, "
+                                                         "tgconstrrelid, tginitdeferred, tableoid, oid, "
+                                        "tgconstrrelid::pg_catalog.regclass as tgconstrrelname "
+                                                         "from pg_catalog.pg_trigger t "
+                                                         "where tgrelid = '%u'::pg_catalog.oid "
+                                                         "and (not tgisconstraint "
+                                                         " OR NOT EXISTS"
+                                                         "  (SELECT 1 FROM pg_catalog.pg_depend d "
+                                                         "   JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) "
+                                                         "   WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))",
+                                                         tbinfo->dobj.catId.oid);
+               }
+               else if (g_fout->remoteVersion >= 70100)
                {
                        appendPQExpBuffer(query,
                                                          "SELECT tgname, tgfoid::regproc as tgfname, "
@@ -3436,7 +4092,7 @@ getTriggers(TableInfo tblinfo[], int numTables)
                        tginfo[j].tgnargs = atoi(PQgetvalue(res, j, i_tgnargs));
                        tginfo[j].tgargs = strdup(PQgetvalue(res, j, i_tgargs));
                        tginfo[j].tgisconstraint = *(PQgetvalue(res, j, i_tgisconstraint)) == 't';
-                       tginfo[j].tgenabled = *(PQgetvalue(res, j, i_tgenabled)) == 't';
+                       tginfo[j].tgenabled = *(PQgetvalue(res, j, i_tgenabled));
                        tginfo[j].tgdeferrable = *(PQgetvalue(res, j, i_tgdeferrable)) == 't';
                        tginfo[j].tginitdeferred = *(PQgetvalue(res, j, i_tginitdeferred)) == 't';
 
@@ -3501,7 +4157,19 @@ getProcLangs(int *numProcLangs)
        /* Make sure we are in proper schema */
        selectSourceSchema("pg_catalog");
 
-       if (g_fout->remoteVersion >= 80100)
+       if (g_fout->remoteVersion >= 80300)
+       {
+               /* pg_language has a lanowner column */
+               appendPQExpBuffer(query, "SELECT tableoid, oid, "
+                                                 "lanname, lanpltrusted, lanplcallfoid, "
+                                                 "lanvalidator,  lanacl, "
+                                                 "(%s lanowner) as lanowner "
+                                                 "FROM pg_language "
+                                                 "WHERE lanispl "
+                                                 "ORDER BY oid",
+                                                 username_subquery);
+       }
+       else if (g_fout->remoteVersion >= 80100)
        {
                /* Languages are owned by the bootstrap superuser, OID 10 */
                appendPQExpBuffer(query, "SELECT tableoid, oid, *, "
@@ -3727,8 +4395,7 @@ void
 getTableAttrs(TableInfo *tblinfo, int numTables)
 {
        int                     i,
-                               j,
-                               k;
+                               j;
        PQExpBuffer q = createPQExpBuffer();
        int                     i_attnum;
        int                     i_attname;
@@ -3847,7 +4514,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));
@@ -3871,7 +4537,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')
@@ -3953,6 +4618,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
@@ -3998,10 +4665,22 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                                                  tbinfo->dobj.name);
 
                        resetPQExpBuffer(q);
-                       if (g_fout->remoteVersion >= 70400)
+                       if (g_fout->remoteVersion >= 80400)
                        {
                                appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
-                                                       "pg_catalog.pg_get_constraintdef(oid) AS consrc "
+                                                       "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
+                                                                 "conislocal "
+                                                                 "FROM pg_catalog.pg_constraint "
+                                                                 "WHERE conrelid = '%u'::pg_catalog.oid "
+                                                                 "   AND contype = 'c' "
+                                                                 "ORDER BY conname",
+                                                                 tbinfo->dobj.catId.oid);
+                       }
+                       else if (g_fout->remoteVersion >= 70400)
+                       {
+                               appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
+                                                       "pg_catalog.pg_get_constraintdef(oid) AS consrc, "
+                                                                 "true as conislocal "
                                                                  "FROM pg_catalog.pg_constraint "
                                                                  "WHERE conrelid = '%u'::pg_catalog.oid "
                                                                  "   AND contype = 'c' "
@@ -4012,7 +4691,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                        {
                                /* no pg_get_constraintdef, must use consrc */
                                appendPQExpBuffer(q, "SELECT tableoid, oid, conname, "
-                                                                 "'CHECK (' || consrc || ')' AS consrc "
+                                                                 "'CHECK (' || consrc || ')' AS consrc, "
+                                                                 "true as conislocal "
                                                                  "FROM pg_catalog.pg_constraint "
                                                                  "WHERE conrelid = '%u'::pg_catalog.oid "
                                                                  "   AND contype = 'c' "
@@ -4024,7 +4704,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                                /* 7.2 did not have OIDs in pg_relcheck */
                                appendPQExpBuffer(q, "SELECT tableoid, 0 as oid, "
                                                                  "rcname AS conname, "
-                                                                 "'CHECK (' || rcsrc || ')' AS consrc "
+                                                                 "'CHECK (' || rcsrc || ')' AS consrc, "
+                                                                 "true as conislocal "
                                                                  "FROM pg_relcheck "
                                                                  "WHERE rcrelid = '%u'::oid "
                                                                  "ORDER BY rcname",
@@ -4034,7 +4715,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                        {
                                appendPQExpBuffer(q, "SELECT tableoid, oid, "
                                                                  "rcname AS conname, "
-                                                                 "'CHECK (' || rcsrc || ')' AS consrc "
+                                                                 "'CHECK (' || rcsrc || ')' AS consrc, "
+                                                                 "true as conislocal "
                                                                  "FROM pg_relcheck "
                                                                  "WHERE rcrelid = '%u'::oid "
                                                                  "ORDER BY rcname",
@@ -4046,7 +4728,8 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                                appendPQExpBuffer(q, "SELECT "
                                                                  "(SELECT oid FROM pg_class WHERE relname = 'pg_relcheck') AS tableoid, "
                                                                  "oid, rcname AS conname, "
-                                                                 "'CHECK (' || rcsrc || ')' AS consrc "
+                                                                 "'CHECK (' || rcsrc || ')' AS consrc, "
+                                                                 "true as conislocal "
                                                                  "FROM pg_relcheck "
                                                                  "WHERE rcrelid = '%u'::oid "
                                                                  "ORDER BY rcname",
@@ -4080,9 +4763,11 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                                constrs[j].contype = 'c';
                                constrs[j].condef = strdup(PQgetvalue(res, j, 3));
                                constrs[j].conindex = 0;
-                               constrs[j].coninherited = false;
+                               constrs[j].conislocal = (PQgetvalue(res, j, 4)[0] == 't');
                                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
@@ -4094,53 +4779,336 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 
                                /*
                                 * If the constraint is inherited, this will be detected
-                                * later.  We also detect later if the constraint must be
-                                * split out from the table definition.
+                                * later (in pre-8.4 databases).  We also detect later if the
+                                * constraint must be split out from the table definition.
                                 */
                        }
                        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];
+       destroyPQExpBuffer(q);
+}
 
-                               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;
-                               }
-                       }
-               }
+
+/*
+ * getTSParsers:
+ *       read all text search parsers in the system catalogs and return them
+ *       in the TSParserInfo* structure
+ *
+ *     numTSParsers is set to the number of parsers read in
+ */
+TSParserInfo *
+getTSParsers(int *numTSParsers)
+{
+       PGresult   *res;
+       int                     ntups;
+       int                     i;
+       PQExpBuffer query = createPQExpBuffer();
+       TSParserInfo *prsinfo;
+       int                     i_tableoid;
+       int                     i_oid;
+       int                     i_prsname;
+       int                     i_prsnamespace;
+       int                     i_prsstart;
+       int                     i_prstoken;
+       int                     i_prsend;
+       int                     i_prsheadline;
+       int                     i_prslextype;
+
+       /* Before 8.3, there is no built-in text search support */
+       if (g_fout->remoteVersion < 80300)
+       {
+               *numTSParsers = 0;
+               return NULL;
        }
 
-       destroyPQExpBuffer(q);
+       /*
+        * find all text search objects, including builtin ones; we filter out
+        * system-defined objects at dump-out time.
+        */
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       appendPQExpBuffer(query, "SELECT tableoid, oid, prsname, prsnamespace, "
+                                         "prsstart::oid, prstoken::oid, "
+                                         "prsend::oid, prsheadline::oid, prslextype::oid "
+                                         "FROM pg_ts_parser");
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       ntups = PQntuples(res);
+       *numTSParsers = ntups;
+
+       prsinfo = (TSParserInfo *) malloc(ntups * sizeof(TSParserInfo));
+
+       i_tableoid = PQfnumber(res, "tableoid");
+       i_oid = PQfnumber(res, "oid");
+       i_prsname = PQfnumber(res, "prsname");
+       i_prsnamespace = PQfnumber(res, "prsnamespace");
+       i_prsstart = PQfnumber(res, "prsstart");
+       i_prstoken = PQfnumber(res, "prstoken");
+       i_prsend = PQfnumber(res, "prsend");
+       i_prsheadline = PQfnumber(res, "prsheadline");
+       i_prslextype = PQfnumber(res, "prslextype");
+
+       for (i = 0; i < ntups; i++)
+       {
+               prsinfo[i].dobj.objType = DO_TSPARSER;
+               prsinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               prsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&prsinfo[i].dobj);
+               prsinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_prsname));
+               prsinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_prsnamespace)),
+                                                                                                 prsinfo[i].dobj.catId.oid);
+               prsinfo[i].prsstart = atooid(PQgetvalue(res, i, i_prsstart));
+               prsinfo[i].prstoken = atooid(PQgetvalue(res, i, i_prstoken));
+               prsinfo[i].prsend = atooid(PQgetvalue(res, i, i_prsend));
+               prsinfo[i].prsheadline = atooid(PQgetvalue(res, i, i_prsheadline));
+               prsinfo[i].prslextype = atooid(PQgetvalue(res, i, i_prslextype));
+
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(prsinfo[i].dobj));
+       }
+
+       PQclear(res);
+
+       destroyPQExpBuffer(query);
+
+       return prsinfo;
+}
+
+/*
+ * getTSDictionaries:
+ *       read all text search dictionaries in the system catalogs and return them
+ *       in the TSDictInfo* structure
+ *
+ *     numTSDicts is set to the number of dictionaries read in
+ */
+TSDictInfo *
+getTSDictionaries(int *numTSDicts)
+{
+       PGresult   *res;
+       int                     ntups;
+       int                     i;
+       PQExpBuffer query = createPQExpBuffer();
+       TSDictInfo *dictinfo;
+       int                     i_tableoid;
+       int                     i_oid;
+       int                     i_dictname;
+       int                     i_dictnamespace;
+       int                     i_rolname;
+       int                     i_dicttemplate;
+       int                     i_dictinitoption;
+
+       /* Before 8.3, there is no built-in text search support */
+       if (g_fout->remoteVersion < 80300)
+       {
+               *numTSDicts = 0;
+               return NULL;
+       }
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       appendPQExpBuffer(query, "SELECT tableoid, oid, dictname, "
+                                         "dictnamespace, (%s dictowner) as rolname, "
+                                         "dicttemplate, dictinitoption "
+                                         "FROM pg_ts_dict",
+                                         username_subquery);
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       ntups = PQntuples(res);
+       *numTSDicts = ntups;
+
+       dictinfo = (TSDictInfo *) malloc(ntups * sizeof(TSDictInfo));
+
+       i_tableoid = PQfnumber(res, "tableoid");
+       i_oid = PQfnumber(res, "oid");
+       i_dictname = PQfnumber(res, "dictname");
+       i_dictnamespace = PQfnumber(res, "dictnamespace");
+       i_rolname = PQfnumber(res, "rolname");
+       i_dictinitoption = PQfnumber(res, "dictinitoption");
+       i_dicttemplate = PQfnumber(res, "dicttemplate");
+
+       for (i = 0; i < ntups; i++)
+       {
+               dictinfo[i].dobj.objType = DO_TSDICT;
+               dictinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               dictinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&dictinfo[i].dobj);
+               dictinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_dictname));
+               dictinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_dictnamespace)),
+                                                                                                dictinfo[i].dobj.catId.oid);
+               dictinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+               dictinfo[i].dicttemplate = atooid(PQgetvalue(res, i, i_dicttemplate));
+               if (PQgetisnull(res, i, i_dictinitoption))
+                       dictinfo[i].dictinitoption = NULL;
+               else
+                       dictinfo[i].dictinitoption = strdup(PQgetvalue(res, i, i_dictinitoption));
+
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(dictinfo[i].dobj));
+       }
+
+       PQclear(res);
+
+       destroyPQExpBuffer(query);
+
+       return dictinfo;
+}
+
+/*
+ * getTSTemplates:
+ *       read all text search templates in the system catalogs and return them
+ *       in the TSTemplateInfo* structure
+ *
+ *     numTSTemplates is set to the number of templates read in
+ */
+TSTemplateInfo *
+getTSTemplates(int *numTSTemplates)
+{
+       PGresult   *res;
+       int                     ntups;
+       int                     i;
+       PQExpBuffer query = createPQExpBuffer();
+       TSTemplateInfo *tmplinfo;
+       int                     i_tableoid;
+       int                     i_oid;
+       int                     i_tmplname;
+       int                     i_tmplnamespace;
+       int                     i_tmplinit;
+       int                     i_tmpllexize;
+
+       /* Before 8.3, there is no built-in text search support */
+       if (g_fout->remoteVersion < 80300)
+       {
+               *numTSTemplates = 0;
+               return NULL;
+       }
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       appendPQExpBuffer(query, "SELECT tableoid, oid, tmplname, "
+                                         "tmplnamespace, tmplinit::oid, tmpllexize::oid "
+                                         "FROM pg_ts_template");
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       ntups = PQntuples(res);
+       *numTSTemplates = ntups;
+
+       tmplinfo = (TSTemplateInfo *) malloc(ntups * sizeof(TSTemplateInfo));
+
+       i_tableoid = PQfnumber(res, "tableoid");
+       i_oid = PQfnumber(res, "oid");
+       i_tmplname = PQfnumber(res, "tmplname");
+       i_tmplnamespace = PQfnumber(res, "tmplnamespace");
+       i_tmplinit = PQfnumber(res, "tmplinit");
+       i_tmpllexize = PQfnumber(res, "tmpllexize");
+
+       for (i = 0; i < ntups; i++)
+       {
+               tmplinfo[i].dobj.objType = DO_TSTEMPLATE;
+               tmplinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               tmplinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&tmplinfo[i].dobj);
+               tmplinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_tmplname));
+               tmplinfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_tmplnamespace)),
+                                                                                                tmplinfo[i].dobj.catId.oid);
+               tmplinfo[i].tmplinit = atooid(PQgetvalue(res, i, i_tmplinit));
+               tmplinfo[i].tmpllexize = atooid(PQgetvalue(res, i, i_tmpllexize));
+
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(tmplinfo[i].dobj));
+       }
+
+       PQclear(res);
+
+       destroyPQExpBuffer(query);
+
+       return tmplinfo;
+}
+
+/*
+ * getTSConfigurations:
+ *       read all text search configurations in the system catalogs and return
+ *       them in the TSConfigInfo* structure
+ *
+ *     numTSConfigs is set to the number of configurations read in
+ */
+TSConfigInfo *
+getTSConfigurations(int *numTSConfigs)
+{
+       PGresult   *res;
+       int                     ntups;
+       int                     i;
+       PQExpBuffer query = createPQExpBuffer();
+       TSConfigInfo *cfginfo;
+       int                     i_tableoid;
+       int                     i_oid;
+       int                     i_cfgname;
+       int                     i_cfgnamespace;
+       int                     i_rolname;
+       int                     i_cfgparser;
+
+       /* Before 8.3, there is no built-in text search support */
+       if (g_fout->remoteVersion < 80300)
+       {
+               *numTSConfigs = 0;
+               return NULL;
+       }
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       appendPQExpBuffer(query, "SELECT tableoid, oid, cfgname, "
+                                         "cfgnamespace, (%s cfgowner) as rolname, cfgparser "
+                                         "FROM pg_ts_config",
+                                         username_subquery);
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       ntups = PQntuples(res);
+       *numTSConfigs = ntups;
+
+       cfginfo = (TSConfigInfo *) malloc(ntups * sizeof(TSConfigInfo));
+
+       i_tableoid = PQfnumber(res, "tableoid");
+       i_oid = PQfnumber(res, "oid");
+       i_cfgname = PQfnumber(res, "cfgname");
+       i_cfgnamespace = PQfnumber(res, "cfgnamespace");
+       i_rolname = PQfnumber(res, "rolname");
+       i_cfgparser = PQfnumber(res, "cfgparser");
+
+       for (i = 0; i < ntups; i++)
+       {
+               cfginfo[i].dobj.objType = DO_TSCONFIG;
+               cfginfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+               cfginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+               AssignDumpId(&cfginfo[i].dobj);
+               cfginfo[i].dobj.name = strdup(PQgetvalue(res, i, i_cfgname));
+               cfginfo[i].dobj.namespace = findNamespace(atooid(PQgetvalue(res, i, i_cfgnamespace)),
+                                                                                                 cfginfo[i].dobj.catId.oid);
+               cfginfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+               cfginfo[i].cfgparser = atooid(PQgetvalue(res, i, i_cfgparser));
+
+               /* Decide whether we want to dump it */
+               selectDumpableObject(&(cfginfo[i].dobj));
+       }
+
+       PQclear(res);
+
+       destroyPQExpBuffer(query);
+
+       return cfginfo;
 }
 
 
@@ -4193,7 +5161,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(),
@@ -4251,7 +5219,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(),
@@ -4273,7 +5241,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(),
@@ -4479,6 +5447,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;
@@ -4491,6 +5462,9 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
                case DO_OPCLASS:
                        dumpOpclass(fout, (OpclassInfo *) dobj);
                        break;
+               case DO_OPFAMILY:
+                       dumpOpfamily(fout, (OpfamilyInfo *) dobj);
+                       break;
                case DO_CONVERSION:
                        dumpConversion(fout, (ConvInfo *) dobj);
                        break;
@@ -4527,6 +5501,18 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
                case DO_TABLE_TYPE:
                        /* table rowtypes are never dumped separately */
                        break;
+               case DO_TSPARSER:
+                       dumpTSParser(fout, (TSParserInfo *) dobj);
+                       break;
+               case DO_TSDICT:
+                       dumpTSDictionary(fout, (TSDictInfo *) dobj);
+                       break;
+               case DO_TSTEMPLATE:
+                       dumpTSTemplate(fout, (TSTemplateInfo *) dobj);
+                       break;
+               case DO_TSCONFIG:
+                       dumpTSConfig(fout, (TSConfigInfo *) dobj);
+                       break;
                case DO_BLOBS:
                        ArchiveEntry(fout, dobj->catId, dobj->dumpId,
                                                 dobj->name, NULL, NULL, "",
@@ -4555,8 +5541,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 */
@@ -4604,79 +5590,169 @@ 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 != RELKIND_COMPOSITE_TYPE)
-               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 */
-       if (tinfo->typtype == 'b')
+       if (tinfo->typtype == TYPTYPE_BASE)
                dumpBaseType(fout, tinfo);
-       else if (tinfo->typtype == 'd')
+       else if (tinfo->typtype == TYPTYPE_DOMAIN)
                dumpDomain(fout, tinfo);
-       else if (tinfo->typtype == 'c')
+       else if (tinfo->typtype == TYPTYPE_COMPOSITE)
                dumpCompositeType(fout, tinfo);
+       else if (tinfo->typtype == TYPTYPE_ENUM)
+               dumpEnumType(fout, tinfo);
 }
 
 /*
- * dumpBaseType
- *       writes out to fout the queries to recreate a user-defined base type
+ * dumpEnumType
+ *       writes out to fout the queries to recreate a user-defined enum type
  */
 static void
-dumpBaseType(Archive *fout, TypeInfo *tinfo)
+dumpEnumType(Archive *fout, TypeInfo *tinfo)
 {
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
        PQExpBuffer query = createPQExpBuffer();
        PGresult   *res;
-       int                     ntups;
-       char       *typlen;
-       char       *typinput;
-       char       *typoutput;
-       char       *typreceive;
-       char       *typsend;
-       char       *typanalyze;
-       Oid                     typinputoid;
-       Oid                     typoutputoid;
-       Oid                     typreceiveoid;
-       Oid                     typsendoid;
-       Oid                     typanalyzeoid;
-       char       *typdelim;
-       char       *typdefault;
-       char       *typbyval;
-       char       *typalign;
-       char       *typstorage;
+       int                     num,
+                               i;
+       char       *label;
+
+       /* Set proper schema search path so regproc references list correctly */
+       selectSourceSchema(tinfo->dobj.namespace->dobj.name);
+
+       appendPQExpBuffer(query, "SELECT enumlabel FROM pg_catalog.pg_enum "
+                                         "WHERE enumtypid = '%u'"
+                                         "ORDER BY oid",
+                                         tinfo->dobj.catId.oid);
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       num = PQntuples(res);
+       /* should be at least 1 value */
+       if (num == 0)
+       {
+               write_msg(NULL, "no label definitions found for enum ID %u\n", tinfo->dobj.catId.oid);
+               exit_nicely();
+       }
+
+       /*
+        * DROP must be fully qualified in case same name appears in pg_catalog.
+        * CASCADE shouldn't be required here as for normal types since the I/O
+        * functions are generic and do not get dropped.
+        */
+       appendPQExpBuffer(delq, "DROP TYPE %s.",
+                                         fmtId(tinfo->dobj.namespace->dobj.name));
+       appendPQExpBuffer(delq, "%s;\n",
+                                         fmtId(tinfo->dobj.name));
+       appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (\n",
+                                         fmtId(tinfo->dobj.name));
+       for (i = 0; i < num; i++)
+       {
+               label = PQgetvalue(res, i, 0);
+               if (i > 0)
+                       appendPQExpBuffer(q, ",\n");
+               appendPQExpBuffer(q, "    ");
+               appendStringLiteralAH(q, label, fout);
+       }
+       appendPQExpBuffer(q, "\n);\n");
+
+       ArchiveEntry(fout, tinfo->dobj.catId, tinfo->dobj.dumpId,
+                                tinfo->dobj.name,
+                                tinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                tinfo->rolname, false,
+                                "TYPE", q->data, delq->data, NULL,
+                                tinfo->dobj.dependencies, tinfo->dobj.nDeps,
+                                NULL, NULL);
+
+       /* Dump Type Comments */
+       resetPQExpBuffer(q);
+
+       appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo->dobj.name));
+       dumpComment(fout, q->data,
+                               tinfo->dobj.namespace->dobj.name, tinfo->rolname,
+                               tinfo->dobj.catId, 0, tinfo->dobj.dumpId);
+
+       PQclear(res);
+       destroyPQExpBuffer(q);
+       destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(query);
+}
+
+/*
+ * dumpBaseType
+ *       writes out to fout the queries to recreate a user-defined base type
+ */
+static void
+dumpBaseType(Archive *fout, TypeInfo *tinfo)
+{
+       PQExpBuffer q = createPQExpBuffer();
+       PQExpBuffer delq = createPQExpBuffer();
+       PQExpBuffer query = createPQExpBuffer();
+       PGresult   *res;
+       int                     ntups;
+       char       *typlen;
+       char       *typinput;
+       char       *typoutput;
+       char       *typreceive;
+       char       *typsend;
+       char       *typmodin;
+       char       *typmodout;
+       char       *typanalyze;
+       Oid                     typinputoid;
+       Oid                     typoutputoid;
+       Oid                     typreceiveoid;
+       Oid                     typsendoid;
+       Oid                     typmodinoid;
+       Oid                     typmodoutoid;
+       Oid                     typanalyzeoid;
+       char       *typdelim;
+       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);
 
        /* Fetch type-specific details */
-       if (fout->remoteVersion >= 80000)
+       if (fout->remoteVersion >= 80300)
+       {
+               appendPQExpBuffer(query, "SELECT typlen, "
+                                                 "typinput, typoutput, typreceive, typsend, "
+                                                 "typmodin, typmodout, typanalyze, "
+                                                 "typinput::pg_catalog.oid as typinputoid, "
+                                                 "typoutput::pg_catalog.oid as typoutputoid, "
+                                                 "typreceive::pg_catalog.oid as typreceiveoid, "
+                                                 "typsend::pg_catalog.oid as typsendoid, "
+                                                 "typmodin::pg_catalog.oid as typmodinoid, "
+                                                 "typmodout::pg_catalog.oid as typmodoutoid, "
+                                                 "typanalyze::pg_catalog.oid as typanalyzeoid, "
+                                                 "typdelim, typbyval, typalign, typstorage, "
+                                                 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
+                                                 "FROM pg_catalog.pg_type "
+                                                 "WHERE oid = '%u'::pg_catalog.oid",
+                                                 tinfo->dobj.catId.oid);
+       }
+       else if (fout->remoteVersion >= 80000)
        {
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, typreceive, typsend, "
+                                                 "'-' as typmodin, '-' as typmodout, "
                                                  "typanalyze, "
                                                  "typinput::pg_catalog.oid as typinputoid, "
                                                  "typoutput::pg_catalog.oid as typoutputoid, "
                                                  "typreceive::pg_catalog.oid as typreceiveoid, "
                                                  "typsend::pg_catalog.oid as typsendoid, "
+                                                 "0 as typmodinoid, 0 as typmodoutoid, "
                                                  "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);
@@ -4685,14 +5761,16 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        {
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, typreceive, typsend, "
+                                                 "'-' as typmodin, '-' as typmodout, "
                                                  "'-' as typanalyze, "
                                                  "typinput::pg_catalog.oid as typinputoid, "
                                                  "typoutput::pg_catalog.oid as typoutputoid, "
                                                  "typreceive::pg_catalog.oid as typreceiveoid, "
                                                  "typsend::pg_catalog.oid as typsendoid, "
+                                                 "0 as typmodinoid, 0 as typmodoutoid, "
                                                  "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);
@@ -4702,18 +5780,20 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, "
                                                  "'-' as typreceive, '-' as typsend, "
+                                                 "'-' as typmodin, '-' as typmodout, "
                                                  "'-' as typanalyze, "
                                                  "typinput::pg_catalog.oid as typinputoid, "
                                                  "typoutput::pg_catalog.oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
+                                                 "0 as typmodinoid, 0 as typmodoutoid, "
                                                  "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,
@@ -4722,13 +5802,37 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, "
                                                  "'-' as typreceive, '-' as typsend, "
+                                                 "'-' as typmodin, '-' as typmodout, "
+                                                 "'-' as typanalyze, "
+                                                 "typinput::oid as typinputoid, "
+                                                 "typoutput::oid as typoutputoid, "
+                                                 "0 as typreceiveoid, 0 as typsendoid, "
+                                                 "0 as typmodinoid, 0 as typmodoutoid, "
+                                                 "0 as typanalyzeoid, "
+                                                 "typdelim, typbyval, typalign, typstorage, "
+                                                 "NULL as typdefaultbin, typdefault "
+                                                 "FROM pg_type "
+                                                 "WHERE oid = '%u'::oid",
+                                                 tinfo->dobj.catId.oid);
+       }
+       else if (fout->remoteVersion >= 70100)
+       {
+               /*
+                * Ignore pre-7.2 typdefault; the field exists but has an unusable
+                * representation.
+                */
+               appendPQExpBuffer(query, "SELECT typlen, "
+                                                 "typinput, typoutput, "
+                                                 "'-' as typreceive, '-' as typsend, "
+                                                 "'-' as typmodin, '-' as typmodout, "
                                                  "'-' as typanalyze, "
                                                  "typinput::oid as typinputoid, "
                                                  "typoutput::oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
+                                                 "0 as typmodinoid, 0 as typmodoutoid, "
                                                  "0 as typanalyzeoid, "
-                                                 "typdelim, typdefault, typbyval, typalign, "
-                                                 "typstorage "
+                                                 "typdelim, typbyval, typalign, typstorage, "
+                                                 "NULL as typdefaultbin, NULL as typdefault "
                                                  "FROM pg_type "
                                                  "WHERE oid = '%u'::oid",
                                                  tinfo->dobj.catId.oid);
@@ -4738,13 +5842,16 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, "
                                                  "'-' as typreceive, '-' as typsend, "
+                                                 "'-' as typmodin, '-' as typmodout, "
                                                  "'-' as typanalyze, "
                                                  "typinput::oid as typinputoid, "
                                                  "typoutput::oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
+                                                 "0 as typmodinoid, 0 as typmodoutoid, "
                                                  "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);
@@ -4757,7 +5864,7 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        ntups = PQntuples(res);
        if (ntups != 1)
        {
-               write_msg(NULL, "Got %d rows instead of one from: %s",
+               write_msg(NULL, "query returned %d rows instead of one: %s\n",
                                  ntups, query->data);
                exit_nicely();
        }
@@ -4767,23 +5874,35 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        typoutput = PQgetvalue(res, 0, PQfnumber(res, "typoutput"));
        typreceive = PQgetvalue(res, 0, PQfnumber(res, "typreceive"));
        typsend = PQgetvalue(res, 0, PQfnumber(res, "typsend"));
+       typmodin = PQgetvalue(res, 0, PQfnumber(res, "typmodin"));
+       typmodout = PQgetvalue(res, 0, PQfnumber(res, "typmodout"));
        typanalyze = PQgetvalue(res, 0, PQfnumber(res, "typanalyze"));
        typinputoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typinputoid")));
        typoutputoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typoutputoid")));
        typreceiveoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typreceiveoid")));
        typsendoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typsendoid")));
+       typmodinoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typmodinoid")));
+       typmodoutoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typmodoutoid")));
        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));
@@ -4805,6 +5924,10 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                        appendPQExpBuffer(q, ",\n    RECEIVE = %s", typreceive);
                if (OidIsValid(typsendoid))
                        appendPQExpBuffer(q, ",\n    SEND = %s", typsend);
+               if (OidIsValid(typmodinoid))
+                       appendPQExpBuffer(q, ",\n    TYPMOD_IN = %s", typmodin);
+               if (OidIsValid(typmodoutoid))
+                       appendPQExpBuffer(q, ",\n    TYPMOD_OUT = %s", typmodout);
                if (OidIsValid(typanalyzeoid))
                        appendPQExpBuffer(q, ",\n    ANALYZE = %s", typanalyze);
        }
@@ -4814,16 +5937,19 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                /* cannot combine these because fmtId uses static result area */
                appendPQExpBuffer(q, ",\n    INPUT = %s", fmtId(typinput));
                appendPQExpBuffer(q, ",\n    OUTPUT = %s", fmtId(typoutput));
-               /* no chance that receive/send/analyze need be printed */
+               /* receive/send/typmodin/typmodout/analyze need not be printed */
        }
 
        if (typdefault != NULL)
        {
                appendPQExpBuffer(q, ",\n    DEFAULT = ");
-               appendStringLiteral(q, typdefault, true);
+               if (typdefault_is_literal)
+                       appendStringLiteralAH(q, typdefault, fout);
+               else
+                       appendPQExpBufferStr(q, typdefault);
        }
 
-       if (tinfo->isArray)
+       if (OidIsValid(tinfo->typelem))
        {
                char       *elemType;
 
@@ -4837,7 +5963,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)
@@ -4902,6 +6028,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);
@@ -4910,7 +6037,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);
@@ -4922,17 +6049,22 @@ dumpDomain(Archive *fout, TypeInfo *tinfo)
        ntups = PQntuples(res);
        if (ntups != 1)
        {
-               write_msg(NULL, "Got %d rows instead of one from: %s",
+               write_msg(NULL, "query returned %d rows instead of one: %s\n",
                                  ntups, query->data);
                exit_nicely();
        }
 
        typnotnull = PQgetvalue(res, 0, PQfnumber(res, "typnotnull"));
        typdefn = PQgetvalue(res, 0, PQfnumber(res, "typdefn"));
-       if (PQgetisnull(res, 0, PQfnumber(res, "typdefault")))
-               typdefault = NULL;
-       else
+       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",
@@ -4942,8 +6074,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);
 
@@ -5030,7 +6168,7 @@ dumpCompositeType(Archive *fout, TypeInfo *tinfo)
        ntups = PQntuples(res);
        if (ntups < 1)
        {
-               write_msg(NULL, "query yielded no rows: %s\n", query->data);
+               write_msg(NULL, "query returned no rows: %s\n", query->data);
                exit_nicely();
        }
 
@@ -5087,6 +6225,47 @@ dumpCompositeType(Archive *fout, TypeInfo *tinfo)
 }
 
 /*
+ * dumpShellType
+ *       writes out to fout the queries to create a shell type
+ *
+ * We dump a shell definition in advance of the I/O functions for the type.
+ */
+static void
+dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
+{
+       PQExpBuffer q;
+
+       /* Skip if not to be dumped */
+       if (!stinfo->dobj.dump || dataOnly)
+               return;
+
+       q = createPQExpBuffer();
+
+       /*
+        * Note the lack of a DROP command for the shell type; any required DROP
+        * is driven off the base type entry, instead.  This interacts with
+        * _printTocEntry()'s use of the presence of a DROP command to decide
+        * whether an entry needs an ALTER OWNER command.  We don't want to alter
+        * the shell type's owner immediately on creation; that should happen only
+        * after it's filled in, otherwise the backend complains.
+        */
+
+       appendPQExpBuffer(q, "CREATE TYPE %s;\n",
+                                         fmtId(stinfo->dobj.name));
+
+       ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId,
+                                stinfo->dobj.name,
+                                stinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                stinfo->baseType->rolname, false,
+                                "SHELL TYPE", q->data, "", NULL,
+                                stinfo->dobj.dependencies, stinfo->dobj.nDeps,
+                                NULL, NULL);
+
+       destroyPQExpBuffer(q);
+}
+
+/*
  * Determine whether we want to dump definitions for procedural languages.
  * Since the languages themselves don't have schemas, we can't rely on
  * the normal schema-based selection mechanism.  We choose to dump them
@@ -5101,7 +6280,7 @@ dumpCompositeType(Archive *fout, TypeInfo *tinfo)
 static bool
 shouldDumpProcLangs(void)
 {
-       if (selectTableName != NULL || selectSchemaName != NULL)
+       if (!include_everything)
                return false;
        /* And they're schema not data */
        if (dataOnly)
@@ -5137,13 +6316,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;
        }
 
@@ -5256,15 +6435,18 @@ format_function_arguments(FuncInfo *finfo, int nallargs,
                {
                        switch (argmodes[j][0])
                        {
-                               case 'i':
+                               case PROARGMODE_IN:
                                        argmode = "";
                                        break;
-                               case 'o':
+                               case PROARGMODE_OUT:
                                        argmode = "OUT ";
                                        break;
-                               case 'b':
+                               case PROARGMODE_INOUT:
                                        argmode = "INOUT ";
                                        break;
+                               case PROARGMODE_VARIADIC:
+                                       argmode = "VARIADIC ";
+                                       break;
                                default:
                                        write_msg(NULL, "WARNING: bogus value in proargmodes array\n");
                                        argmode = "";
@@ -5351,15 +6533,21 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        char       *provolatile;
        char       *proisstrict;
        char       *prosecdef;
+       char       *proconfig;
+       char       *procost;
+       char       *prorows;
        char       *lanname;
        char       *rettypename;
        int                     nallargs;
        char      **allargtypes = NULL;
        char      **argmodes = NULL;
        char      **argnames = NULL;
+       char      **configitems = NULL;
+       int                     nconfigitems = 0;
+       int                     i;
 
-       /* 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();
@@ -5371,12 +6559,25 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        selectSourceSchema(finfo->dobj.namespace->dobj.name);
 
        /* Fetch function-specific details */
-       if (g_fout->remoteVersion >= 80100)
+       if (g_fout->remoteVersion >= 80300)
+       {
+               appendPQExpBuffer(query,
+                                                 "SELECT proretset, prosrc, probin, "
+                                                 "proallargtypes, proargmodes, proargnames, "
+                                                 "provolatile, proisstrict, prosecdef, "
+                                                 "proconfig, procost, prorows, "
+                                                 "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
+                                                 "FROM pg_catalog.pg_proc "
+                                                 "WHERE oid = '%u'::pg_catalog.oid",
+                                                 finfo->dobj.catId.oid);
+       }
+       else if (g_fout->remoteVersion >= 80100)
        {
                appendPQExpBuffer(query,
                                                  "SELECT proretset, prosrc, probin, "
                                                  "proallargtypes, proargmodes, proargnames, "
                                                  "provolatile, proisstrict, prosecdef, "
+                                                 "null as proconfig, 0 as procost, 0 as prorows, "
                                                  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
                                                  "FROM pg_catalog.pg_proc "
                                                  "WHERE oid = '%u'::pg_catalog.oid",
@@ -5390,6 +6591,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                                                  "null as proargmodes, "
                                                  "proargnames, "
                                                  "provolatile, proisstrict, prosecdef, "
+                                                 "null as proconfig, 0 as procost, 0 as prorows, "
                                                  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
                                                  "FROM pg_catalog.pg_proc "
                                                  "WHERE oid = '%u'::pg_catalog.oid",
@@ -5403,6 +6605,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                                                  "null as proargmodes, "
                                                  "null as proargnames, "
                                                  "provolatile, proisstrict, prosecdef, "
+                                                 "null as proconfig, 0 as procost, 0 as prorows, "
                                                  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
                                                  "FROM pg_catalog.pg_proc "
                                                  "WHERE oid = '%u'::pg_catalog.oid",
@@ -5418,6 +6621,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                         "case when proiscachable then 'i' else 'v' end as provolatile, "
                                                  "proisstrict, "
                                                  "'f'::boolean as prosecdef, "
+                                                 "null as proconfig, 0 as procost, 0 as prorows, "
                  "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
                                                  "FROM pg_proc "
                                                  "WHERE oid = '%u'::oid",
@@ -5433,6 +6637,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                         "case when proiscachable then 'i' else 'v' end as provolatile, "
                                                  "'f'::boolean as proisstrict, "
                                                  "'f'::boolean as prosecdef, "
+                                                 "null as proconfig, 0 as procost, 0 as prorows, "
                  "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
                                                  "FROM pg_proc "
                                                  "WHERE oid = '%u'::oid",
@@ -5446,7 +6651,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        ntups = PQntuples(res);
        if (ntups != 1)
        {
-               write_msg(NULL, "Got %d rows instead of one from: %s",
+               write_msg(NULL, "query returned %d rows instead of one: %s\n",
                                  ntups, query->data);
                exit_nicely();
        }
@@ -5460,16 +6665,21 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
        proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
        prosecdef = PQgetvalue(res, 0, PQfnumber(res, "prosecdef"));
+       proconfig = PQgetvalue(res, 0, PQfnumber(res, "proconfig"));
+       procost = PQgetvalue(res, 0, PQfnumber(res, "procost"));
+       prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows"));
        lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
 
        /*
-        * See backend/commands/define.c for details of how the 'AS' clause is
-        * used.
+        * See backend/commands/functioncmds.c for details of how the 'AS' clause
+        * is used.  In 8.4 and up, an unused probin is NULL (here ""); previous
+        * versions would set it to "-".  There are no known cases in which prosrc
+        * is unused, so the tests below for "-" are probably useless.
         */
-       if (strcmp(probin, "-") != 0)
+       if (probin[0] != '\0' && strcmp(probin, "-") != 0)
        {
                appendPQExpBuffer(asPart, "AS ");
-               appendStringLiteral(asPart, probin, true);
+               appendStringLiteralAH(asPart, probin, fout);
                if (strcmp(prosrc, "-") != 0)
                {
                        appendPQExpBuffer(asPart, ", ");
@@ -5478,10 +6688,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
@@ -5491,7 +6702,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);
                }
@@ -5543,6 +6754,18 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                }
        }
 
+       if (proconfig && *proconfig)
+       {
+               if (!parsePGArray(proconfig, &configitems, &nconfigitems))
+               {
+                       write_msg(NULL, "WARNING: could not parse proconfig array\n");
+                       if (configitems)
+                               free(configitems);
+                       configitems = NULL;
+                       nconfigitems = 0;
+               }
+       }
+
        funcsig = format_function_arguments(finfo, nallargs, allargtypes,
                                                                                argmodes, argnames);
        funcsig_tag = format_function_signature(finfo, false);
@@ -5557,14 +6780,12 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        rettypename = getFormattedTypeName(finfo->prorettype, zeroAsOpaque);
 
        appendPQExpBuffer(q, "CREATE FUNCTION %s ", funcsig);
-       appendPQExpBuffer(q, "RETURNS %s%s\n    %s\n    LANGUAGE %s",
+       appendPQExpBuffer(q, "RETURNS %s%s",
                                          (proretset[0] == 't') ? "SETOF " : "",
-                                         rettypename,
-                                         asPart->data,
-                                         fmtId(lanname));
-
+                                         rettypename);
        free(rettypename);
 
+       appendPQExpBuffer(q, "\n    LANGUAGE %s", fmtId(lanname));
        if (provolatile[0] != PROVOLATILE_VOLATILE)
        {
                if (provolatile[0] == PROVOLATILE_IMMUTABLE)
@@ -5585,7 +6806,54 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        if (prosecdef[0] == 't')
                appendPQExpBuffer(q, " SECURITY DEFINER");
 
-       appendPQExpBuffer(q, ";\n");
+       /*
+        * COST and ROWS are emitted only if present and not default, so as not to
+        * break backwards-compatibility of the dump without need.      Keep this code
+        * in sync with the defaults in functioncmds.c.
+        */
+       if (strcmp(procost, "0") != 0)
+       {
+               if (strcmp(lanname, "internal") == 0 || strcmp(lanname, "c") == 0)
+               {
+                       /* default cost is 1 */
+                       if (strcmp(procost, "1") != 0)
+                               appendPQExpBuffer(q, " COST %s", procost);
+               }
+               else
+               {
+                       /* default cost is 100 */
+                       if (strcmp(procost, "100") != 0)
+                               appendPQExpBuffer(q, " COST %s", procost);
+               }
+       }
+       if (proretset[0] == 't' &&
+               strcmp(prorows, "0") != 0 && strcmp(prorows, "1000") != 0)
+               appendPQExpBuffer(q, " ROWS %s", prorows);
+
+       for (i = 0; i < nconfigitems; i++)
+       {
+               /* we feel free to scribble on configitems[] here */
+               char       *configitem = configitems[i];
+               char       *pos;
+
+               pos = strchr(configitem, '=');
+               if (pos == NULL)
+                       continue;
+               *pos++ = '\0';
+               appendPQExpBuffer(q, "\n    SET %s TO ", fmtId(configitem));
+
+               /*
+                * Some GUC variable names are 'LIST' type and hence must not be
+                * quoted.
+                */
+               if (pg_strcasecmp(configitem, "DateStyle") == 0
+                       || pg_strcasecmp(configitem, "search_path") == 0)
+                       appendPQExpBuffer(q, "%s", pos);
+               else
+                       appendStringLiteralAH(q, pos, fout);
+       }
+
+       appendPQExpBuffer(q, "\n    %s;\n", asPart->data);
 
        ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
                                 funcsig_tag,
@@ -5622,6 +6890,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                free(argmodes);
        if (argnames)
                free(argnames);
+       if (configitems)
+               free(configitems);
 }
 
 
@@ -5651,9 +6921,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);
@@ -5671,25 +6940,25 @@ dumpCast(Archive *fout, CastInfo *cast)
                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) */
@@ -5775,11 +7044,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        int                     i_oprnegate;
        int                     i_oprrest;
        int                     i_oprjoin;
+       int                     i_oprcanmerge;
        int                     i_oprcanhash;
-       int                     i_oprlsortop;
-       int                     i_oprrsortop;
-       int                     i_oprltcmpop;
-       int                     i_oprgtcmpop;
        char       *oprkind;
        char       *oprcode;
        char       *oprleft;
@@ -5788,14 +7054,11 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        char       *oprnegate;
        char       *oprrest;
        char       *oprjoin;
+       char       *oprcanmerge;
        char       *oprcanhash;
-       char       *oprlsortop;
-       char       *oprrsortop;
-       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;
 
        /*
@@ -5814,7 +7077,22 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        /* Make sure we are in proper schema so regoperator works correctly */
        selectSourceSchema(oprinfo->dobj.namespace->dobj.name);
 
-       if (g_fout->remoteVersion >= 70300)
+       if (g_fout->remoteVersion >= 80300)
+       {
+               appendPQExpBuffer(query, "SELECT oprkind, "
+                                                 "oprcode::pg_catalog.regprocedure, "
+                                                 "oprleft::pg_catalog.regtype, "
+                                                 "oprright::pg_catalog.regtype, "
+                                                 "oprcom::pg_catalog.regoperator, "
+                                                 "oprnegate::pg_catalog.regoperator, "
+                                                 "oprrest::pg_catalog.regprocedure, "
+                                                 "oprjoin::pg_catalog.regprocedure, "
+                                                 "oprcanmerge, oprcanhash "
+                                                 "from pg_catalog.pg_operator "
+                                                 "where oid = '%u'::pg_catalog.oid",
+                                                 oprinfo->dobj.catId.oid);
+       }
+       else if (g_fout->remoteVersion >= 70300)
        {
                appendPQExpBuffer(query, "SELECT oprkind, "
                                                  "oprcode::pg_catalog.regprocedure, "
@@ -5824,11 +7102,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
                                                  "oprnegate::pg_catalog.regoperator, "
                                                  "oprrest::pg_catalog.regprocedure, "
                                                  "oprjoin::pg_catalog.regprocedure, "
-                                                 "oprcanhash, "
-                                                 "oprlsortop::pg_catalog.regoperator, "
-                                                 "oprrsortop::pg_catalog.regoperator, "
-                                                 "oprltcmpop::pg_catalog.regoperator, "
-                                                 "oprgtcmpop::pg_catalog.regoperator "
+                                                 "(oprlsortop != 0) as oprcanmerge, "
+                                                 "oprcanhash "
                                                  "from pg_catalog.pg_operator "
                                                  "where oid = '%u'::pg_catalog.oid",
                                                  oprinfo->dobj.catId.oid);
@@ -5841,8 +7116,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
                                                  "CASE WHEN oprright = 0 THEN '-' "
                                                  "ELSE format_type(oprright, NULL) END as oprright, "
                                                  "oprcom, oprnegate, oprrest, oprjoin, "
-                                                 "oprcanhash, oprlsortop, oprrsortop, "
-                                                 "0 as oprltcmpop, 0 as oprgtcmpop "
+                                                 "(oprlsortop != 0) as oprcanmerge, "
+                                                 "oprcanhash "
                                                  "from pg_operator "
                                                  "where oid = '%u'::oid",
                                                  oprinfo->dobj.catId.oid);
@@ -5855,8 +7130,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
                                                  "CASE WHEN oprright = 0 THEN '-'::name "
                                                  "ELSE (select typname from pg_type where oid = oprright) END as oprright, "
                                                  "oprcom, oprnegate, oprrest, oprjoin, "
-                                                 "oprcanhash, oprlsortop, oprrsortop, "
-                                                 "0 as oprltcmpop, 0 as oprgtcmpop "
+                                                 "(oprlsortop != 0) as oprcanmerge, "
+                                                 "oprcanhash "
                                                  "from pg_operator "
                                                  "where oid = '%u'::oid",
                                                  oprinfo->dobj.catId.oid);
@@ -5869,7 +7144,7 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        ntups = PQntuples(res);
        if (ntups != 1)
        {
-               write_msg(NULL, "Got %d rows instead of one from: %s",
+               write_msg(NULL, "query returned %d rows instead of one: %s\n",
                                  ntups, query->data);
                exit_nicely();
        }
@@ -5882,11 +7157,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        i_oprnegate = PQfnumber(res, "oprnegate");
        i_oprrest = PQfnumber(res, "oprrest");
        i_oprjoin = PQfnumber(res, "oprjoin");
+       i_oprcanmerge = PQfnumber(res, "oprcanmerge");
        i_oprcanhash = PQfnumber(res, "oprcanhash");
-       i_oprlsortop = PQfnumber(res, "oprlsortop");
-       i_oprrsortop = PQfnumber(res, "oprrsortop");
-       i_oprltcmpop = PQfnumber(res, "oprltcmpop");
-       i_oprgtcmpop = PQfnumber(res, "oprgtcmpop");
 
        oprkind = PQgetvalue(res, 0, i_oprkind);
        oprcode = PQgetvalue(res, 0, i_oprcode);
@@ -5896,11 +7168,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        oprnegate = PQgetvalue(res, 0, i_oprnegate);
        oprrest = PQgetvalue(res, 0, i_oprrest);
        oprjoin = PQgetvalue(res, 0, i_oprjoin);
+       oprcanmerge = PQgetvalue(res, 0, i_oprcanmerge);
        oprcanhash = PQgetvalue(res, 0, i_oprcanhash);
-       oprlsortop = PQgetvalue(res, 0, i_oprlsortop);
-       oprrsortop = PQgetvalue(res, 0, i_oprrsortop);
-       oprltcmpop = PQgetvalue(res, 0, i_oprltcmpop);
-       oprgtcmpop = PQgetvalue(res, 0, i_oprgtcmpop);
 
        appendPQExpBuffer(details, "    PROCEDURE = %s",
                                          convertRegProcReference(oprcode));
@@ -5946,6 +7215,9 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        if (name)
                appendPQExpBuffer(details, ",\n    NEGATOR = %s", name);
 
+       if (strcmp(oprcanmerge, "t") == 0)
+               appendPQExpBuffer(details, ",\n    MERGES");
+
        if (strcmp(oprcanhash, "t") == 0)
                appendPQExpBuffer(details, ",\n    HASHES");
 
@@ -5957,22 +7229,6 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        if (name)
                appendPQExpBuffer(details, ",\n    JOIN = %s", name);
 
-       name = convertOperatorReference(oprlsortop);
-       if (name)
-               appendPQExpBuffer(details, ",\n    SORT1 = %s", name);
-
-       name = convertOperatorReference(oprrsortop);
-       if (name)
-               appendPQExpBuffer(details, ",\n    SORT2 = %s", name);
-
-       name = convertOperatorReference(oprltcmpop);
-       if (name)
-               appendPQExpBuffer(details, ",\n    LTCMP = %s", name);
-
-       name = convertOperatorReference(oprgtcmpop);
-       if (name)
-               appendPQExpBuffer(details, ",\n    GTCMP = %s", name);
-
        /*
         * DROP must be fully qualified in case same name appears in pg_catalog
         */
@@ -6112,6 +7368,43 @@ convertOperatorReference(const char *opr)
 }
 
 /*
+ * Convert a function OID obtained from pg_ts_parser or pg_ts_template
+ *
+ * It is sufficient to use REGPROC rather than REGPROCEDURE, since the
+ * argument lists of these functions are predetermined.  Note that the
+ * caller should ensure we are in the proper schema, because the results
+ * are search path dependent!
+ */
+static const char *
+convertTSFunction(Oid funcOid)
+{
+       char       *result;
+       char            query[128];
+       PGresult   *res;
+       int                     ntups;
+
+       snprintf(query, sizeof(query),
+                        "SELECT '%u'::pg_catalog.regproc", funcOid);
+       res = PQexec(g_conn, query);
+       check_sql_result(res, g_conn, query, PGRES_TUPLES_OK);
+
+       ntups = PQntuples(res);
+       if (ntups != 1)
+       {
+               write_msg(NULL, "query returned %d rows instead of one: %s\n",
+                                 ntups, query);
+               exit_nicely();
+       }
+
+       result = strdup(PQgetvalue(res, 0, 0));
+
+       PQclear(res);
+
+       return result;
+}
+
+
+/*
  * dumpOpclass
  *       write out a single operator class definition
  */
@@ -6126,6 +7419,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        int                     i_opcintype;
        int                     i_opckeytype;
        int                     i_opcdefault;
+       int                     i_opcfamily;
+       int                     i_opcfamilynsp;
        int                     i_amname;
        int                     i_amopstrategy;
        int                     i_amopreqcheck;
@@ -6135,6 +7430,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        char       *opcintype;
        char       *opckeytype;
        char       *opcdefault;
+       char       *opcfamily;
+       char       *opcfamilynsp;
        char       *amname;
        char       *amopstrategy;
        char       *amopreqcheck;
@@ -6144,8 +7441,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;
 
        /*
@@ -6164,13 +7461,32 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        selectSourceSchema(opcinfo->dobj.namespace->dobj.name);
 
        /* Get additional fields from the pg_opclass row */
-       appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
-                                         "opckeytype::pg_catalog.regtype, "
-                                         "opcdefault, "
-          "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
-                                         "FROM pg_catalog.pg_opclass "
-                                         "WHERE oid = '%u'::pg_catalog.oid",
-                                         opcinfo->dobj.catId.oid);
+       if (g_fout->remoteVersion >= 80300)
+       {
+               appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
+                                                 "opckeytype::pg_catalog.regtype, "
+                                                 "opcdefault, "
+                                                 "opfname AS opcfamily, "
+                                                 "nspname AS opcfamilynsp, "
+                                                 "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcmethod) AS amname "
+                                                 "FROM pg_catalog.pg_opclass c "
+                                  "LEFT JOIN pg_catalog.pg_opfamily f ON f.oid = opcfamily "
+                          "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = opfnamespace "
+                                                 "WHERE c.oid = '%u'::pg_catalog.oid",
+                                                 opcinfo->dobj.catId.oid);
+       }
+       else
+       {
+               appendPQExpBuffer(query, "SELECT opcintype::pg_catalog.regtype, "
+                                                 "opckeytype::pg_catalog.regtype, "
+                                                 "opcdefault, "
+                                                 "NULL AS opcfamily, "
+                                                 "NULL AS opcfamilynsp, "
+               "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opcamid) AS amname "
+                                                 "FROM pg_catalog.pg_opclass "
+                                                 "WHERE oid = '%u'::pg_catalog.oid",
+                                                 opcinfo->dobj.catId.oid);
+       }
 
        res = PQexec(g_conn, query->data);
        check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
@@ -6179,7 +7495,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        ntups = PQntuples(res);
        if (ntups != 1)
        {
-               write_msg(NULL, "Got %d rows instead of one from: %s",
+               write_msg(NULL, "query returned %d rows instead of one: %s\n",
                                  ntups, query->data);
                exit_nicely();
        }
@@ -6187,11 +7503,15 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        i_opcintype = PQfnumber(res, "opcintype");
        i_opckeytype = PQfnumber(res, "opckeytype");
        i_opcdefault = PQfnumber(res, "opcdefault");
+       i_opcfamily = PQfnumber(res, "opcfamily");
+       i_opcfamilynsp = PQfnumber(res, "opcfamilynsp");
        i_amname = PQfnumber(res, "amname");
 
        opcintype = PQgetvalue(res, 0, i_opcintype);
        opckeytype = PQgetvalue(res, 0, i_opckeytype);
        opcdefault = PQgetvalue(res, 0, i_opcdefault);
+       opcfamily = PQgetvalue(res, 0, i_opcfamily);
+       opcfamilynsp = PQgetvalue(res, 0, i_opcfamilynsp);
        /* amname will still be needed after we PQclear res */
        amname = strdup(PQgetvalue(res, 0, i_amname));
 
@@ -6210,9 +7530,19 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
                                          fmtId(opcinfo->dobj.name));
        if (strcmp(opcdefault, "t") == 0)
                appendPQExpBuffer(q, "DEFAULT ");
-       appendPQExpBuffer(q, "FOR TYPE %s USING %s AS\n    ",
+       appendPQExpBuffer(q, "FOR TYPE %s USING %s",
                                          opcintype,
                                          fmtId(amname));
+       if (strlen(opcfamily) > 0 &&
+               (strcmp(opcfamily, opcinfo->dobj.name) != 0 ||
+                strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0))
+       {
+               appendPQExpBuffer(q, " FAMILY ");
+               if (strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
+                       appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp));
+               appendPQExpBuffer(q, "%s", fmtId(opcfamily));
+       }
+       appendPQExpBuffer(q, " AS\n    ");
 
        needComma = false;
 
@@ -6230,12 +7560,51 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
         */
        resetPQExpBuffer(query);
 
-       appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
-                                         "amopopr::pg_catalog.regoperator "
-                                         "FROM pg_catalog.pg_amop "
-                                         "WHERE amopclaid = '%u'::pg_catalog.oid "
-                                         "ORDER BY amopstrategy",
-                                         opcinfo->dobj.catId.oid);
+       if (g_fout->remoteVersion >= 80400)
+       {
+               /*
+                * Print only those opfamily members that are tied to the opclass by
+                * pg_depend entries.
+                *
+                * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
+                * an older server's table in which it is used.  Would it be better
+                * to silently ignore it?
+                */
+               appendPQExpBuffer(query, "SELECT amopstrategy, false as amopreqcheck, "
+                                                 "amopopr::pg_catalog.regoperator "
+                                                 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
+                  "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
+                                                 "AND refobjid = '%u'::pg_catalog.oid "
+                                  "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
+                                                 "AND objid = ao.oid "
+                                                 "ORDER BY amopstrategy",
+                                                 opcinfo->dobj.catId.oid);
+       }
+       else if (g_fout->remoteVersion >= 80300)
+       {
+               /*
+                * Print only those opfamily members that are tied to the opclass by
+                * pg_depend entries.
+                */
+               appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
+                                                 "amopopr::pg_catalog.regoperator "
+                                                 "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
+                  "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
+                                                 "AND refobjid = '%u'::pg_catalog.oid "
+                                  "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
+                                                 "AND objid = ao.oid "
+                                                 "ORDER BY amopstrategy",
+                                                 opcinfo->dobj.catId.oid);
+       }
+       else
+       {
+               appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
+                                                 "amopopr::pg_catalog.regoperator "
+                                                 "FROM pg_catalog.pg_amop "
+                                                 "WHERE amopclaid = '%u'::pg_catalog.oid "
+                                                 "ORDER BY amopstrategy",
+                                                 opcinfo->dobj.catId.oid);
+       }
 
        res = PQexec(g_conn, query->data);
        check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
@@ -6270,12 +7639,31 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
         */
        resetPQExpBuffer(query);
 
-       appendPQExpBuffer(query, "SELECT amprocnum, "
-                                         "amproc::pg_catalog.regprocedure "
-                                         "FROM pg_catalog.pg_amproc "
-                                         "WHERE amopclaid = '%u'::pg_catalog.oid "
-                                         "ORDER BY amprocnum",
-                                         opcinfo->dobj.catId.oid);
+       if (g_fout->remoteVersion >= 80300)
+       {
+               /*
+                * Print only those opfamily members that are tied to the opclass by
+                * pg_depend entries.
+                */
+               appendPQExpBuffer(query, "SELECT amprocnum, "
+                                                 "amproc::pg_catalog.regprocedure "
+                                               "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
+                  "WHERE refclassid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
+                                                 "AND refobjid = '%u'::pg_catalog.oid "
+                                "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
+                                                 "AND objid = ap.oid "
+                                                 "ORDER BY amprocnum",
+                                                 opcinfo->dobj.catId.oid);
+       }
+       else
+       {
+               appendPQExpBuffer(query, "SELECT amprocnum, "
+                                                 "amproc::pg_catalog.regprocedure "
+                                                 "FROM pg_catalog.pg_amproc "
+                                                 "WHERE amopclaid = '%u'::pg_catalog.oid "
+                                                 "ORDER BY amprocnum",
+                                                 opcinfo->dobj.catId.oid);
+       }
 
        res = PQexec(g_conn, query->data);
        check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
@@ -6329,6 +7717,284 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
 }
 
 /*
+ * dumpOpfamily
+ *       write out a single operator family definition
+ */
+static void
+dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
+{
+       PQExpBuffer query;
+       PQExpBuffer q;
+       PQExpBuffer delq;
+       PGresult   *res;
+       PGresult   *res_ops;
+       PGresult   *res_procs;
+       int                     ntups;
+       int                     i_amname;
+       int                     i_amopstrategy;
+       int                     i_amopreqcheck;
+       int                     i_amopopr;
+       int                     i_amprocnum;
+       int                     i_amproc;
+       int                     i_amproclefttype;
+       int                     i_amprocrighttype;
+       char       *amname;
+       char       *amopstrategy;
+       char       *amopreqcheck;
+       char       *amopopr;
+       char       *amprocnum;
+       char       *amproc;
+       char       *amproclefttype;
+       char       *amprocrighttype;
+       bool            needComma;
+       int                     i;
+
+       /* Skip if not to be dumped */
+       if (!opfinfo->dobj.dump || dataOnly)
+               return;
+
+       /*
+        * We want to dump the opfamily only if (1) it contains "loose" operators
+        * or functions, or (2) it contains an opclass with a different name or
+        * owner.  Otherwise it's sufficient to let it be created during creation
+        * of the contained opclass, and not dumping it improves portability of
+        * the dump.  Since we have to fetch the loose operators/funcs anyway, do
+        * that first.
+        */
+
+       query = createPQExpBuffer();
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
+
+       /* Make sure we are in proper schema so regoperator works correctly */
+       selectSourceSchema(opfinfo->dobj.namespace->dobj.name);
+
+       /*
+        * Fetch only those opfamily members that are tied directly to the
+        * opfamily by pg_depend entries.
+        */
+       if (g_fout->remoteVersion >= 80400)
+       {
+               /*
+                * XXX RECHECK is gone as of 8.4, but we'll still print it if dumping
+                * an older server's table in which it is used.  Would it be better
+                * to silently ignore it?
+                */
+               appendPQExpBuffer(query, "SELECT amopstrategy, false as amopreqcheck, "
+                                         "amopopr::pg_catalog.regoperator "
+                                         "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
+                 "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
+                                         "AND refobjid = '%u'::pg_catalog.oid "
+                                  "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
+                                         "AND objid = ao.oid "
+                                         "ORDER BY amopstrategy",
+                                         opfinfo->dobj.catId.oid);
+       }
+       else
+       {
+               appendPQExpBuffer(query, "SELECT amopstrategy, amopreqcheck, "
+                                         "amopopr::pg_catalog.regoperator "
+                                         "FROM pg_catalog.pg_amop ao, pg_catalog.pg_depend "
+                 "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
+                                         "AND refobjid = '%u'::pg_catalog.oid "
+                                  "AND classid = 'pg_catalog.pg_amop'::pg_catalog.regclass "
+                                         "AND objid = ao.oid "
+                                         "ORDER BY amopstrategy",
+                                         opfinfo->dobj.catId.oid);
+       }
+
+       res_ops = PQexec(g_conn, query->data);
+       check_sql_result(res_ops, g_conn, query->data, PGRES_TUPLES_OK);
+
+       resetPQExpBuffer(query);
+
+       appendPQExpBuffer(query, "SELECT amprocnum, "
+                                         "amproc::pg_catalog.regprocedure, "
+                                         "amproclefttype::pg_catalog.regtype, "
+                                         "amprocrighttype::pg_catalog.regtype "
+                                         "FROM pg_catalog.pg_amproc ap, pg_catalog.pg_depend "
+                 "WHERE refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
+                                         "AND refobjid = '%u'::pg_catalog.oid "
+                                "AND classid = 'pg_catalog.pg_amproc'::pg_catalog.regclass "
+                                         "AND objid = ap.oid "
+                                         "ORDER BY amprocnum",
+                                         opfinfo->dobj.catId.oid);
+
+       res_procs = PQexec(g_conn, query->data);
+       check_sql_result(res_procs, g_conn, query->data, PGRES_TUPLES_OK);
+
+       if (PQntuples(res_ops) == 0 && PQntuples(res_procs) == 0)
+       {
+               /* No loose members, so check contained opclasses */
+               resetPQExpBuffer(query);
+
+               appendPQExpBuffer(query, "SELECT 1 "
+                                                 "FROM pg_catalog.pg_opclass c, pg_catalog.pg_opfamily f, pg_catalog.pg_depend "
+                                                 "WHERE f.oid = '%u'::pg_catalog.oid "
+                       "AND refclassid = 'pg_catalog.pg_opfamily'::pg_catalog.regclass "
+                                                 "AND refobjid = f.oid "
+                               "AND classid = 'pg_catalog.pg_opclass'::pg_catalog.regclass "
+                                                 "AND objid = c.oid "
+                                                 "AND (opcname != opfname OR opcnamespace != opfnamespace OR opcowner != opfowner) "
+                                                 "LIMIT 1",
+                                                 opfinfo->dobj.catId.oid);
+
+               res = PQexec(g_conn, query->data);
+               check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+               if (PQntuples(res) == 0)
+               {
+                       /* no need to dump it, so bail out */
+                       PQclear(res);
+                       PQclear(res_ops);
+                       PQclear(res_procs);
+                       destroyPQExpBuffer(query);
+                       destroyPQExpBuffer(q);
+                       destroyPQExpBuffer(delq);
+                       return;
+               }
+
+               PQclear(res);
+       }
+
+       /* Get additional fields from the pg_opfamily row */
+       resetPQExpBuffer(query);
+
+       appendPQExpBuffer(query, "SELECT "
+        "(SELECT amname FROM pg_catalog.pg_am WHERE oid = opfmethod) AS amname "
+                                         "FROM pg_catalog.pg_opfamily "
+                                         "WHERE oid = '%u'::pg_catalog.oid",
+                                         opfinfo->dobj.catId.oid);
+
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+       /* Expecting a single result only */
+       ntups = PQntuples(res);
+       if (ntups != 1)
+       {
+               write_msg(NULL, "query returned %d rows instead of one: %s\n",
+                                 ntups, query->data);
+               exit_nicely();
+       }
+
+       i_amname = PQfnumber(res, "amname");
+
+       /* amname will still be needed after we PQclear res */
+       amname = strdup(PQgetvalue(res, 0, i_amname));
+
+       /*
+        * DROP must be fully qualified in case same name appears in pg_catalog
+        */
+       appendPQExpBuffer(delq, "DROP OPERATOR FAMILY %s",
+                                         fmtId(opfinfo->dobj.namespace->dobj.name));
+       appendPQExpBuffer(delq, ".%s",
+                                         fmtId(opfinfo->dobj.name));
+       appendPQExpBuffer(delq, " USING %s;\n",
+                                         fmtId(amname));
+
+       /* Build the fixed portion of the CREATE command */
+       appendPQExpBuffer(q, "CREATE OPERATOR FAMILY %s",
+                                         fmtId(opfinfo->dobj.name));
+       appendPQExpBuffer(q, " USING %s;\n",
+                                         fmtId(amname));
+
+       PQclear(res);
+
+       /* Do we need an ALTER to add loose members? */
+       if (PQntuples(res_ops) > 0 || PQntuples(res_procs) > 0)
+       {
+               appendPQExpBuffer(q, "ALTER OPERATOR FAMILY %s",
+                                                 fmtId(opfinfo->dobj.name));
+               appendPQExpBuffer(q, " USING %s ADD\n    ",
+                                                 fmtId(amname));
+
+               needComma = false;
+
+               /*
+                * Now fetch and print the OPERATOR entries (pg_amop rows).
+                */
+               ntups = PQntuples(res_ops);
+
+               i_amopstrategy = PQfnumber(res_ops, "amopstrategy");
+               i_amopreqcheck = PQfnumber(res_ops, "amopreqcheck");
+               i_amopopr = PQfnumber(res_ops, "amopopr");
+
+               for (i = 0; i < ntups; i++)
+               {
+                       amopstrategy = PQgetvalue(res_ops, i, i_amopstrategy);
+                       amopreqcheck = PQgetvalue(res_ops, i, i_amopreqcheck);
+                       amopopr = PQgetvalue(res_ops, i, i_amopopr);
+
+                       if (needComma)
+                               appendPQExpBuffer(q, " ,\n    ");
+
+                       appendPQExpBuffer(q, "OPERATOR %s %s",
+                                                         amopstrategy, amopopr);
+                       if (strcmp(amopreqcheck, "t") == 0)
+                               appendPQExpBuffer(q, " RECHECK");
+
+                       needComma = true;
+               }
+
+               /*
+                * Now fetch and print the FUNCTION entries (pg_amproc rows).
+                */
+               ntups = PQntuples(res_procs);
+
+               i_amprocnum = PQfnumber(res_procs, "amprocnum");
+               i_amproc = PQfnumber(res_procs, "amproc");
+               i_amproclefttype = PQfnumber(res_procs, "amproclefttype");
+               i_amprocrighttype = PQfnumber(res_procs, "amprocrighttype");
+
+               for (i = 0; i < ntups; i++)
+               {
+                       amprocnum = PQgetvalue(res_procs, i, i_amprocnum);
+                       amproc = PQgetvalue(res_procs, i, i_amproc);
+                       amproclefttype = PQgetvalue(res_procs, i, i_amproclefttype);
+                       amprocrighttype = PQgetvalue(res_procs, i, i_amprocrighttype);
+
+                       if (needComma)
+                               appendPQExpBuffer(q, " ,\n    ");
+
+                       appendPQExpBuffer(q, "FUNCTION %s (%s, %s) %s",
+                                                         amprocnum, amproclefttype, amprocrighttype,
+                                                         amproc);
+
+                       needComma = true;
+               }
+
+               appendPQExpBuffer(q, ";\n");
+       }
+
+       ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId,
+                                opfinfo->dobj.name,
+                                opfinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                opfinfo->rolname,
+                                false, "OPERATOR FAMILY", q->data, delq->data, NULL,
+                                opfinfo->dobj.dependencies, opfinfo->dobj.nDeps,
+                                NULL, NULL);
+
+       /* Dump Operator Family Comments */
+       resetPQExpBuffer(q);
+       appendPQExpBuffer(q, "OPERATOR FAMILY %s",
+                                         fmtId(opfinfo->dobj.name));
+       appendPQExpBuffer(q, " USING %s",
+                                         fmtId(amname));
+       dumpComment(fout, q->data,
+                               NULL, opfinfo->rolname,
+                               opfinfo->dobj.catId, 0, opfinfo->dobj.dumpId);
+
+       free(amname);
+       PQclear(res_ops);
+       PQclear(res_procs);
+       destroyPQExpBuffer(query);
+       destroyPQExpBuffer(q);
+       destroyPQExpBuffer(delq);
+}
+
+/*
  * dumpConversion
  *       write out a single conversion definition
  */
@@ -6352,8 +8018,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();
@@ -6380,7 +8046,7 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        ntups = PQntuples(res);
        if (ntups != 1)
        {
-               write_msg(NULL, "Got %d rows instead of one from: %s",
+               write_msg(NULL, "query returned %d rows instead of one: %s\n",
                                  ntups, query->data);
                exit_nicely();
        }
@@ -6408,9 +8074,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);
 
@@ -6448,6 +8114,7 @@ static char *
 format_aggregate_signature(AggInfo *agginfo, Archive *fout, bool honor_quotes)
 {
        PQExpBufferData buf;
+       int                     j;
 
        initPQExpBuffer(&buf);
        if (honor_quotes)
@@ -6456,23 +8123,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;
 }
 
@@ -6496,8 +8164,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;
@@ -6506,8 +8172,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();
@@ -6525,8 +8191,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 "
@@ -6539,8 +8203,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 "
@@ -6553,9 +8215,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",
@@ -6568,8 +8227,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",
@@ -6578,148 +8235,477 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
 
        res = PQexec(g_conn, query->data);
        check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
-
-       /* Expecting a single result only */
+
+       /* Expecting a single result only */
+       ntups = PQntuples(res);
+       if (ntups != 1)
+       {
+               write_msg(NULL, "query returned %d rows instead of one: %s\n",
+                                 ntups, query->data);
+               exit_nicely();
+       }
+
+       i_aggtransfn = PQfnumber(res, "aggtransfn");
+       i_aggfinalfn = PQfnumber(res, "aggfinalfn");
+       i_aggsortop = PQfnumber(res, "aggsortop");
+       i_aggtranstype = PQfnumber(res, "aggtranstype");
+       i_agginitval = PQfnumber(res, "agginitval");
+       i_convertok = PQfnumber(res, "convertok");
+
+       aggtransfn = PQgetvalue(res, 0, i_aggtransfn);
+       aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
+       aggsortop = PQgetvalue(res, 0, i_aggsortop);
+       aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
+       agginitval = PQgetvalue(res, 0, i_agginitval);
+       convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't');
+
+       aggsig = format_aggregate_signature(agginfo, fout, true);
+       aggsig_tag = format_aggregate_signature(agginfo, fout, false);
+
+       if (!convertok)
+       {
+               write_msg(NULL, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
+                                 aggsig);
+               return;
+       }
+
+       if (g_fout->remoteVersion >= 70300)
+       {
+               /* If using 7.3's regproc or regtype, data is already quoted */
+               appendPQExpBuffer(details, "    SFUNC = %s,\n    STYPE = %s",
+                                                 aggtransfn,
+                                                 aggtranstype);
+       }
+       else if (g_fout->remoteVersion >= 70100)
+       {
+               /* format_type quotes, regproc does not */
+               appendPQExpBuffer(details, "    SFUNC = %s,\n    STYPE = %s",
+                                                 fmtId(aggtransfn),
+                                                 aggtranstype);
+       }
+       else
+       {
+               /* need quotes all around */
+               appendPQExpBuffer(details, "    SFUNC = %s,\n",
+                                                 fmtId(aggtransfn));
+               appendPQExpBuffer(details, "    STYPE = %s",
+                                                 fmtId(aggtranstype));
+       }
+
+       if (!PQgetisnull(res, 0, i_agginitval))
+       {
+               appendPQExpBuffer(details, ",\n    INITCOND = ");
+               appendStringLiteralAH(details, agginitval, fout);
+       }
+
+       if (strcmp(aggfinalfn, "-") != 0)
+       {
+               appendPQExpBuffer(details, ",\n    FINALFUNC = %s",
+                                                 aggfinalfn);
+       }
+
+       aggsortop = convertOperatorReference(aggsortop);
+       if (aggsortop)
+       {
+               appendPQExpBuffer(details, ",\n    SORTOP = %s",
+                                                 aggsortop);
+       }
+
+       /*
+        * DROP must be fully qualified in case same name appears in pg_catalog
+        */
+       appendPQExpBuffer(delq, "DROP AGGREGATE %s.%s;\n",
+                                         fmtId(agginfo->aggfn.dobj.namespace->dobj.name),
+                                         aggsig);
+
+       appendPQExpBuffer(q, "CREATE AGGREGATE %s (\n%s\n);\n",
+                                         aggsig, details->data);
+
+       ArchiveEntry(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
+                                aggsig_tag,
+                                agginfo->aggfn.dobj.namespace->dobj.name,
+                                NULL,
+                                agginfo->aggfn.rolname,
+                                false, "AGGREGATE", q->data, delq->data, NULL,
+                                agginfo->aggfn.dobj.dependencies, agginfo->aggfn.dobj.nDeps,
+                                NULL, NULL);
+
+       /* Dump Aggregate Comments */
+       resetPQExpBuffer(q);
+       appendPQExpBuffer(q, "AGGREGATE %s", aggsig);
+       dumpComment(fout, q->data,
+                       agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname,
+                               agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
+
+       /*
+        * Since there is no GRANT ON AGGREGATE syntax, we have to make the ACL
+        * command look like a function's GRANT; in particular this affects the
+        * syntax for zero-argument aggregates.
+        */
+       free(aggsig);
+       free(aggsig_tag);
+
+       aggsig = format_function_signature(&agginfo->aggfn, true);
+       aggsig_tag = format_function_signature(&agginfo->aggfn, false);
+
+       dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
+                       "FUNCTION",
+                       aggsig, aggsig_tag,
+                       agginfo->aggfn.dobj.namespace->dobj.name,
+                       agginfo->aggfn.rolname, agginfo->aggfn.proacl);
+
+       free(aggsig);
+       free(aggsig_tag);
+
+       PQclear(res);
+
+       destroyPQExpBuffer(query);
+       destroyPQExpBuffer(q);
+       destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(details);
+}
+
+/*
+ * dumpTSParser
+ *       write out a single text search parser
+ */
+static void
+dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
+{
+       PQExpBuffer q;
+       PQExpBuffer delq;
+
+       /* Skip if not to be dumped */
+       if (!prsinfo->dobj.dump || dataOnly)
+               return;
+
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema(prsinfo->dobj.namespace->dobj.name);
+
+       appendPQExpBuffer(q, "CREATE TEXT SEARCH PARSER %s (\n",
+                                         fmtId(prsinfo->dobj.name));
+
+       appendPQExpBuffer(q, "    START = %s,\n",
+                                         convertTSFunction(prsinfo->prsstart));
+       appendPQExpBuffer(q, "    GETTOKEN = %s,\n",
+                                         convertTSFunction(prsinfo->prstoken));
+       appendPQExpBuffer(q, "    END = %s,\n",
+                                         convertTSFunction(prsinfo->prsend));
+       if (prsinfo->prsheadline != InvalidOid)
+               appendPQExpBuffer(q, "    HEADLINE = %s,\n",
+                                                 convertTSFunction(prsinfo->prsheadline));
+       appendPQExpBuffer(q, "    LEXTYPES = %s );\n",
+                                         convertTSFunction(prsinfo->prslextype));
+
+       /*
+        * DROP must be fully qualified in case same name appears in pg_catalog
+        */
+       appendPQExpBuffer(delq, "DROP TEXT SEARCH PARSER %s",
+                                         fmtId(prsinfo->dobj.namespace->dobj.name));
+       appendPQExpBuffer(delq, ".%s;\n",
+                                         fmtId(prsinfo->dobj.name));
+
+       ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId,
+                                prsinfo->dobj.name,
+                                prsinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                "",
+                                false, "TEXT SEARCH PARSER", q->data, delq->data, NULL,
+                                prsinfo->dobj.dependencies, prsinfo->dobj.nDeps,
+                                NULL, NULL);
+
+       /* Dump Parser Comments */
+       resetPQExpBuffer(q);
+       appendPQExpBuffer(q, "TEXT SEARCH PARSER %s",
+                                         fmtId(prsinfo->dobj.name));
+       dumpComment(fout, q->data,
+                               NULL, "",
+                               prsinfo->dobj.catId, 0, prsinfo->dobj.dumpId);
+
+       destroyPQExpBuffer(q);
+       destroyPQExpBuffer(delq);
+}
+
+/*
+ * dumpTSDictionary
+ *       write out a single text search dictionary
+ */
+static void
+dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
+{
+       PQExpBuffer q;
+       PQExpBuffer delq;
+       PQExpBuffer query;
+       PGresult   *res;
+       int                     ntups;
+       char       *nspname;
+       char       *tmplname;
+
+       /* Skip if not to be dumped */
+       if (!dictinfo->dobj.dump || dataOnly)
+               return;
+
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
+       query = createPQExpBuffer();
+
+       /* Fetch name and namespace of the dictionary's template */
+       selectSourceSchema("pg_catalog");
+       appendPQExpBuffer(query, "SELECT nspname, tmplname "
+                                         "FROM pg_ts_template p, pg_namespace n "
+                                         "WHERE p.oid = '%u' AND n.oid = tmplnamespace",
+                                         dictinfo->dicttemplate);
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+       ntups = PQntuples(res);
+       if (ntups != 1)
+       {
+               write_msg(NULL, "query returned %d rows instead of one: %s\n",
+                                 ntups, query->data);
+               exit_nicely();
+       }
+       nspname = PQgetvalue(res, 0, 0);
+       tmplname = PQgetvalue(res, 0, 1);
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema(dictinfo->dobj.namespace->dobj.name);
+
+       appendPQExpBuffer(q, "CREATE TEXT SEARCH DICTIONARY %s (\n",
+                                         fmtId(dictinfo->dobj.name));
+
+       appendPQExpBuffer(q, "    TEMPLATE = ");
+       if (strcmp(nspname, dictinfo->dobj.namespace->dobj.name) != 0)
+               appendPQExpBuffer(q, "%s.", fmtId(nspname));
+       appendPQExpBuffer(q, "%s", fmtId(tmplname));
+
+       PQclear(res);
+
+       /* the dictinitoption can be dumped straight into the command */
+       if (dictinfo->dictinitoption)
+               appendPQExpBuffer(q, ",\n    %s", dictinfo->dictinitoption);
+
+       appendPQExpBuffer(q, " );\n");
+
+       /*
+        * DROP must be fully qualified in case same name appears in pg_catalog
+        */
+       appendPQExpBuffer(delq, "DROP TEXT SEARCH DICTIONARY %s",
+                                         fmtId(dictinfo->dobj.namespace->dobj.name));
+       appendPQExpBuffer(delq, ".%s;\n",
+                                         fmtId(dictinfo->dobj.name));
+
+       ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId,
+                                dictinfo->dobj.name,
+                                dictinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                dictinfo->rolname,
+                                false, "TEXT SEARCH DICTIONARY", q->data, delq->data, NULL,
+                                dictinfo->dobj.dependencies, dictinfo->dobj.nDeps,
+                                NULL, NULL);
+
+       /* Dump Dictionary Comments */
+       resetPQExpBuffer(q);
+       appendPQExpBuffer(q, "TEXT SEARCH DICTIONARY %s",
+                                         fmtId(dictinfo->dobj.name));
+       dumpComment(fout, q->data,
+                               NULL, dictinfo->rolname,
+                               dictinfo->dobj.catId, 0, dictinfo->dobj.dumpId);
+
+       destroyPQExpBuffer(q);
+       destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(query);
+}
+
+/*
+ * dumpTSTemplate
+ *       write out a single text search template
+ */
+static void
+dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
+{
+       PQExpBuffer q;
+       PQExpBuffer delq;
+
+       /* Skip if not to be dumped */
+       if (!tmplinfo->dobj.dump || dataOnly)
+               return;
+
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema(tmplinfo->dobj.namespace->dobj.name);
+
+       appendPQExpBuffer(q, "CREATE TEXT SEARCH TEMPLATE %s (\n",
+                                         fmtId(tmplinfo->dobj.name));
+
+       if (tmplinfo->tmplinit != InvalidOid)
+               appendPQExpBuffer(q, "    INIT = %s,\n",
+                                                 convertTSFunction(tmplinfo->tmplinit));
+       appendPQExpBuffer(q, "    LEXIZE = %s );\n",
+                                         convertTSFunction(tmplinfo->tmpllexize));
+
+       /*
+        * DROP must be fully qualified in case same name appears in pg_catalog
+        */
+       appendPQExpBuffer(delq, "DROP TEXT SEARCH TEMPLATE %s",
+                                         fmtId(tmplinfo->dobj.namespace->dobj.name));
+       appendPQExpBuffer(delq, ".%s;\n",
+                                         fmtId(tmplinfo->dobj.name));
+
+       ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId,
+                                tmplinfo->dobj.name,
+                                tmplinfo->dobj.namespace->dobj.name,
+                                NULL,
+                                "",
+                                false, "TEXT SEARCH TEMPLATE", q->data, delq->data, NULL,
+                                tmplinfo->dobj.dependencies, tmplinfo->dobj.nDeps,
+                                NULL, NULL);
+
+       /* Dump Template Comments */
+       resetPQExpBuffer(q);
+       appendPQExpBuffer(q, "TEXT SEARCH TEMPLATE %s",
+                                         fmtId(tmplinfo->dobj.name));
+       dumpComment(fout, q->data,
+                               NULL, "",
+                               tmplinfo->dobj.catId, 0, tmplinfo->dobj.dumpId);
+
+       destroyPQExpBuffer(q);
+       destroyPQExpBuffer(delq);
+}
+
+/*
+ * dumpTSConfig
+ *       write out a single text search configuration
+ */
+static void
+dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
+{
+       PQExpBuffer q;
+       PQExpBuffer delq;
+       PQExpBuffer query;
+       PGresult   *res;
+       char       *nspname;
+       char       *prsname;
+       int                     ntups,
+                               i;
+       int                     i_tokenname;
+       int                     i_dictname;
+
+       /* Skip if not to be dumped */
+       if (!cfginfo->dobj.dump || dataOnly)
+               return;
+
+       q = createPQExpBuffer();
+       delq = createPQExpBuffer();
+       query = createPQExpBuffer();
+
+       /* Fetch name and namespace of the config's parser */
+       selectSourceSchema("pg_catalog");
+       appendPQExpBuffer(query, "SELECT nspname, prsname "
+                                         "FROM pg_ts_parser p, pg_namespace n "
+                                         "WHERE p.oid = '%u' AND n.oid = prsnamespace",
+                                         cfginfo->cfgparser);
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
        ntups = PQntuples(res);
        if (ntups != 1)
        {
-               write_msg(NULL, "Got %d rows instead of one from: %s",
+               write_msg(NULL, "query returned %d rows instead of one: %s\n",
                                  ntups, query->data);
                exit_nicely();
        }
+       nspname = PQgetvalue(res, 0, 0);
+       prsname = PQgetvalue(res, 0, 1);
 
-       i_aggtransfn = PQfnumber(res, "aggtransfn");
-       i_aggfinalfn = PQfnumber(res, "aggfinalfn");
-       i_aggsortop = PQfnumber(res, "aggsortop");
-       i_aggtranstype = PQfnumber(res, "aggtranstype");
-       i_agginitval = PQfnumber(res, "agginitval");
-       i_anybasetype = PQfnumber(res, "anybasetype");
-       i_fmtbasetype = PQfnumber(res, "fmtbasetype");
-       i_convertok = PQfnumber(res, "convertok");
+       /* Make sure we are in proper schema */
+       selectSourceSchema(cfginfo->dobj.namespace->dobj.name);
 
-       aggtransfn = PQgetvalue(res, 0, i_aggtransfn);
-       aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn);
-       aggsortop = PQgetvalue(res, 0, i_aggsortop);
-       aggtranstype = PQgetvalue(res, 0, i_aggtranstype);
-       agginitval = PQgetvalue(res, 0, i_agginitval);
-       /* we save anybasetype for format_aggregate_signature */
-       agginfo->anybasetype = (PQgetvalue(res, 0, i_anybasetype)[0] == 't');
-       /* we save fmtbasetype for format_aggregate_signature */
-       agginfo->fmtbasetype = strdup(PQgetvalue(res, 0, i_fmtbasetype));
-       convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't');
+       appendPQExpBuffer(q, "CREATE TEXT SEARCH CONFIGURATION %s (\n",
+                                         fmtId(cfginfo->dobj.name));
 
-       aggsig = format_aggregate_signature(agginfo, fout, true);
-       aggsig_tag = format_aggregate_signature(agginfo, fout, false);
+       appendPQExpBuffer(q, "    PARSER = ");
+       if (strcmp(nspname, cfginfo->dobj.namespace->dobj.name) != 0)
+               appendPQExpBuffer(q, "%s.", fmtId(nspname));
+       appendPQExpBuffer(q, "%s );\n", fmtId(prsname));
 
-       if (!convertok)
-       {
-               write_msg(NULL, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
-                                 aggsig);
-               return;
-       }
+       PQclear(res);
 
-       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,
-                                                 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,
-                                                 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",
-                                                 fmtId(aggtranstype));
-       }
+       resetPQExpBuffer(query);
+       appendPQExpBuffer(query,
+                                         "SELECT \n"
+                                         "  ( SELECT alias FROM pg_catalog.ts_token_type('%u'::pg_catalog.oid) AS t \n"
+                                         "    WHERE t.tokid = m.maptokentype ) AS tokenname, \n"
+                                         "  m.mapdict::pg_catalog.regdictionary AS dictname \n"
+                                         "FROM pg_catalog.pg_ts_config_map AS m \n"
+                                         "WHERE m.mapcfg = '%u' \n"
+                                         "ORDER BY m.mapcfg, m.maptokentype, m.mapseqno",
+                                         cfginfo->cfgparser, cfginfo->dobj.catId.oid);
 
-       if (!PQgetisnull(res, 0, i_agginitval))
-       {
-               appendPQExpBuffer(details, ",\n    INITCOND = ");
-               appendStringLiteral(details, agginitval, true);
-       }
+       res = PQexec(g_conn, query->data);
+       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+       ntups = PQntuples(res);
 
-       if (strcmp(aggfinalfn, "-") != 0)
-       {
-               appendPQExpBuffer(details, ",\n    FINALFUNC = %s",
-                                                 aggfinalfn);
-       }
+       i_tokenname = PQfnumber(res, "tokenname");
+       i_dictname = PQfnumber(res, "dictname");
 
-       aggsortop = convertOperatorReference(aggsortop);
-       if (aggsortop)
+       for (i = 0; i < ntups; i++)
        {
-               appendPQExpBuffer(details, ",\n    SORTOP = %s",
-                                                 aggsortop);
+               char       *tokenname = PQgetvalue(res, i, i_tokenname);
+               char       *dictname = PQgetvalue(res, i, i_dictname);
+
+               if (i == 0 ||
+                       strcmp(tokenname, PQgetvalue(res, i - 1, i_tokenname)) != 0)
+               {
+                       /* starting a new token type, so start a new command */
+                       if (i > 0)
+                               appendPQExpBuffer(q, ";\n");
+                       appendPQExpBuffer(q, "\nALTER TEXT SEARCH CONFIGURATION %s\n",
+                                                         fmtId(cfginfo->dobj.name));
+                       /* tokenname needs quoting, dictname does NOT */
+                       appendPQExpBuffer(q, "    ADD MAPPING FOR %s WITH %s",
+                                                         fmtId(tokenname), dictname);
+               }
+               else
+                       appendPQExpBuffer(q, ", %s", dictname);
        }
 
+       if (ntups > 0)
+               appendPQExpBuffer(q, ";\n");
+
+       PQclear(res);
+
        /*
         * DROP must be fully qualified in case same name appears in pg_catalog
         */
-       appendPQExpBuffer(delq, "DROP AGGREGATE %s.%s;\n",
-                                         fmtId(agginfo->aggfn.dobj.namespace->dobj.name),
-                                         aggsig);
-
-       appendPQExpBuffer(q, "CREATE AGGREGATE %s (\n%s\n);\n",
-                                         fmtId(agginfo->aggfn.dobj.name),
-                                         details->data);
+       appendPQExpBuffer(delq, "DROP TEXT SEARCH CONFIGURATION %s",
+                                         fmtId(cfginfo->dobj.namespace->dobj.name));
+       appendPQExpBuffer(delq, ".%s;\n",
+                                         fmtId(cfginfo->dobj.name));
 
-       ArchiveEntry(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
-                                aggsig_tag,
-                                agginfo->aggfn.dobj.namespace->dobj.name,
+       ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId,
+                                cfginfo->dobj.name,
+                                cfginfo->dobj.namespace->dobj.name,
                                 NULL,
-                                agginfo->aggfn.rolname,
-                                false, "AGGREGATE", q->data, delq->data, NULL,
-                                agginfo->aggfn.dobj.dependencies, agginfo->aggfn.dobj.nDeps,
+                                cfginfo->rolname,
+                          false, "TEXT SEARCH CONFIGURATION", q->data, delq->data, NULL,
+                                cfginfo->dobj.dependencies, cfginfo->dobj.nDeps,
                                 NULL, NULL);
 
-       /* Dump Aggregate Comments */
+       /* Dump Configuration Comments */
        resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "AGGREGATE %s", aggsig);
+       appendPQExpBuffer(q, "TEXT SEARCH CONFIGURATION %s",
+                                         fmtId(cfginfo->dobj.name));
        dumpComment(fout, q->data,
-                       agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname,
-                               agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
-
-       /*
-        * Since there is no GRANT ON AGGREGATE syntax, we have to make the ACL
-        * command look like a function's GRANT; in particular this affects the
-        * syntax for aggregates on ANY.
-        */
-       free(aggsig);
-       free(aggsig_tag);
-
-       aggsig = format_function_signature(&agginfo->aggfn, true);
-       aggsig_tag = format_function_signature(&agginfo->aggfn, false);
+                               NULL, cfginfo->rolname,
+                               cfginfo->dobj.catId, 0, cfginfo->dobj.dumpId);
 
-       dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
-                       "FUNCTION",
-                       aggsig, aggsig_tag,
-                       agginfo->aggfn.dobj.namespace->dobj.name,
-                       agginfo->aggfn.rolname, agginfo->aggfn.proacl);
-
-       free(aggsig);
-       free(aggsig_tag);
-
-       PQclear(res);
-
-       destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(details);
+       destroyPQExpBuffer(query);
 }
 
 
@@ -6779,7 +8765,7 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
 {
        char       *namecopy;
 
-       if (tbinfo->dump)
+       if (tbinfo->dobj.dump)
        {
                if (tbinfo->relkind == RELKIND_SEQUENCE)
                        dumpSequence(fout, tbinfo);
@@ -6838,7 +8824,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, ";");
                }
 
@@ -6914,16 +8900,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
                                {
@@ -6934,24 +8912,17 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                }
 
                                /*
-                                * Default value --- suppress if inherited, serial, or to be
-                                * printed separately.
+                                * Default value --- suppress if inherited or to be printed
+                                * separately.
                                 */
                                if (tbinfo->attrdefs[j] != NULL &&
                                        !tbinfo->inhAttrDef[j] &&
-                                       !tbinfo->attisserial[j] &&
                                        !tbinfo->attrdefs[j]->separate)
                                        appendPQExpBuffer(q, " DEFAULT %s",
                                                                          tbinfo->attrdefs[j]->adef_expr);
 
                                /*
                                 * Not Null constraint --- suppress if inherited
-                                *
-                                * Note: we could suppress this for serial columns since
-                                * SERIAL implies NOT NULL.  We choose not to for forward
-                                * compatibility, since there has been some talk of making
-                                * SERIAL not imply NOT NULL, in which case the explicit
-                                * specification would be needed.
                                 */
                                if (tbinfo->notnull[j] && !tbinfo->inhNotNull[j])
                                        appendPQExpBuffer(q, " NOT NULL");
@@ -6967,7 +8938,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                {
                        ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
 
-                       if (constr->coninherited || constr->separate)
+                       if (constr->separate || !constr->conislocal)
                                continue;
 
                        if (actual_atts > 0)
@@ -7000,6 +8971,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 */
@@ -7079,7 +9053,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
        {
                ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
 
-               if (constr->coninherited || constr->separate)
+               if (constr->separate || !constr->conislocal)
                        continue;
 
                dumpTableConstraintComment(fout, constr);
@@ -7102,11 +9076,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();
@@ -7255,9 +9229,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();
@@ -7298,7 +9271,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)
@@ -7401,8 +9379,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));
@@ -7488,7 +9466,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);
@@ -7550,7 +9528,8 @@ static void
 dumpSequence(Archive *fout, TableInfo *tbinfo)
 {
        PGresult   *res;
-       char       *last,
+       char       *startv,
+                          *last,
                           *incby,
                           *maxv = NULL,
                           *minv = NULL,
@@ -7568,19 +9547,40 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
        snprintf(bufm, sizeof(bufm), INT64_FORMAT, SEQ_MINVALUE);
        snprintf(bufx, sizeof(bufx), INT64_FORMAT, SEQ_MAXVALUE);
 
-       appendPQExpBuffer(query,
-                                         "SELECT sequence_name, last_value, increment_by, "
-                                  "CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
-                                  "     WHEN increment_by < 0 AND max_value = -1 THEN NULL "
-                                         "     ELSE max_value "
-                                         "END AS max_value, "
-                                       "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
-                                  "     WHEN increment_by < 0 AND min_value = %s THEN NULL "
-                                         "     ELSE min_value "
-                                         "END AS min_value, "
-                                         "cache_value, is_cycled, is_called from %s",
-                                         bufx, bufm,
-                                         fmtId(tbinfo->dobj.name));
+       if (g_fout->remoteVersion >= 80400)
+       {
+               appendPQExpBuffer(query,
+                                 "SELECT sequence_name, "
+                                 "start_value, last_value, increment_by, "
+                                 "CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
+                                 "     WHEN increment_by < 0 AND max_value = -1 THEN NULL "
+                                 "     ELSE max_value "
+                                 "END AS max_value, "
+                                 "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
+                                 "     WHEN increment_by < 0 AND min_value = %s THEN NULL "
+                                 "     ELSE min_value "
+                                 "END AS min_value, "
+                                 "cache_value, is_cycled, is_called from %s",
+                                 bufx, bufm,
+                                 fmtId(tbinfo->dobj.name));
+       }
+       else
+       {
+               appendPQExpBuffer(query,
+                                 "SELECT sequence_name, "
+                                 "0 as start_value, last_value, increment_by, "
+                                 "CASE WHEN increment_by > 0 AND max_value = %s THEN NULL "
+                                 "     WHEN increment_by < 0 AND max_value = -1 THEN NULL "
+                                 "     ELSE max_value "
+                                 "END AS max_value, "
+                                 "CASE WHEN increment_by > 0 AND min_value = 1 THEN NULL "
+                                 "     WHEN increment_by < 0 AND min_value = %s THEN NULL "
+                                 "     ELSE min_value "
+                                 "END AS min_value, "
+                                 "cache_value, is_cycled, is_called from %s",
+                                 bufx, bufm,
+                                 fmtId(tbinfo->dobj.name));
+       }
 
        res = PQexec(g_conn, query->data);
        check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
@@ -7602,28 +9602,28 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
        }
 #endif
 
-       last = PQgetvalue(res, 0, 1);
-       incby = PQgetvalue(res, 0, 2);
-       if (!PQgetisnull(res, 0, 3))
-               maxv = PQgetvalue(res, 0, 3);
+       startv = PQgetvalue(res, 0, 1);
+       last = PQgetvalue(res, 0, 2);
+       incby = PQgetvalue(res, 0, 3);
        if (!PQgetisnull(res, 0, 4))
-               minv = PQgetvalue(res, 0, 4);
-       cache = PQgetvalue(res, 0, 5);
-       cycled = (strcmp(PQgetvalue(res, 0, 6), "t") == 0);
-       called = (strcmp(PQgetvalue(res, 0, 7), "t") == 0);
+               maxv = PQgetvalue(res, 0, 4);
+       if (!PQgetisnull(res, 0, 5))
+               minv = PQgetvalue(res, 0, 5);
+       cache = PQgetvalue(res, 0, 6);
+       cycled = (strcmp(PQgetvalue(res, 0, 7), "t") == 0);
+       called = (strcmp(PQgetvalue(res, 0, 8), "t") == 0);
 
        /*
         * 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 OWNED
+        * BY 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);
 
@@ -7641,8 +9641,18 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
                                                  "CREATE SEQUENCE %s\n",
                                                  fmtId(tbinfo->dobj.name));
 
-               if (!called)
-                       appendPQExpBuffer(query, "    START WITH %s\n", last);
+               if (g_fout->remoteVersion >= 80400)
+                       appendPQExpBuffer(query, "    START WITH %s\n", startv);
+               else
+               {
+                       /*
+                        * Versions before 8.4 did not remember the true start value.  If
+                        * is_called is false then the sequence has never been incremented
+                        * so we can use last_val.  Otherwise punt and let it default.
+                        */
+                       if (!called)
+                               appendPQExpBuffer(query, "    START WITH %s\n", last);
+               }
 
                appendPQExpBuffer(query, "    INCREMENT BY %s\n", incby);
 
@@ -7670,32 +9680,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 && owning_tab->dobj.dump)
+                       {
+                               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"));
 
@@ -7709,16 +9744,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);
@@ -7788,6 +9813,13 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
                else
                        appendPQExpBuffer(query, " UPDATE");
        }
+       if (TRIGGER_FOR_TRUNCATE(tginfo->tgtype))
+       {
+               if (findx > 0)
+                       appendPQExpBuffer(query, " OR TRUNCATE");
+               else
+                       appendPQExpBuffer(query, " TRUNCATE");
+       }
        appendPQExpBuffer(query, " ON %s\n",
                                          fmtId(tbinfo->dobj.name));
 
@@ -7828,8 +9860,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 (;;)
@@ -7854,18 +9885,18 @@ 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, '\'');
@@ -7875,11 +9906,27 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
        }
        appendPQExpBuffer(query, ");\n");
 
-       if (!tginfo->tgenabled)
+       if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
        {
                appendPQExpBuffer(query, "\nALTER TABLE %s ",
                                                  fmtId(tbinfo->dobj.name));
-               appendPQExpBuffer(query, "DISABLE TRIGGER %s;\n",
+               switch (tginfo->tgenabled)
+               {
+                       case 'D':
+                       case 'f':
+                               appendPQExpBuffer(query, "DISABLE");
+                               break;
+                       case 'A':
+                               appendPQExpBuffer(query, "ENABLE ALWAYS");
+                               break;
+                       case 'R':
+                               appendPQExpBuffer(query, "ENABLE REPLICA");
+                               break;
+                       default:
+                               appendPQExpBuffer(query, "ENABLE");
+                               break;
+               }
+               appendPQExpBuffer(query, " TRIGGER %s;\n",
                                                  fmtId(tginfo->dobj.name));
        }
 
@@ -7919,10 +9966,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;
 
        /*
@@ -7960,7 +10005,7 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
 
        if (PQntuples(res) != 1)
        {
-               write_msg(NULL, "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned",
+               write_msg(NULL, "query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned\n",
                                  rinfo->dobj.name, tbinfo->dobj.name);
                exit_nicely();
        }
@@ -7968,6 +10013,33 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
        printfPQExpBuffer(cmd, "%s\n", PQgetvalue(res, 0, 0));
 
        /*
+        * Add the command to alter the rules replication firing semantics if it
+        * differs from the default.
+        */
+       if (rinfo->ev_enabled != 'O')
+       {
+               appendPQExpBuffer(cmd, "ALTER TABLE %s.",
+                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
+               appendPQExpBuffer(cmd, "%s ",
+                                                 fmtId(tbinfo->dobj.name));
+               switch (rinfo->ev_enabled)
+               {
+                       case 'A':
+                               appendPQExpBuffer(cmd, "ENABLE ALWAYS RULE %s;\n",
+                                                                 fmtId(rinfo->dobj.name));
+                               break;
+                       case 'R':
+                               appendPQExpBuffer(cmd, "ENABLE REPLICA RULE %s;\n",
+                                                                 fmtId(rinfo->dobj.name));
+                               break;
+                       case 'D':
+                               appendPQExpBuffer(cmd, "DISABLE RULE %s;\n",
+                                                                 fmtId(rinfo->dobj.name));
+                               break;
+               }
+       }
+
+       /*
         * DROP must be fully qualified in case same name appears in pg_catalog
         */
        appendPQExpBuffer(delcmd, "DROP RULE %s ",
@@ -8216,7 +10288,7 @@ getFormattedTypeName(Oid oid, OidOptions opts)
        ntups = PQntuples(res);
        if (ntups != 1)
        {
-               write_msg(NULL, "query yielded %d rows instead of one: %s\n",
+               write_msg(NULL, "query returned %d rows instead of one: %s\n",
                                  ntups, query->data);
                exit_nicely();
        }