]> granicus.if.org Git - postgresql/blobdiff - src/bin/pg_dump/pg_dump.c
Un-break pg_dump for pre-8.3 source servers.
[postgresql] / src / bin / pg_dump / pg_dump.c
index 0ffb3725e01ac0dbb5910216e2d1d2b72839af73..be25e94cb2007bdefe5ebf700ed6b3870002c891 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-2018, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2019, 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
@@ -33,6 +33,7 @@
 
 #include <unistd.h>
 #include <ctype.h>
+#include <limits.h>
 #ifdef HAVE_TERMIOS_H
 #include <termios.h>
 #endif
 #include "access/attnum.h"
 #include "access/sysattr.h"
 #include "access/transam.h"
-#include "catalog/pg_aggregate.h"
-#include "catalog/pg_am.h"
-#include "catalog/pg_attribute.h"
-#include "catalog/pg_cast.h"
-#include "catalog/pg_class.h"
-#include "catalog/pg_default_acl.h"
-#include "catalog/pg_largeobject.h"
-#include "catalog/pg_largeobject_metadata.h"
-#include "catalog/pg_proc.h"
-#include "catalog/pg_trigger.h"
-#include "catalog/pg_type.h"
+#include "catalog/pg_aggregate_d.h"
+#include "catalog/pg_am_d.h"
+#include "catalog/pg_attribute_d.h"
+#include "catalog/pg_cast_d.h"
+#include "catalog/pg_class_d.h"
+#include "catalog/pg_default_acl_d.h"
+#include "catalog/pg_largeobject_d.h"
+#include "catalog/pg_largeobject_metadata_d.h"
+#include "catalog/pg_proc_d.h"
+#include "catalog/pg_trigger_d.h"
+#include "catalog/pg_type_d.h"
 #include "libpq/libpq-fs.h"
+#include "storage/block.h"
 
 #include "dumputils.h"
 #include "parallel.h"
 #include "pg_backup_db.h"
 #include "pg_backup_utils.h"
 #include "pg_dump.h"
+#include "fe_utils/connect.h"
 #include "fe_utils/string_utils.h"
 
 
@@ -89,8 +92,6 @@ typedef enum OidOptions
 } OidOptions;
 
 /* global decls */
-bool           g_verbose;                      /* User wants verbose narration of our
-                                                                * activities. */
 static bool dosync = true;             /* Issue fsync() to make dump durable on disk. */
 
 /* subquery used to convert user ID (eg, datdba) to user name */
@@ -132,34 +133,51 @@ char              g_comment_end[10];
 
 static const CatalogId nilCatalogId = {0, 0};
 
+/* override for standard extra_float_digits setting */
+static bool have_extra_float_digits = false;
+static int     extra_float_digits;
+
+/*
+ * The default number of rows per INSERT when
+ * --inserts is specified without --rows-per-insert
+ */
+#define DUMP_DEFAULT_ROWS_PER_INSERT 1
+
+/*
+ * Macro for producing quoted, schema-qualified name of a dumpable object.
+ */
+#define fmtQualifiedDumpable(obj) \
+       fmtQualifiedId((obj)->dobj.namespace->dobj.name, \
+                                  (obj)->dobj.name)
+
 static void help(const char *progname);
 static void setup_connection(Archive *AH,
-                                const char *dumpencoding, const char *dumpsnapshot,
-                                char *use_role);
+                                                        const char *dumpencoding, const char *dumpsnapshot,
+                                                        char *use_role);
 static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
 static void expand_schema_name_patterns(Archive *fout,
-                                                       SimpleStringList *patterns,
-                                                       SimpleOidList *oids,
-                                                       bool strict_names);
+                                                                               SimpleStringList *patterns,
+                                                                               SimpleOidList *oids,
+                                                                               bool strict_names);
 static void expand_table_name_patterns(Archive *fout,
-                                                  SimpleStringList *patterns,
-                                                  SimpleOidList *oids,
-                                                  bool strict_names);
+                                                                          SimpleStringList *patterns,
+                                                                          SimpleOidList *oids,
+                                                                          bool strict_names);
 static NamespaceInfo *findNamespace(Archive *fout, Oid nsoid);
 static void dumpTableData(Archive *fout, TableDataInfo *tdinfo);
 static void refreshMatViewData(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);
-static int findComments(Archive *fout, Oid classoid, Oid objoid,
-                        CommentItem **items);
+static void dumpComment(Archive *fout, const char *type, const char *name,
+                                               const char *namespace, const char *owner,
+                                               CatalogId catalogId, int subid, DumpId dumpId);
+static int     findComments(Archive *fout, Oid classoid, Oid objoid,
+                                                CommentItem **items);
 static int     collectComments(Archive *fout, CommentItem **items);
-static void dumpSecLabel(Archive *fout, const char *target,
-                        const char *namespace, const char *owner,
-                        CatalogId catalogId, int subid, DumpId dumpId);
-static int findSecLabels(Archive *fout, Oid classoid, Oid objoid,
-                         SecLabelItem **items);
+static void dumpSecLabel(Archive *fout, const char *type, const char *name,
+                                                const char *namespace, const char *owner,
+                                                CatalogId catalogId, int subid, DumpId dumpId);
+static int     findSecLabels(Archive *fout, Oid classoid, Oid objoid,
+                                                 SecLabelItem **items);
 static int     collectSecLabels(Archive *fout, SecLabelItem **items);
 static void dumpDumpableObject(Archive *fout, DumpableObject *dobj);
 static void dumpNamespace(Archive *fout, NamespaceInfo *nspinfo);
@@ -204,45 +222,44 @@ static void dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo);
 static void dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo);
 static void dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo);
 static void dumpUserMappings(Archive *fout,
-                                const char *servername, const char *namespace,
-                                const char *owner, CatalogId catalogId, DumpId dumpId);
+                                                        const char *servername, const char *namespace,
+                                                        const char *owner, CatalogId catalogId, DumpId dumpId);
 static void dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo);
 
 static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
-               const char *type, const char *name, const char *subname,
-               const char *tag, const char *nspname, const char *owner,
-               const char *acls, const char *racls,
-               const char *initacls, const char *initracls);
+                                       const char *type, const char *name, const char *subname,
+                                       const char *nspname, const char *owner,
+                                       const char *acls, const char *racls,
+                                       const char *initacls, const char *initracls);
 
 static void getDependencies(Archive *fout);
 static void BuildArchiveDependencies(Archive *fout);
 static void findDumpableDependencies(ArchiveHandle *AH, DumpableObject *dobj,
-                                                DumpId **dependencies, int *nDeps, int *allocDeps);
+                                                                        DumpId **dependencies, int *nDeps, int *allocDeps);
 
 static DumpableObject *createBoundaryObjects(void);
 static void addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
-                                               DumpableObject *boundaryObjs);
+                                                                       DumpableObject *boundaryObjs);
 
 static void getDomainConstraints(Archive *fout, TypeInfo *tyinfo);
-static void getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, bool oids, char relkind);
-static void makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo, bool oids);
+static void getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, char relkind);
+static void makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo);
 static void buildMatViewRefreshDependencies(Archive *fout);
 static void getTableDataFKConstraints(void);
 static char *format_function_arguments(FuncInfo *finfo, char *funcargs,
-                                                 bool is_agg);
+                                                                          bool is_agg);
 static char *format_function_arguments_old(Archive *fout,
-                                                         FuncInfo *finfo, int nallargs,
-                                                         char **allargtypes,
-                                                         char **argmodes,
-                                                         char **argnames);
+                                                                                  FuncInfo *finfo, int nallargs,
+                                                                                  char **allargtypes,
+                                                                                  char **argmodes,
+                                                                                  char **argnames);
 static char *format_function_signature(Archive *fout,
-                                                 FuncInfo *finfo, bool honor_quotes);
+                                                                          FuncInfo *finfo, bool honor_quotes);
 static char *convertRegProcReference(Archive *fout,
-                                               const char *proc);
-static char *convertOperatorReference(Archive *fout, const char *opr);
+                                                                        const char *proc);
+static char *getFormattedOperatorName(Archive *fout, const char *oproid);
 static char *convertTSFunction(Archive *fout, Oid funcOid);
-static Oid     findLastBuiltinOid_V71(Archive *fout, const char *);
-static void selectSourceSchema(Archive *fout, const char *schemaName);
+static Oid     findLastBuiltinOid_V71(Archive *fout);
 static char *getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts);
 static void getBlobs(Archive *fout);
 static void dumpBlob(Archive *fout, BlobInfo *binfo);
@@ -253,26 +270,29 @@ static void dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo);
 static void dumpSubscription(Archive *fout, SubscriptionInfo *subinfo);
 static void dumpDatabase(Archive *AH);
 static void dumpDatabaseConfig(Archive *AH, PQExpBuffer outbuf,
-                                  const char *dbname, Oid dboid);
+                                                          const char *dbname, Oid dboid);
 static void dumpEncoding(Archive *AH);
 static void dumpStdStrings(Archive *AH);
+static void dumpSearchPath(Archive *AH);
 static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
-                                                                                PQExpBuffer upgrade_buffer,
-                                                                                Oid pg_type_oid,
-                                                                                bool force_array_type);
+                                                                                                        PQExpBuffer upgrade_buffer,
+                                                                                                        Oid pg_type_oid,
+                                                                                                        bool force_array_type);
 static bool binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
-                                                                               PQExpBuffer upgrade_buffer, Oid pg_rel_oid);
+                                                                                                       PQExpBuffer upgrade_buffer, Oid pg_rel_oid);
 static void binary_upgrade_set_pg_class_oids(Archive *fout,
-                                                                PQExpBuffer upgrade_buffer,
-                                                                Oid pg_class_oid, bool is_index);
+                                                                                        PQExpBuffer upgrade_buffer,
+                                                                                        Oid pg_class_oid, bool is_index);
 static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
-                                                               DumpableObject *dobj,
-                                                               const char *objlabel);
+                                                                                       DumpableObject *dobj,
+                                                                                       const char *objtype,
+                                                                                       const char *objname,
+                                                                                       const char *objnamespace);
 static const char *getAttrName(int attrnum, TableInfo *tblInfo);
 static const char *fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer);
 static bool nonemptyReloptions(const char *reloptions);
 static void appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
-                                               const char *prefix, Archive *fout);
+                                                                       const char *prefix, Archive *fout);
 static char *get_synchronized_snapshot(Archive *fout);
 static void setupDumpWorker(Archive *AHX);
 static TableInfo *getRootTableInfo(TableInfo *tbinfo);
@@ -291,11 +311,14 @@ main(int argc, char **argv)
        DumpableObject *boundaryObjs;
        int                     i;
        int                     optindex;
+       char       *endptr;
        RestoreOptions *ropt;
        Archive    *fout;                       /* the script file */
+       bool            g_verbose = false;
        const char *dumpencoding = NULL;
        const char *dumpsnapshot = NULL;
        char       *use_role = NULL;
+       long            rowsPerInsert;
        int                     numWorkers = 1;
        trivalue        prompt_password = TRI_DEFAULT;
        int                     compressLevel = -1;
@@ -317,7 +340,6 @@ main(int argc, char **argv)
                {"host", required_argument, NULL, 'h'},
                {"jobs", 1, NULL, 'j'},
                {"no-reconnect", no_argument, NULL, 'R'},
-               {"oids", no_argument, NULL, 'o'},
                {"no-owner", no_argument, NULL, 'O'},
                {"port", required_argument, NULL, 'p'},
                {"schema", required_argument, NULL, 'n'},
@@ -347,8 +369,9 @@ main(int argc, char **argv)
                {"disable-triggers", no_argument, &dopt.disable_triggers, 1},
                {"enable-row-security", no_argument, &dopt.enable_row_security, 1},
                {"exclude-table-data", required_argument, NULL, 4},
+               {"extra-float-digits", required_argument, NULL, 8},
                {"if-exists", no_argument, &dopt.if_exists, 1},
-               {"inserts", no_argument, &dopt.dump_inserts, 1},
+               {"inserts", no_argument, NULL, 9},
                {"lock-wait-timeout", required_argument, NULL, 2},
                {"no-tablespaces", no_argument, &dopt.outputNoTablespaces, 1},
                {"quote-all-identifiers", no_argument, &quote_all_identifiers, 1},
@@ -366,10 +389,14 @@ main(int argc, char **argv)
                {"no-unlogged-table-data", no_argument, &dopt.no_unlogged_table_data, 1},
                {"no-subscriptions", no_argument, &dopt.no_subscriptions, 1},
                {"no-sync", no_argument, NULL, 7},
+               {"on-conflict-do-nothing", no_argument, &dopt.do_nothing, 1},
+               {"rows-per-insert", required_argument, NULL, 10},
 
                {NULL, 0, NULL, 0}
        };
 
+       pg_logging_init(argv[0]);
+       pg_logging_set_level(PG_LOG_WARNING);
        set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
 
        /*
@@ -378,8 +405,6 @@ main(int argc, char **argv)
         */
        init_parallel_dump_utils();
 
-       g_verbose = false;
-
        strcpy(g_comment_start, "-- ");
        g_comment_end[0] = '\0';
        strcpy(g_opaque_type, "opaque");
@@ -402,7 +427,7 @@ main(int argc, char **argv)
 
        InitDumpOptions(&dopt);
 
-       while ((c = getopt_long(argc, argv, "abBcCd:E:f:F:h:j:n:N:oOp:RsS:t:T:U:vwWxZ:",
+       while ((c = getopt_long(argc, argv, "abBcCd:E:f:F:h:j:n:N:Op:RsS:t:T:U:vwWxZ:",
                                                        long_options, &optindex)) != -1)
        {
                switch (c)
@@ -460,10 +485,6 @@ main(int argc, char **argv)
                                simple_string_list_append(&schema_exclude_patterns, optarg);
                                break;
 
-                       case 'o':                       /* Dump oids */
-                               dopt.oids = true;
-                               break;
-
                        case 'O':                       /* Don't reconnect to match owner */
                                dopt.outputNoOwner = 1;
                                break;
@@ -499,6 +520,7 @@ main(int argc, char **argv)
 
                        case 'v':                       /* verbose */
                                g_verbose = true;
+                               pg_logging_set_level(PG_LOG_INFO);
                                break;
 
                        case 'w':
@@ -517,7 +539,7 @@ main(int argc, char **argv)
                                compressLevel = atoi(optarg);
                                if (compressLevel < 0 || compressLevel > 9)
                                {
-                                       write_msg(NULL, "compression level must be in range 0..9\n");
+                                       pg_log_error("compression level must be in range 0..9");
                                        exit_nicely(1);
                                }
                                break;
@@ -550,6 +572,41 @@ main(int argc, char **argv)
                                dosync = false;
                                break;
 
+                       case 8:
+                               have_extra_float_digits = true;
+                               extra_float_digits = atoi(optarg);
+                               if (extra_float_digits < -15 || extra_float_digits > 3)
+                               {
+                                       pg_log_error("extra_float_digits must be in range -15..3");
+                                       exit_nicely(1);
+                               }
+                               break;
+
+                       case 9:                         /* inserts */
+
+                               /*
+                                * dump_inserts also stores --rows-per-insert, careful not to
+                                * overwrite that.
+                                */
+                               if (dopt.dump_inserts == 0)
+                                       dopt.dump_inserts = DUMP_DEFAULT_ROWS_PER_INSERT;
+                               break;
+
+                       case 10:                        /* rows per insert */
+                               errno = 0;
+                               rowsPerInsert = strtol(optarg, &endptr, 10);
+
+                               if (endptr == optarg || *endptr != '\0' ||
+                                       rowsPerInsert <= 0 || rowsPerInsert > INT_MAX ||
+                                       errno == ERANGE)
+                               {
+                                       pg_log_error("rows-per-insert must be in range %d..%d",
+                                                                1, INT_MAX);
+                                       exit_nicely(1);
+                               }
+                               dopt.dump_inserts = (int) rowsPerInsert;
+                               break;
+
                        default:
                                fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
                                exit_nicely(1);
@@ -566,16 +623,16 @@ main(int argc, char **argv)
        /* Complain if any arguments remain */
        if (optind < argc)
        {
-               fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
-                               progname, argv[optind]);
+               pg_log_error("too many command-line arguments (first is \"%s\")",
+                                        argv[optind]);
                fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                                progname);
                exit_nicely(1);
        }
 
        /* --column-inserts implies --inserts */
-       if (dopt.column_inserts)
-               dopt.dump_inserts = 1;
+       if (dopt.column_inserts && dopt.dump_inserts == 0)
+               dopt.dump_inserts = DUMP_DEFAULT_ROWS_PER_INSERT;
 
        /*
         * Binary upgrade mode implies dumping sequence data even in schema-only
@@ -587,25 +644,25 @@ main(int argc, char **argv)
 
        if (dopt.dataOnly && dopt.schemaOnly)
        {
-               write_msg(NULL, "options -s/--schema-only and -a/--data-only cannot be used together\n");
+               pg_log_error("options -s/--schema-only and -a/--data-only cannot be used together");
                exit_nicely(1);
        }
 
        if (dopt.dataOnly && dopt.outputClean)
        {
-               write_msg(NULL, "options -c/--clean and -a/--data-only cannot be used together\n");
-               exit_nicely(1);
-       }
-
-       if (dopt.dump_inserts && dopt.oids)
-       {
-               write_msg(NULL, "options --inserts/--column-inserts and -o/--oids cannot be used together\n");
-               write_msg(NULL, "(The INSERT command cannot set OIDs.)\n");
+               pg_log_error("options -c/--clean and -a/--data-only cannot be used together");
                exit_nicely(1);
        }
 
        if (dopt.if_exists && !dopt.outputClean)
-               exit_horribly(NULL, "option --if-exists requires option -c/--clean\n");
+               fatal("option --if-exists requires option -c/--clean");
+
+       /*
+        * --inserts are already implied above if --column-inserts or
+        * --rows-per-insert were specified.
+        */
+       if (dopt.do_nothing && dopt.dump_inserts == 0)
+               fatal("option --on-conflict-do-nothing requires option --inserts, --rows-per-insert, or --column-inserts");
 
        /* Identify archive format to emit */
        archiveFormat = parseArchiveFormat(format, &archiveMode);
@@ -627,8 +684,7 @@ main(int argc, char **argv)
 
 #ifndef HAVE_LIBZ
        if (compressLevel != 0)
-               write_msg(NULL, "WARNING: requested compression not available in this "
-                                 "installation -- archive will be uncompressed\n");
+               pg_log_warning("requested compression not available in this installation -- archive will be uncompressed");
        compressLevel = 0;
 #endif
 
@@ -649,11 +705,11 @@ main(int argc, char **argv)
                || numWorkers > MAXIMUM_WAIT_OBJECTS
 #endif
                )
-               exit_horribly(NULL, "invalid number of parallel jobs\n");
+               fatal("invalid number of parallel jobs");
 
        /* Parallel backup only in the directory archive format so far */
        if (archiveFormat != archDirectory && numWorkers > 1)
-               exit_horribly(NULL, "parallel backup only supported by the directory format\n");
+               fatal("parallel backup only supported by the directory format");
 
        /* Open the output file */
        fout = CreateArchive(filename, archiveFormat, compressLevel, dosync,
@@ -668,6 +724,7 @@ main(int argc, char **argv)
        /* Let the archiver know how noisy to be */
        fout->verbose = g_verbose;
 
+
        /*
         * We allow the server to be back to 8.0, and up to any minor release of
         * our own major version.  (See also version check in pg_dumpall.c.)
@@ -707,15 +764,13 @@ main(int argc, char **argv)
        /* check the version for the synchronized snapshots feature */
        if (numWorkers > 1 && fout->remoteVersion < 90200
                && !dopt.no_synchronized_snapshots)
-               exit_horribly(NULL,
-                                         "Synchronized snapshots are not supported by this server version.\n"
-                                         "Run with --no-synchronized-snapshots instead if you do not need\n"
-                                         "synchronized snapshots.\n");
+               fatal("Synchronized snapshots are not supported by this server version.\n"
+                         "Run with --no-synchronized-snapshots instead if you do not need\n"
+                         "synchronized snapshots.");
 
        /* check the version when a snapshot is explicitly specified by user */
        if (dumpsnapshot && fout->remoteVersion < 90200)
-               exit_horribly(NULL,
-                                         "Exported snapshots are not supported by this server version.\n");
+               fatal("Exported snapshots are not supported by this server version.");
 
        /*
         * Find the last built-in OID, if needed (prior to 8.1)
@@ -723,13 +778,11 @@ main(int argc, char **argv)
         * With 8.1 and above, we can just use FirstNormalObjectId - 1.
         */
        if (fout->remoteVersion < 80100)
-               g_last_builtin_oid = findLastBuiltinOid_V71(fout,
-                                                                                                       PQdb(GetConnection(fout)));
+               g_last_builtin_oid = findLastBuiltinOid_V71(fout);
        else
                g_last_builtin_oid = FirstNormalObjectId - 1;
 
-       if (g_verbose)
-               write_msg(NULL, "last built-in OID is %u\n", g_last_builtin_oid);
+       pg_log_info("last built-in OID is %u", g_last_builtin_oid);
 
        /* Expand schema selection patterns into OID lists */
        if (schema_include_patterns.head != NULL)
@@ -738,7 +791,7 @@ main(int argc, char **argv)
                                                                        &schema_include_oids,
                                                                        strict_names);
                if (schema_include_oids.head == NULL)
-                       exit_horribly(NULL, "no matching schemas were found\n");
+                       fatal("no matching schemas were found");
        }
        expand_schema_name_patterns(fout, &schema_exclude_patterns,
                                                                &schema_exclude_oids,
@@ -752,7 +805,7 @@ main(int argc, char **argv)
                                                                   &table_include_oids,
                                                                   strict_names);
                if (table_include_oids.head == NULL)
-                       exit_horribly(NULL, "no matching tables were found\n");
+                       fatal("no matching tables were found");
        }
        expand_table_name_patterns(fout, &table_exclude_patterns,
                                                           &table_exclude_oids,
@@ -787,19 +840,19 @@ main(int argc, char **argv)
 
        if (!dopt.schemaOnly)
        {
-               getTableData(&dopt, tblinfo, numTables, dopt.oids, 0);
+               getTableData(&dopt, tblinfo, numTables, 0);
                buildMatViewRefreshDependencies(fout);
                if (dopt.dataOnly)
                        getTableDataFKConstraints();
        }
 
        if (dopt.schemaOnly && dopt.sequence_data)
-               getTableData(&dopt, tblinfo, numTables, dopt.oids, RELKIND_SEQUENCE);
+               getTableData(&dopt, tblinfo, numTables, RELKIND_SEQUENCE);
 
        /*
         * In binary-upgrade mode, we do not have to worry about the actual blob
         * data or the associated metadata that resides in the pg_largeobject and
-        * pg_largeobject_metadata tables, respectivly.
+        * pg_largeobject_metadata tables, respectively.
         *
         * However, we do need to collect blob information as there may be
         * comments or other information on blobs that we do need to dump out.
@@ -832,10 +885,6 @@ main(int argc, char **argv)
         */
        sortDumpableObjectsByTypeName(dobjs, numObjs);
 
-       /* If we do a parallel dump, we want the largest tables to go first */
-       if (archiveFormat == archDirectory && numWorkers > 1)
-               sortDataAndIndexObjectsBySize(dobjs, numObjs);
-
        sortDumpableObjects(dobjs, numObjs,
                                                boundaryObjs[0].dumpId, boundaryObjs[1].dumpId);
 
@@ -844,9 +893,10 @@ main(int argc, char **argv)
         * order.
         */
 
-       /* First the special ENCODING and STDSTRINGS entries. */
+       /* First the special ENCODING, STDSTRINGS, and SEARCHPATH entries. */
        dumpEncoding(fout);
        dumpStdStrings(fout);
+       dumpSearchPath(fout);
 
        /* The database items are always next, unless we don't want them at all */
        if (dopt.outputCreateDB)
@@ -952,7 +1002,6 @@ help(const char *progname)
        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 in\n"
                         "                               plain-text format\n"));
        printf(_("  -s, --schema-only            dump only the schema, no data\n"));
@@ -967,8 +1016,10 @@ help(const char *progname)
        printf(_("  --enable-row-security        enable row security (dump only content user has\n"
                         "                               access to)\n"));
        printf(_("  --exclude-table-data=TABLE   do NOT dump data for the named table(s)\n"));
+       printf(_("  --extra-float-digits=NUM     override default setting for extra_float_digits\n"));
        printf(_("  --if-exists                  use IF EXISTS when dropping objects\n"));
        printf(_("  --inserts                    dump data as INSERT commands, rather than COPY\n"));
+       printf(_("  --load-via-partition-root    load partitions via the root table\n"));
        printf(_("  --no-comments                do not dump comments\n"));
        printf(_("  --no-publications            do not dump publications\n"));
        printf(_("  --no-security-labels         do not dump security label assignments\n"));
@@ -976,8 +1027,9 @@ help(const char *progname)
        printf(_("  --no-synchronized-snapshots  do not use synchronized snapshots in parallel jobs\n"));
        printf(_("  --no-tablespaces             do not dump tablespace assignments\n"));
        printf(_("  --no-unlogged-table-data     do not dump unlogged table data\n"));
+       printf(_("  --on-conflict-do-nothing     add ON CONFLICT DO NOTHING to INSERT commands\n"));
        printf(_("  --quote-all-identifiers      quote all identifiers, even if not key words\n"));
-       printf(_("  --load-via-partition-root    load partitions via the root table\n"));
+       printf(_("  --rows-per-insert=NROWS      number of rows per INSERT; implies --inserts\n"));
        printf(_("  --section=SECTION            dump named section (pre-data, data, or post-data)\n"));
        printf(_("  --serializable-deferrable    wait until the dump can run without anomalies\n"));
        printf(_("  --snapshot=SNAPSHOT          use given snapshot for the dump\n"));
@@ -998,7 +1050,7 @@ help(const char *progname)
 
        printf(_("\nIf no database name is supplied, then the PGDATABASE environment\n"
                         "variable value is used.\n\n"));
-       printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
+       printf(_("Report bugs to <pgsql-bugs@lists.postgresql.org>.\n"));
 }
 
 static void
@@ -1009,14 +1061,16 @@ setup_connection(Archive *AH, const char *dumpencoding,
        PGconn     *conn = GetConnection(AH);
        const char *std_strings;
 
+       PQclear(ExecuteSqlQueryForSingleRow(AH, ALWAYS_SECURE_SEARCH_PATH_SQL));
+
        /*
         * Set the client encoding if requested.
         */
        if (dumpencoding)
        {
                if (PQsetClientEncoding(conn, dumpencoding) < 0)
-                       exit_horribly(NULL, "invalid client encoding \"%s\" specified\n",
-                                                 dumpencoding);
+                       fatal("invalid client encoding \"%s\" specified",
+                                 dumpencoding);
        }
 
        /*
@@ -1058,10 +1112,20 @@ setup_connection(Archive *AH, const char *dumpencoding,
                ExecuteSqlStatement(AH, "SET INTERVALSTYLE = POSTGRES");
 
        /*
-        * Set extra_float_digits so that we can dump float data exactly (given
-        * correctly implemented float I/O code, anyway)
+        * Use an explicitly specified extra_float_digits if it has been provided.
+        * Otherwise, set extra_float_digits so that we can dump float data
+        * exactly (given correctly implemented float I/O code, anyway).
         */
-       if (AH->remoteVersion >= 90000)
+       if (have_extra_float_digits)
+       {
+               PQExpBuffer q = createPQExpBuffer();
+
+               appendPQExpBuffer(q, "SET extra_float_digits TO %d",
+                                                 extra_float_digits);
+               ExecuteSqlStatement(AH, q->data);
+               destroyPQExpBuffer(q);
+       }
+       else if (AH->remoteVersion >= 90000)
                ExecuteSqlStatement(AH, "SET extra_float_digits TO 3");
        else
                ExecuteSqlStatement(AH, "SET extra_float_digits TO 2");
@@ -1141,7 +1205,7 @@ setup_connection(Archive *AH, const char *dumpencoding,
        {
                PQExpBuffer query = createPQExpBuffer();
 
-               appendPQExpBuffer(query, "SET TRANSACTION SNAPSHOT ");
+               appendPQExpBufferStr(query, "SET TRANSACTION SNAPSHOT ");
                appendStringLiteralConn(query, AH->sync_snapshot_id, conn);
                ExecuteSqlStatement(AH, query->data);
                destroyPQExpBuffer(query);
@@ -1151,10 +1215,9 @@ setup_connection(Archive *AH, const char *dumpencoding,
                         !dopt->no_synchronized_snapshots)
        {
                if (AH->isStandby && AH->remoteVersion < 100000)
-                       exit_horribly(NULL,
-                                                 "Synchronized snapshots on standby servers are not supported by this server version.\n"
-                                                 "Run with --no-synchronized-snapshots instead if you do not need\n"
-                                                 "synchronized snapshots.\n");
+                       fatal("Synchronized snapshots on standby servers are not supported by this server version.\n"
+                                 "Run with --no-synchronized-snapshots instead if you do not need\n"
+                                 "synchronized snapshots.");
 
 
                AH->sync_snapshot_id = get_synchronized_snapshot(AH);
@@ -1221,7 +1284,7 @@ parseArchiveFormat(const char *format, ArchiveMode *mode)
        else if (pg_strcasecmp(format, "tar") == 0)
                archiveFormat = archTar;
        else
-               exit_horribly(NULL, "invalid output format \"%s\" specified\n", format);
+               fatal("invalid output format \"%s\" specified", format);
        return archiveFormat;
 }
 
@@ -1252,14 +1315,14 @@ expand_schema_name_patterns(Archive *fout,
 
        for (cell = patterns->head; cell; cell = cell->next)
        {
-               appendPQExpBuffer(query,
-                                                 "SELECT oid FROM pg_catalog.pg_namespace n\n");
+               appendPQExpBufferStr(query,
+                                                        "SELECT oid FROM pg_catalog.pg_namespace n\n");
                processSQLNamePattern(GetConnection(fout), query, cell->val, false,
                                                          false, NULL, "n.nspname", NULL, NULL);
 
                res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
                if (strict_names && PQntuples(res) == 0)
-                       exit_horribly(NULL, "no matching schemas were found for pattern \"%s\"\n", cell->val);
+                       fatal("no matching schemas were found for pattern \"%s\"", cell->val);
 
                for (i = 0; i < PQntuples(res); i++)
                {
@@ -1275,7 +1338,8 @@ expand_schema_name_patterns(Archive *fout,
 
 /*
  * Find the OIDs of all tables matching the given list of patterns,
- * and append them to the given OID list.
+ * and append them to the given OID list. See also expand_dbname_patterns()
+ * in pg_dumpall.c
  */
 static void
 expand_table_name_patterns(Archive *fout,
@@ -1299,11 +1363,18 @@ expand_table_name_patterns(Archive *fout,
 
        for (cell = patterns->head; cell; cell = cell->next)
        {
+               /*
+                * Query must remain ABSOLUTELY devoid of unqualified names.  This
+                * would be unnecessary given a pg_table_is_visible() variant taking a
+                * search_path argument.
+                */
                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', '%c', '%c', '%c')\n",
+                                                 "\n     LEFT JOIN pg_catalog.pg_namespace n"
+                                                 "\n     ON n.oid OPERATOR(pg_catalog.=) c.relnamespace"
+                                                 "\nWHERE c.relkind OPERATOR(pg_catalog.=) ANY"
+                                                 "\n    (array['%c', '%c', '%c', '%c', '%c', '%c'])\n",
                                                  RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
                                                  RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE,
                                                  RELKIND_PARTITIONED_TABLE);
@@ -1311,9 +1382,12 @@ expand_table_name_patterns(Archive *fout,
                                                          false, "n.nspname", "c.relname", NULL,
                                                          "pg_catalog.pg_table_is_visible(c.oid)");
 
+               ExecuteSqlStatement(fout, "RESET search_path");
                res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+               PQclear(ExecuteSqlQueryForSingleRow(fout,
+                                                                                       ALWAYS_SECURE_SEARCH_PATH_SQL));
                if (strict_names && PQntuples(res) == 0)
-                       exit_horribly(NULL, "no matching tables were found for pattern \"%s\"\n", cell->val);
+                       fatal("no matching tables were found for pattern \"%s\"", cell->val);
 
                for (i = 0; i < PQntuples(res); i++)
                {
@@ -1714,8 +1788,6 @@ dumpTableData_copy(Archive *fout, void *dcontext)
        TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
        TableInfo  *tbinfo = tdinfo->tdtable;
        const char *classname = tbinfo->dobj.name;
-       const bool      hasoids = tbinfo->hasoids;
-       const bool      oids = tdinfo->oids;
        PQExpBuffer q = createPQExpBuffer();
 
        /*
@@ -1729,17 +1801,8 @@ dumpTableData_copy(Archive *fout, void *dcontext)
        char       *copybuf;
        const char *column_list;
 
-       if (g_verbose)
-               write_msg(NULL, "dumping contents of table \"%s.%s\"\n",
-                                 tbinfo->dobj.namespace->dobj.name, classname);
-
-       /*
-        * Make sure we are in proper schema.  We will qualify the table name
-        * below anyway (in case its name conflicts with a pg_catalog table); but
-        * this ensures reproducible results in case the table contains regproc,
-        * regclass, etc columns.
-        */
-       selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
+       pg_log_info("dumping contents of table \"%s.%s\"",
+                               tbinfo->dobj.namespace->dobj.name, classname);
 
        /*
         * Specify the column list explicitly so that we have no possibility of
@@ -1749,15 +1812,7 @@ dumpTableData_copy(Archive *fout, void *dcontext)
         */
        column_list = fmtCopyColumnList(tbinfo, clistBuf);
 
-       if (oids && hasoids)
-       {
-               appendPQExpBuffer(q, "COPY %s %s WITH OIDS TO stdout;",
-                                                 fmtQualifiedId(fout->remoteVersion,
-                                                                                tbinfo->dobj.namespace->dobj.name,
-                                                                                classname),
-                                                 column_list);
-       }
-       else if (tdinfo->filtercond)
+       if (tdinfo->filtercond)
        {
                /* Note: this syntax is only supported in 8.2 and up */
                appendPQExpBufferStr(q, "COPY (SELECT ");
@@ -1770,17 +1825,13 @@ dumpTableData_copy(Archive *fout, void *dcontext)
                else
                        appendPQExpBufferStr(q, "* ");
                appendPQExpBuffer(q, "FROM %s %s) TO stdout;",
-                                                 fmtQualifiedId(fout->remoteVersion,
-                                                                                tbinfo->dobj.namespace->dobj.name,
-                                                                                classname),
+                                                 fmtQualifiedDumpable(tbinfo),
                                                  tdinfo->filtercond);
        }
        else
        {
                appendPQExpBuffer(q, "COPY %s %s TO stdout;",
-                                                 fmtQualifiedId(fout->remoteVersion,
-                                                                                tbinfo->dobj.namespace->dobj.name,
-                                                                                classname),
+                                                 fmtQualifiedDumpable(tbinfo),
                                                  column_list);
        }
        res = ExecuteSqlQuery(fout, q->data, PGRES_COPY_OUT);
@@ -1851,9 +1902,9 @@ dumpTableData_copy(Archive *fout, void *dcontext)
        if (ret == -2)
        {
                /* 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(conn));
-               write_msg(NULL, "The command was: %s\n", q->data);
+               pg_log_error("Dumping the contents of table \"%s\" failed: PQgetCopyData() failed.", classname);
+               pg_log_error("Error message from server: %s", PQerrorMessage(conn));
+               pg_log_error("The command was: %s", q->data);
                exit_nicely(1);
        }
 
@@ -1861,17 +1912,17 @@ dumpTableData_copy(Archive *fout, void *dcontext)
        res = PQgetResult(conn);
        if (PQresultStatus(res) != PGRES_COMMAND_OK)
        {
-               write_msg(NULL, "Dumping the contents of table \"%s\" failed: PQgetResult() failed.\n", classname);
-               write_msg(NULL, "Error message from server: %s", PQerrorMessage(conn));
-               write_msg(NULL, "The command was: %s\n", q->data);
+               pg_log_error("Dumping the contents of table \"%s\" failed: PQgetResult() failed.", classname);
+               pg_log_error("Error message from server: %s", PQerrorMessage(conn));
+               pg_log_error("The command was: %s", q->data);
                exit_nicely(1);
        }
        PQclear(res);
 
        /* Do this to ensure we've pumped libpq back to idle state */
        if (PQgetResult(conn) != NULL)
-               write_msg(NULL, "WARNING: unexpected extra results during COPY of table \"%s\"\n",
-                                 classname);
+               pg_log_warning("unexpected extra results during COPY of table \"%s\"",
+                                          classname);
 
        destroyPQExpBuffer(q);
        return 1;
@@ -1890,28 +1941,17 @@ dumpTableData_insert(Archive *fout, void *dcontext)
 {
        TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
        TableInfo  *tbinfo = tdinfo->tdtable;
-       const char *classname = tbinfo->dobj.name;
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer insertStmt = NULL;
        PGresult   *res;
-       int                     tuple;
        int                     nfields;
-       int                     field;
-
-       /*
-        * Make sure we are in proper schema.  We will qualify the table name
-        * below anyway (in case its name conflicts with a pg_catalog table); but
-        * this ensures reproducible results in case the table contains regproc,
-        * regclass, etc columns.
-        */
-       selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
+       int                     rows_per_statement = dopt->dump_inserts;
+       int                     rows_this_statement = 0;
 
        appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
                                          "SELECT * FROM ONLY %s",
-                                         fmtQualifiedId(fout->remoteVersion,
-                                                                        tbinfo->dobj.namespace->dobj.name,
-                                                                        classname));
+                                         fmtQualifiedDumpable(tbinfo));
        if (tdinfo->filtercond)
                appendPQExpBuffer(q, " %s", tdinfo->filtercond);
 
@@ -1922,83 +1962,96 @@ dumpTableData_insert(Archive *fout, void *dcontext)
                res = ExecuteSqlQuery(fout, "FETCH 100 FROM _pg_dump_cursor",
                                                          PGRES_TUPLES_OK);
                nfields = PQnfields(res);
-               for (tuple = 0; tuple < PQntuples(res); tuple++)
-               {
-                       /*
-                        * First time through, we build as much of the INSERT statement as
-                        * possible in "insertStmt", which we can then just print for each
-                        * line. If the table happens to have zero columns then this will
-                        * be a complete statement, otherwise it will end in "VALUES(" and
-                        * be ready to have the row's column values appended.
-                        */
-                       if (insertStmt == NULL)
-                       {
-                               insertStmt = createPQExpBuffer();
 
-                               /*
-                                * When load-via-partition-root is set, get the root table
-                                * name for the partition table, so that we can reload data
-                                * through the root table.
-                                */
-                               if (dopt->load_via_partition_root && tbinfo->ispartition)
-                               {
-                                       TableInfo  *parentTbinfo;
+               /*
+                * First time through, we build as much of the INSERT statement as
+                * possible in "insertStmt", which we can then just print for each
+                * statement. If the table happens to have zero columns then this will
+                * be a complete statement, otherwise it will end in "VALUES" and be
+                * ready to have the row's column values printed.
+                */
+               if (insertStmt == NULL)
+               {
+                       TableInfo  *targettab;
 
-                                       parentTbinfo = getRootTableInfo(tbinfo);
+                       insertStmt = createPQExpBuffer();
 
-                                       /*
-                                        * When we loading data through the root, we will qualify
-                                        * the table name. This is needed because earlier
-                                        * search_path will be set for the partition table.
-                                        */
-                                       classname = (char *) fmtQualifiedId(fout->remoteVersion,
-                                                                                                               parentTbinfo->dobj.namespace->dobj.name,
-                                                                                                               parentTbinfo->dobj.name);
-                               }
-                               else
-                                       classname = fmtId(tbinfo->dobj.name);
+                       /*
+                        * When load-via-partition-root is set, get the root table name
+                        * for the partition table, so that we can reload data through the
+                        * root table.
+                        */
+                       if (dopt->load_via_partition_root && tbinfo->ispartition)
+                               targettab = getRootTableInfo(tbinfo);
+                       else
+                               targettab = tbinfo;
 
-                               appendPQExpBuffer(insertStmt, "INSERT INTO %s ",
-                                                                 classname);
+                       appendPQExpBuffer(insertStmt, "INSERT INTO %s ",
+                                                         fmtQualifiedDumpable(targettab));
 
-                               /* corner case for zero-column table */
-                               if (nfields == 0)
-                               {
-                                       appendPQExpBufferStr(insertStmt, "DEFAULT VALUES;\n");
-                               }
-                               else
+                       /* corner case for zero-column table */
+                       if (nfields == 0)
+                       {
+                               appendPQExpBufferStr(insertStmt, "DEFAULT VALUES;\n");
+                       }
+                       else
+                       {
+                               /* append the list of column names if required */
+                               if (dopt->column_inserts)
                                {
-                                       /* append the list of column names if required */
-                                       if (dopt->column_inserts)
+                                       appendPQExpBufferChar(insertStmt, '(');
+                                       for (int field = 0; field < nfields; field++)
                                        {
-                                               appendPQExpBufferChar(insertStmt, '(');
-                                               for (field = 0; field < nfields; field++)
-                                               {
-                                                       if (field > 0)
-                                                               appendPQExpBufferStr(insertStmt, ", ");
-                                                       appendPQExpBufferStr(insertStmt,
-                                                                                                fmtId(PQfname(res, field)));
-                                               }
-                                               appendPQExpBufferStr(insertStmt, ") ");
+                                               if (field > 0)
+                                                       appendPQExpBufferStr(insertStmt, ", ");
+                                               appendPQExpBufferStr(insertStmt,
+                                                                                        fmtId(PQfname(res, field)));
                                        }
+                                       appendPQExpBufferStr(insertStmt, ") ");
+                               }
 
-                                       if (tbinfo->needs_override)
-                                               appendPQExpBufferStr(insertStmt, "OVERRIDING SYSTEM VALUE ");
+                               if (tbinfo->needs_override)
+                                       appendPQExpBufferStr(insertStmt, "OVERRIDING SYSTEM VALUE ");
 
-                                       appendPQExpBufferStr(insertStmt, "VALUES (");
-                               }
+                               appendPQExpBufferStr(insertStmt, "VALUES");
                        }
+               }
 
-                       archputs(insertStmt->data, fout);
+               for (int tuple = 0; tuple < PQntuples(res); tuple++)
+               {
+                       /* Write the INSERT if not in the middle of a multi-row INSERT. */
+                       if (rows_this_statement == 0)
+                               archputs(insertStmt->data, fout);
 
-                       /* if it is zero-column table then we're done */
+                       /*
+                        * If it is zero-column table then we've already written the
+                        * complete statement, which will mean we've disobeyed
+                        * --rows-per-insert when it's set greater than 1.  We do support
+                        * a way to make this multi-row with: SELECT UNION ALL SELECT
+                        * UNION ALL ... but that's non-standard so we should avoid it
+                        * given that using INSERTs is mostly only ever needed for
+                        * cross-database exports.
+                        */
                        if (nfields == 0)
                                continue;
 
-                       for (field = 0; field < nfields; field++)
+                       /* Emit a row heading */
+                       if (rows_per_statement == 1)
+                               archputs(" (", fout);
+                       else if (rows_this_statement > 0)
+                               archputs(",\n\t(", fout);
+                       else
+                               archputs("\n\t(", fout);
+
+                       for (int field = 0; field < nfields; field++)
                        {
                                if (field > 0)
                                        archputs(", ", fout);
+                               if (tbinfo->attgenerated[field])
+                               {
+                                       archputs("DEFAULT", fout);
+                                       continue;
+                               }
                                if (PQgetisnull(res, tuple, field))
                                {
                                        archputs("NULL", fout);
@@ -2059,7 +2112,20 @@ dumpTableData_insert(Archive *fout, void *dcontext)
                                                break;
                                }
                        }
-                       archputs(");\n", fout);
+
+                       /* Terminate the row ... */
+                       archputs(")", fout);
+
+                       /* ... and the statement, if the target no. of rows is reached */
+                       if (++rows_this_statement >= rows_per_statement)
+                       {
+                               if (dopt->do_nothing)
+                                       archputs(" ON CONFLICT DO NOTHING;\n", fout);
+                               else
+                                       archputs(";\n", fout);
+                               /* Reset the row counter */
+                               rows_this_statement = 0;
+                       }
                }
 
                if (PQntuples(res) <= 0)
@@ -2070,6 +2136,15 @@ dumpTableData_insert(Archive *fout, void *dcontext)
                PQclear(res);
        }
 
+       /* Terminate any statements that didn't make the row count. */
+       if (rows_this_statement > 0)
+       {
+               if (dopt->do_nothing)
+                       archputs(" ON CONFLICT DO NOTHING;\n", fout);
+               else
+                       archputs(";\n", fout);
+       }
+
        archputs("\n\n", fout);
 
        ExecuteSqlStatement(fout, "CLOSE _pg_dump_cursor");
@@ -2135,24 +2210,16 @@ dumpTableData(Archive *fout, TableDataInfo *tdinfo)
                        TableInfo  *parentTbinfo;
 
                        parentTbinfo = getRootTableInfo(tbinfo);
-
-                       /*
-                        * When we load data through the root, we will qualify the table
-                        * name, because search_path is set for the partition.
-                        */
-                       copyFrom = fmtQualifiedId(fout->remoteVersion,
-                                                                         parentTbinfo->dobj.namespace->dobj.name,
-                                                                         parentTbinfo->dobj.name);
+                       copyFrom = fmtQualifiedDumpable(parentTbinfo);
                }
                else
-                       copyFrom = fmtId(tbinfo->dobj.name);
+                       copyFrom = fmtQualifiedDumpable(tbinfo);
 
                /* must use 2 steps here 'cause fmtId is nonreentrant */
                appendPQExpBuffer(copyBuf, "COPY %s ",
                                                  copyFrom);
-               appendPQExpBuffer(copyBuf, "%s %sFROM stdin;\n",
-                                                 fmtCopyColumnList(tbinfo, clistBuf),
-                                                 (tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : "");
+               appendPQExpBuffer(copyBuf, "%s FROM stdin;\n",
+                                                 fmtCopyColumnList(tbinfo, clistBuf));
                copyStmt = copyBuf->data;
        }
        else
@@ -2168,13 +2235,32 @@ dumpTableData(Archive *fout, TableDataInfo *tdinfo)
         * See comments for BuildArchiveDependencies.
         */
        if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA)
-               ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
-                                        tbinfo->dobj.name, tbinfo->dobj.namespace->dobj.name,
-                                        NULL, tbinfo->rolname,
-                                        false, "TABLE DATA", SECTION_DATA,
-                                        "", "", copyStmt,
-                                        &(tbinfo->dobj.dumpId), 1,
-                                        dumpFn, tdinfo);
+       {
+               TocEntry   *te;
+
+               te = ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
+                                                 ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+                                                                          .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                          .owner = tbinfo->rolname,
+                                                                          .description = "TABLE DATA",
+                                                                          .section = SECTION_DATA,
+                                                                          .copyStmt = copyStmt,
+                                                                          .deps = &(tbinfo->dobj.dumpId),
+                                                                          .nDeps = 1,
+                                                                          .dumpFn = dumpFn,
+                                                                          .dumpArg = tdinfo));
+
+               /*
+                * Set the TocEntry's dataLength in case we are doing a parallel dump
+                * and want to order dump jobs by table size.  We choose to measure
+                * dataLength in table pages during dump, so no scaling is needed.
+                * However, relpages is declared as "integer" in pg_class, and hence
+                * also in TableInfo, but it's really BlockNumber a/k/a unsigned int.
+                * Cast so that we get the right interpretation of table sizes
+                * exceeding INT_MAX pages.
+                */
+               te->dataLength = (BlockNumber) tbinfo->relpages;
+       }
 
        destroyPQExpBuffer(copyBuf);
        destroyPQExpBuffer(clistBuf);
@@ -2200,26 +2286,20 @@ refreshMatViewData(Archive *fout, TableDataInfo *tdinfo)
        q = createPQExpBuffer();
 
        appendPQExpBuffer(q, "REFRESH MATERIALIZED VIEW %s;\n",
-                                         fmtId(tbinfo->dobj.name));
+                                         fmtQualifiedDumpable(tbinfo));
 
        if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA)
                ArchiveEntry(fout,
                                         tdinfo->dobj.catId,    /* catalog ID */
                                         tdinfo->dobj.dumpId,   /* dump ID */
-                                        tbinfo->dobj.name, /* Name */
-                                        tbinfo->dobj.namespace->dobj.name, /* Namespace */
-                                        NULL,          /* Tablespace */
-                                        tbinfo->rolname,       /* Owner */
-                                        false,         /* with oids */
-                                        "MATERIALIZED VIEW DATA",      /* Desc */
-                                        SECTION_POST_DATA, /* Section */
-                                        q->data,       /* Create */
-                                        "",            /* Del */
-                                        NULL,          /* Copy */
-                                        tdinfo->dobj.dependencies, /* Deps */
-                                        tdinfo->dobj.nDeps,    /* # Deps */
-                                        NULL,          /* Dumper */
-                                        NULL);         /* Dumper Arg */
+                                        ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+                                                                 .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tbinfo->rolname,
+                                                                 .description = "MATERIALIZED VIEW DATA",
+                                                                 .section = SECTION_POST_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .deps = tdinfo->dobj.dependencies,
+                                                                 .nDeps = tdinfo->dobj.nDeps));
 
        destroyPQExpBuffer(q);
 }
@@ -2229,7 +2309,7 @@ refreshMatViewData(Archive *fout, TableDataInfo *tdinfo)
  *       set up dumpable objects representing the contents of tables
  */
 static void
-getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, bool oids, char relkind)
+getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, char relkind)
 {
        int                     i;
 
@@ -2237,7 +2317,7 @@ getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, bool oids, ch
        {
                if (tblinfo[i].dobj.dump & DUMP_COMPONENT_DATA &&
                        (!relkind || tblinfo[i].relkind == relkind))
-                       makeTableDataInfo(dopt, &(tblinfo[i]), oids);
+                       makeTableDataInfo(dopt, &(tblinfo[i]));
        }
 }
 
@@ -2248,7 +2328,7 @@ getTableData(DumpOptions *dopt, TableInfo *tblinfo, int numTables, bool oids, ch
  * table data; the "dump" flag in such objects isn't used.
  */
 static void
-makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo, bool oids)
+makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo)
 {
        TableDataInfo *tdinfo;
 
@@ -2299,7 +2379,6 @@ makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo, bool oids)
        tdinfo->dobj.name = tbinfo->dobj.name;
        tdinfo->dobj.namespace = tbinfo->dobj.namespace;
        tdinfo->tdtable = tbinfo;
-       tdinfo->oids = oids;
        tdinfo->filtercond = NULL;      /* might get set later */
        addObjectDependency(&tdinfo->dobj, tbinfo->dobj.dumpId);
 
@@ -2328,9 +2407,6 @@ buildMatViewRefreshDependencies(Archive *fout)
        if (fout->remoteVersion < 90300)
                return;
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        query = createPQExpBuffer();
 
        appendPQExpBufferStr(query, "WITH RECURSIVE w AS "
@@ -2559,6 +2635,7 @@ dumpDatabase(Archive *fout)
        PGresult   *res;
        int                     i_tableoid,
                                i_oid,
+                               i_datname,
                                i_dba,
                                i_encoding,
                                i_collate,
@@ -2586,42 +2663,55 @@ dumpDatabase(Archive *fout)
                                minmxid;
        char       *qdatname;
 
-       datname = PQdb(conn);
-       qdatname = pg_strdup(fmtId(datname));
-
-       if (g_verbose)
-               write_msg(NULL, "saving database definition\n");
+       pg_log_info("saving database definition");
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
-       /* Fetch the database-level properties for this database */
+       /*
+        * Fetch the database-level properties for this database.
+        *
+        * The order in which privileges are in the ACL string (the order they
+        * have been GRANT'd in, which the backend maintains) must be preserved to
+        * ensure that GRANTs WITH GRANT OPTION and subsequent GRANTs based on
+        * those are dumped in the correct order.  Note that initial privileges
+        * (pg_init_privs) are not supported on databases, so this logic cannot
+        * make use of buildACLQueries().
+        */
        if (fout->remoteVersion >= 90600)
        {
-               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
                                                  "(%s datdba) AS dba, "
                                                  "pg_encoding_to_char(encoding) AS encoding, "
                                                  "datcollate, datctype, datfrozenxid, datminmxid, "
-                                                 "(SELECT array_agg(acl ORDER BY acl::text COLLATE \"C\") FROM ( "
-                                                 "  SELECT unnest(coalesce(datacl,acldefault('d',datdba))) AS acl "
-                                                 "  EXCEPT SELECT unnest(acldefault('d',datdba))) as datacls)"
+                                                 "(SELECT array_agg(acl ORDER BY row_n) FROM "
+                                                 "  (SELECT acl, row_n FROM "
+                                                 "     unnest(coalesce(datacl,acldefault('d',datdba))) "
+                                                 "     WITH ORDINALITY AS perm(acl,row_n) "
+                                                 "   WHERE NOT EXISTS ( "
+                                                 "     SELECT 1 "
+                                                 "     FROM unnest(acldefault('d',datdba)) "
+                                                 "       AS init(init_acl) "
+                                                 "     WHERE acl = init_acl)) AS datacls) "
                                                  " AS datacl, "
-                                                 "(SELECT array_agg(acl ORDER BY acl::text COLLATE \"C\") FROM ( "
-                                                 "  SELECT unnest(acldefault('d',datdba)) AS acl "
-                                                 "  EXCEPT SELECT unnest(coalesce(datacl,acldefault('d',datdba)))) as rdatacls)"
+                                                 "(SELECT array_agg(acl ORDER BY row_n) FROM "
+                                                 "  (SELECT acl, row_n FROM "
+                                                 "     unnest(acldefault('d',datdba)) "
+                                                 "     WITH ORDINALITY AS initp(acl,row_n) "
+                                                 "   WHERE NOT EXISTS ( "
+                                                 "     SELECT 1 "
+                                                 "     FROM unnest(coalesce(datacl,acldefault('d',datdba))) "
+                                                 "       AS permp(orig_acl) "
+                                                 "     WHERE acl = orig_acl)) AS rdatacls) "
                                                  " AS rdatacl, "
                                                  "datistemplate, datconnlimit, "
                                                  "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, "
                                                  "shobj_description(oid, 'pg_database') AS description "
 
                                                  "FROM pg_database "
-                                                 "WHERE datname = ",
+                                                 "WHERE datname = current_database()",
                                                  username_subquery);
-               appendStringLiteralAH(dbQry, datname, fout);
        }
        else if (fout->remoteVersion >= 90300)
        {
-               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
                                                  "(%s datdba) AS dba, "
                                                  "pg_encoding_to_char(encoding) AS encoding, "
                                                  "datcollate, datctype, datfrozenxid, datminmxid, "
@@ -2630,13 +2720,12 @@ dumpDatabase(Archive *fout)
                                                  "shobj_description(oid, 'pg_database') AS description "
 
                                                  "FROM pg_database "
-                                                 "WHERE datname = ",
+                                                 "WHERE datname = current_database()",
                                                  username_subquery);
-               appendStringLiteralAH(dbQry, datname, fout);
        }
        else if (fout->remoteVersion >= 80400)
        {
-               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
                                                  "(%s datdba) AS dba, "
                                                  "pg_encoding_to_char(encoding) AS encoding, "
                                                  "datcollate, datctype, datfrozenxid, 0 AS datminmxid, "
@@ -2645,13 +2734,12 @@ dumpDatabase(Archive *fout)
                                                  "shobj_description(oid, 'pg_database') AS description "
 
                                                  "FROM pg_database "
-                                                 "WHERE datname = ",
+                                                 "WHERE datname = current_database()",
                                                  username_subquery);
-               appendStringLiteralAH(dbQry, datname, fout);
        }
        else if (fout->remoteVersion >= 80200)
        {
-               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
                                                  "(%s datdba) AS dba, "
                                                  "pg_encoding_to_char(encoding) AS encoding, "
                                                  "NULL AS datcollate, NULL AS datctype, datfrozenxid, 0 AS datminmxid, "
@@ -2660,13 +2748,12 @@ dumpDatabase(Archive *fout)
                                                  "shobj_description(oid, 'pg_database') AS description "
 
                                                  "FROM pg_database "
-                                                 "WHERE datname = ",
+                                                 "WHERE datname = current_database()",
                                                  username_subquery);
-               appendStringLiteralAH(dbQry, datname, fout);
        }
        else
        {
-               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, "
+               appendPQExpBuffer(dbQry, "SELECT tableoid, oid, datname, "
                                                  "(%s datdba) AS dba, "
                                                  "pg_encoding_to_char(encoding) AS encoding, "
                                                  "NULL AS datcollate, NULL AS datctype, datfrozenxid, 0 AS datminmxid, "
@@ -2674,15 +2761,15 @@ dumpDatabase(Archive *fout)
                                                  "-1 as datconnlimit, "
                                                  "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace "
                                                  "FROM pg_database "
-                                                 "WHERE datname = ",
+                                                 "WHERE datname = current_database()",
                                                  username_subquery);
-               appendStringLiteralAH(dbQry, datname, fout);
        }
 
        res = ExecuteSqlQueryForSingleRow(fout, dbQry->data);
 
        i_tableoid = PQfnumber(res, "tableoid");
        i_oid = PQfnumber(res, "oid");
+       i_datname = PQfnumber(res, "datname");
        i_dba = PQfnumber(res, "dba");
        i_encoding = PQfnumber(res, "encoding");
        i_collate = PQfnumber(res, "datcollate");
@@ -2697,6 +2784,7 @@ dumpDatabase(Archive *fout)
 
        dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid));
        dbCatId.oid = atooid(PQgetvalue(res, 0, i_oid));
+       datname = PQgetvalue(res, 0, i_datname);
        dba = PQgetvalue(res, 0, i_dba);
        encoding = PQgetvalue(res, 0, i_encoding);
        collate = PQgetvalue(res, 0, i_collate);
@@ -2709,6 +2797,8 @@ dumpDatabase(Archive *fout)
        datconnlimit = PQgetvalue(res, 0, i_datconnlimit);
        tablespace = PQgetvalue(res, 0, i_tablespace);
 
+       qdatname = pg_strdup(fmtId(datname));
+
        /*
         * Prepare the CREATE DATABASE command.  We must specify encoding, locale,
         * and tablespace since those can't be altered later.  Other DB properties
@@ -2722,15 +2812,23 @@ dumpDatabase(Archive *fout)
                appendPQExpBufferStr(creaQry, " ENCODING = ");
                appendStringLiteralAH(creaQry, encoding, fout);
        }
-       if (strlen(collate) > 0)
+       if (strlen(collate) > 0 && strcmp(collate, ctype) == 0)
        {
-               appendPQExpBufferStr(creaQry, " LC_COLLATE = ");
+               appendPQExpBufferStr(creaQry, " LOCALE = ");
                appendStringLiteralAH(creaQry, collate, fout);
        }
-       if (strlen(ctype) > 0)
+       else
        {
-               appendPQExpBufferStr(creaQry, " LC_CTYPE = ");
-               appendStringLiteralAH(creaQry, ctype, fout);
+               if (strlen(collate) > 0)
+               {
+                       appendPQExpBufferStr(creaQry, " LC_COLLATE = ");
+                       appendStringLiteralAH(creaQry, collate, fout);
+               }
+               if (strlen(ctype) > 0)
+               {
+                       appendPQExpBufferStr(creaQry, " LC_CTYPE = ");
+                       appendStringLiteralAH(creaQry, ctype, fout);
+               }
        }
 
        /*
@@ -2755,22 +2853,14 @@ dumpDatabase(Archive *fout)
        ArchiveEntry(fout,
                                 dbCatId,               /* catalog ID */
                                 dbDumpId,              /* dump ID */
-                                datname,               /* Name */
-                                NULL,                  /* Namespace */
-                                NULL,                  /* Tablespace */
-                                dba,                   /* Owner */
-                                false,                 /* with oids */
-                                "DATABASE",    /* Desc */
-                                SECTION_PRE_DATA,      /* Section */
-                                creaQry->data, /* Create */
-                                delQry->data,  /* Del */
-                                NULL,                  /* Copy */
-                                NULL,                  /* Deps */
-                                0,                             /* # Deps */
-                                NULL,                  /* Dumper */
-                                NULL);                 /* Dumper Arg */
-
-       /* Compute correct tag for comments etc */
+                                ARCHIVE_OPTS(.tag = datname,
+                                                         .owner = dba,
+                                                         .description = "DATABASE",
+                                                         .section = SECTION_PRE_DATA,
+                                                         .createStmt = creaQry->data,
+                                                         .dropStmt = delQry->data));
+
+       /* Compute correct tag for archive entry */
        appendPQExpBuffer(labelq, "DATABASE %s", qdatname);
 
        /* Dump DB comment if any */
@@ -2796,16 +2886,18 @@ dumpDatabase(Archive *fout)
                        appendPQExpBufferStr(dbQry, ";\n");
 
                        ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                                labelq->data, NULL, NULL, dba,
-                                                false, "COMMENT", SECTION_NONE,
-                                                dbQry->data, "", NULL,
-                                                &(dbDumpId), 1,
-                                                NULL, NULL);
+                                                ARCHIVE_OPTS(.tag = labelq->data,
+                                                                         .owner = dba,
+                                                                         .description = "COMMENT",
+                                                                         .section = SECTION_NONE,
+                                                                         .createStmt = dbQry->data,
+                                                                         .deps = &dbDumpId,
+                                                                         .nDeps = 1));
                }
        }
        else
        {
-               dumpComment(fout, labelq->data, NULL, dba,
+               dumpComment(fout, "DATABASE", qdatname, NULL, dba,
                                        dbCatId, 0, dbDumpId);
        }
 
@@ -2823,11 +2915,13 @@ dumpDatabase(Archive *fout)
                emitShSecLabels(conn, shres, seclabelQry, "DATABASE", datname);
                if (seclabelQry->len > 0)
                        ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                                labelq->data, NULL, NULL, dba,
-                                                false, "SECURITY LABEL", SECTION_NONE,
-                                                seclabelQry->data, "", NULL,
-                                                &(dbDumpId), 1,
-                                                NULL, NULL);
+                                                ARCHIVE_OPTS(.tag = labelq->data,
+                                                                         .owner = dba,
+                                                                         .description = "SECURITY LABEL",
+                                                                         .section = SECTION_NONE,
+                                                                         .createStmt = seclabelQry->data,
+                                                                         .deps = &dbDumpId,
+                                                                         .nDeps = 1));
                destroyPQExpBuffer(seclabelQry);
                PQclear(shres);
        }
@@ -2837,7 +2931,7 @@ dumpDatabase(Archive *fout)
         * (pg_init_privs) on databases.
         */
        dumpACL(fout, dbCatId, dbDumpId, "DATABASE",
-                       qdatname, NULL, labelq->data, NULL,
+                       qdatname, NULL, NULL,
                        dba, datacl, rdatacl, "", "");
 
        /*
@@ -2893,15 +2987,17 @@ dumpDatabase(Archive *fout)
 
        if (creaQry->len > 0)
                ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                        datname, NULL, NULL, dba,
-                                        false, "DATABASE PROPERTIES", SECTION_PRE_DATA,
-                                        creaQry->data, delQry->data, NULL,
-                                        &(dbDumpId), 1,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = datname,
+                                                                 .owner = dba,
+                                                                 .description = "DATABASE PROPERTIES",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = creaQry->data,
+                                                                 .dropStmt = delQry->data,
+                                                                 .deps = &dbDumpId));
 
        /*
-        * pg_largeobject and pg_largeobject_metadata come from the old system
-        * intact, so set their relfrozenxids and relminmxids.
+        * pg_largeobject comes from the old system intact, so set its
+        * relfrozenxids and relminmxids.
         */
        if (dopt->binary_upgrade)
        {
@@ -2938,55 +3034,13 @@ dumpDatabase(Archive *fout)
                                                  atooid(PQgetvalue(lo_res, 0, i_relminmxid)),
                                                  LargeObjectRelationId);
                ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                        "pg_largeobject", NULL, NULL, "",
-                                        false, "pg_largeobject", SECTION_PRE_DATA,
-                                        loOutQry->data, "", NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = "pg_largeobject",
+                                                                 .description = "pg_largeobject",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = loOutQry->data));
 
                PQclear(lo_res);
 
-               /*
-                * pg_largeobject_metadata
-                */
-               if (fout->remoteVersion >= 90000)
-               {
-                       resetPQExpBuffer(loFrozenQry);
-                       resetPQExpBuffer(loOutQry);
-
-                       if (fout->remoteVersion >= 90300)
-                               appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid, relminmxid\n"
-                                                                 "FROM pg_catalog.pg_class\n"
-                                                                 "WHERE oid = %u;\n",
-                                                                 LargeObjectMetadataRelationId);
-                       else
-                               appendPQExpBuffer(loFrozenQry, "SELECT relfrozenxid, 0 AS relminmxid\n"
-                                                                 "FROM pg_catalog.pg_class\n"
-                                                                 "WHERE oid = %u;\n",
-                                                                 LargeObjectMetadataRelationId);
-
-                       lo_res = ExecuteSqlQueryForSingleRow(fout, loFrozenQry->data);
-
-                       i_relfrozenxid = PQfnumber(lo_res, "relfrozenxid");
-                       i_relminmxid = PQfnumber(lo_res, "relminmxid");
-
-                       appendPQExpBufferStr(loOutQry, "\n-- For binary upgrade, set pg_largeobject_metadata relfrozenxid and relminmxid\n");
-                       appendPQExpBuffer(loOutQry, "UPDATE pg_catalog.pg_class\n"
-                                                         "SET relfrozenxid = '%u', relminmxid = '%u'\n"
-                                                         "WHERE oid = %u;\n",
-                                                         atooid(PQgetvalue(lo_res, 0, i_relfrozenxid)),
-                                                         atooid(PQgetvalue(lo_res, 0, i_relminmxid)),
-                                                         LargeObjectMetadataRelationId);
-                       ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                                "pg_largeobject_metadata", NULL, NULL, "",
-                                                false, "pg_largeobject_metadata", SECTION_PRE_DATA,
-                                                loOutQry->data, "", NULL,
-                                                NULL, 0,
-                                                NULL, NULL);
-
-                       PQclear(lo_res);
-               }
-
                destroyPQExpBuffer(loFrozenQry);
                destroyPQExpBuffer(loOutQry);
        }
@@ -3081,19 +3135,17 @@ dumpEncoding(Archive *AH)
        const char *encname = pg_encoding_to_char(AH->encoding);
        PQExpBuffer qry = createPQExpBuffer();
 
-       if (g_verbose)
-               write_msg(NULL, "saving encoding = %s\n", encname);
+       pg_log_info("saving encoding = %s", encname);
 
        appendPQExpBufferStr(qry, "SET client_encoding = ");
        appendStringLiteralAH(qry, encname, AH);
        appendPQExpBufferStr(qry, ";\n");
 
        ArchiveEntry(AH, nilCatalogId, createDumpId(),
-                                "ENCODING", NULL, NULL, "",
-                                false, "ENCODING", SECTION_PRE_DATA,
-                                qry->data, "", NULL,
-                                NULL, 0,
-                                NULL, NULL);
+                                ARCHIVE_OPTS(.tag = "ENCODING",
+                                                         .description = "ENCODING",
+                                                         .section = SECTION_PRE_DATA,
+                                                         .createStmt = qry->data));
 
        destroyPQExpBuffer(qry);
 }
@@ -3108,21 +3160,80 @@ 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);
+       pg_log_info("saving standard_conforming_strings = %s",
+                               stdstrings);
 
        appendPQExpBuffer(qry, "SET standard_conforming_strings = '%s';\n",
                                          stdstrings);
 
        ArchiveEntry(AH, nilCatalogId, createDumpId(),
-                                "STDSTRINGS", NULL, NULL, "",
-                                false, "STDSTRINGS", SECTION_PRE_DATA,
-                                qry->data, "", NULL,
-                                NULL, 0,
-                                NULL, NULL);
+                                ARCHIVE_OPTS(.tag = "STDSTRINGS",
+                                                         .description = "STDSTRINGS",
+                                                         .section = SECTION_PRE_DATA,
+                                                         .createStmt = qry->data));
+
+       destroyPQExpBuffer(qry);
+}
+
+/*
+ * dumpSearchPath: record the active search_path in the archive
+ */
+static void
+dumpSearchPath(Archive *AH)
+{
+       PQExpBuffer qry = createPQExpBuffer();
+       PQExpBuffer path = createPQExpBuffer();
+       PGresult   *res;
+       char      **schemanames = NULL;
+       int                     nschemanames = 0;
+       int                     i;
+
+       /*
+        * We use the result of current_schemas(), not the search_path GUC,
+        * because that might contain wildcards such as "$user", which won't
+        * necessarily have the same value during restore.  Also, this way avoids
+        * listing schemas that may appear in search_path but not actually exist,
+        * which seems like a prudent exclusion.
+        */
+       res = ExecuteSqlQueryForSingleRow(AH,
+                                                                         "SELECT pg_catalog.current_schemas(false)");
+
+       if (!parsePGArray(PQgetvalue(res, 0, 0), &schemanames, &nschemanames))
+               fatal("could not parse result of current_schemas()");
+
+       /*
+        * We use set_config(), not a simple "SET search_path" command, because
+        * the latter has less-clean behavior if the search path is empty.  While
+        * that's likely to get fixed at some point, it seems like a good idea to
+        * be as backwards-compatible as possible in what we put into archives.
+        */
+       for (i = 0; i < nschemanames; i++)
+       {
+               if (i > 0)
+                       appendPQExpBufferStr(path, ", ");
+               appendPQExpBufferStr(path, fmtId(schemanames[i]));
+       }
+
+       appendPQExpBufferStr(qry, "SELECT pg_catalog.set_config('search_path', ");
+       appendStringLiteralAH(qry, path->data, AH);
+       appendPQExpBufferStr(qry, ", false);\n");
+
+       pg_log_info("saving search_path = %s", path->data);
+
+       ArchiveEntry(AH, nilCatalogId, createDumpId(),
+                                ARCHIVE_OPTS(.tag = "SEARCHPATH",
+                                                         .description = "SEARCHPATH",
+                                                         .section = SECTION_PRE_DATA,
+                                                         .createStmt = qry->data));
+
+       /* Also save it in AH->searchpath, in case we're doing plain text dump */
+       AH->searchpath = pg_strdup(qry->data);
 
+       if (schemanames)
+               free(schemanames);
+       PQclear(res);
        destroyPQExpBuffer(qry);
+       destroyPQExpBuffer(path);
 }
 
 
@@ -3147,12 +3258,7 @@ getBlobs(Archive *fout)
        int                     i_initlomacl;
        int                     i_initrlomacl;
 
-       /* Verbose message */
-       if (g_verbose)
-               write_msg(NULL, "reading large objects\n");
-
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
+       pg_log_info("reading large objects");
 
        /* Fetch BLOB OIDs, and owner/ACL data if >= 9.0 */
        if (fout->remoteVersion >= 90600)
@@ -3240,18 +3346,14 @@ getBlobs(Archive *fout)
                        binfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
 
                /*
-                * In binary-upgrade mode for blobs, we do *not* dump out the data or
-                * the ACLs, should any exist.  The data and ACL (if any) will be
-                * copied by pg_upgrade, which simply copies the pg_largeobject and
-                * pg_largeobject_metadata tables.
-                *
-                * We *do* dump out the definition of the blob because we need that to
-                * make the restoration of the comments, and anything else, work since
-                * pg_upgrade copies the files behind pg_largeobject and
-                * pg_largeobject_metadata after the dump is restored.
+                * In binary-upgrade mode for blobs, we do *not* dump out the blob
+                * data, as it will be copied by pg_upgrade, which simply copies the
+                * pg_largeobject table. We *do* however dump out anything but the
+                * data, as pg_upgrade copies just pg_largeobject, but not
+                * pg_largeobject_metadata, after the dump is restored.
                 */
                if (dopt->binary_upgrade)
-                       binfo[i].dobj.dump &= ~(DUMP_COMPONENT_DATA | DUMP_COMPONENT_ACL);
+                       binfo[i].dobj.dump &= ~DUMP_COMPONENT_DATA;
        }
 
        /*
@@ -3292,34 +3394,29 @@ dumpBlob(Archive *fout, BlobInfo *binfo)
 
        if (binfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, binfo->dobj.catId, binfo->dobj.dumpId,
-                                        binfo->dobj.name,
-                                        NULL, NULL,
-                                        binfo->rolname, false,
-                                        "BLOB", SECTION_PRE_DATA,
-                                        cquery->data, dquery->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
-
-       /* set up tag for comment and/or ACL */
-       resetPQExpBuffer(cquery);
-       appendPQExpBuffer(cquery, "LARGE OBJECT %s", binfo->dobj.name);
+                                        ARCHIVE_OPTS(.tag = binfo->dobj.name,
+                                                                 .owner = binfo->rolname,
+                                                                 .description = "BLOB",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = cquery->data,
+                                                                 .dropStmt = dquery->data));
 
        /* Dump comment if any */
        if (binfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, cquery->data,
+               dumpComment(fout, "LARGE OBJECT", binfo->dobj.name,
                                        NULL, binfo->rolname,
                                        binfo->dobj.catId, 0, binfo->dobj.dumpId);
 
        /* Dump security label if any */
        if (binfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, cquery->data,
+               dumpSecLabel(fout, "LARGE OBJECT", binfo->dobj.name,
                                         NULL, binfo->rolname,
                                         binfo->dobj.catId, 0, binfo->dobj.dumpId);
 
        /* Dump ACL if any */
        if (binfo->blobacl && (binfo->dobj.dump & DUMP_COMPONENT_ACL))
                dumpACL(fout, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT",
-                               binfo->dobj.name, NULL, cquery->data,
+                               binfo->dobj.name, NULL,
                                NULL, binfo->rolname, binfo->blobacl, binfo->rblobacl,
                                binfo->initblobacl, binfo->initrblobacl);
 
@@ -3343,20 +3440,20 @@ dumpBlobs(Archive *fout, void *arg)
        int                     i;
        int                     cnt;
 
-       if (g_verbose)
-               write_msg(NULL, "saving large objects\n");
-
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
+       pg_log_info("saving large objects");
 
        /*
         * Currently, we re-fetch all BLOB OIDs using a cursor.  Consider scanning
         * the already-in-memory dumpable objects instead...
         */
        if (fout->remoteVersion >= 90000)
-               blobQry = "DECLARE bloboid CURSOR FOR SELECT oid FROM pg_largeobject_metadata";
+               blobQry =
+                       "DECLARE bloboid CURSOR FOR "
+                       "SELECT oid FROM pg_largeobject_metadata ORDER BY 1";
        else
-               blobQry = "DECLARE bloboid CURSOR FOR SELECT DISTINCT loid FROM pg_largeobject";
+               blobQry =
+                       "DECLARE bloboid CURSOR FOR "
+                       "SELECT DISTINCT loid FROM pg_largeobject ORDER BY 1";
 
        ExecuteSqlStatement(fout, blobQry);
 
@@ -3379,8 +3476,8 @@ dumpBlobs(Archive *fout, void *arg)
                        /* Open the BLOB */
                        loFd = lo_open(conn, blobOid, INV_READ);
                        if (loFd == -1)
-                               exit_horribly(NULL, "could not open large object %u: %s",
-                                                         blobOid, PQerrorMessage(conn));
+                               fatal("could not open large object %u: %s",
+                                         blobOid, PQerrorMessage(conn));
 
                        StartBlob(fout, blobOid);
 
@@ -3389,8 +3486,8 @@ dumpBlobs(Archive *fout, void *arg)
                        {
                                cnt = lo_read(conn, loFd, buf, LOBBUFSIZE);
                                if (cnt < 0)
-                                       exit_horribly(NULL, "error reading large object %u: %s",
-                                                                 blobOid, PQerrorMessage(conn));
+                                       fatal("error reading large object %u: %s",
+                                                 blobOid, PQerrorMessage(conn));
 
                                WriteData(fout, buf, cnt);
                        } while (cnt > 0);
@@ -3441,15 +3538,14 @@ getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
                if (!(tbinfo->dobj.dump & DUMP_COMPONENT_POLICY))
                        continue;
 
-               if (g_verbose)
-                       write_msg(NULL, "reading row security enabled for table \"%s.%s\"\n",
-                                         tbinfo->dobj.namespace->dobj.name,
-                                         tbinfo->dobj.name);
+               pg_log_info("reading row security enabled for table \"%s.%s\"",
+                                       tbinfo->dobj.namespace->dobj.name,
+                                       tbinfo->dobj.name);
 
                /*
                 * Get row security enabled information for the table. We represent
-                * RLS enabled on a table by creating PolicyInfo object with an empty
-                * policy.
+                * RLS being enabled on a table by creating a PolicyInfo object with
+                * null polname.
                 */
                if (tbinfo->rowsec)
                {
@@ -3473,15 +3569,9 @@ getPolicies(Archive *fout, TableInfo tblinfo[], int numTables)
                        polinfo->polwithcheck = NULL;
                }
 
-               if (g_verbose)
-                       write_msg(NULL, "reading policies for table \"%s.%s\"\n",
-                                         tbinfo->dobj.namespace->dobj.name,
-                                         tbinfo->dobj.name);
-
-               /*
-                * select table schema to ensure regproc name is qualified if needed
-                */
-               selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
+               pg_log_info("reading policies for table \"%s.%s\"",
+                                       tbinfo->dobj.namespace->dobj.name,
+                                       tbinfo->dobj.name);
 
                resetPQExpBuffer(query);
 
@@ -3595,18 +3685,23 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
                query = createPQExpBuffer();
 
                appendPQExpBuffer(query, "ALTER TABLE %s ENABLE ROW LEVEL SECURITY;",
-                                                 fmtId(polinfo->dobj.name));
+                                                 fmtQualifiedDumpable(tbinfo));
 
+               /*
+                * We must emit the ROW SECURITY object's dependency on its table
+                * explicitly, because it will not match anything in pg_depend (unlike
+                * the case for other PolicyInfo objects).
+                */
                if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
                        ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
-                                                polinfo->dobj.name,
-                                                polinfo->dobj.namespace->dobj.name,
-                                                NULL,
-                                                tbinfo->rolname, false,
-                                                "ROW SECURITY", SECTION_POST_DATA,
-                                                query->data, "", NULL,
-                                                NULL, 0,
-                                                NULL, NULL);
+                                                ARCHIVE_OPTS(.tag = polinfo->dobj.name,
+                                                                         .namespace = polinfo->dobj.namespace->dobj.name,
+                                                                         .owner = tbinfo->rolname,
+                                                                         .description = "ROW SECURITY",
+                                                                         .section = SECTION_POST_DATA,
+                                                                         .createStmt = query->data,
+                                                                         .deps = &(tbinfo->dobj.dumpId),
+                                                                         .nDeps = 1));
 
                destroyPQExpBuffer(query);
                return;
@@ -3624,8 +3719,8 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
                cmd = " FOR DELETE";
        else
        {
-               write_msg(NULL, "unexpected policy command type: %c\n",
-                                 polinfo->polcmd);
+               pg_log_error("unexpected policy command type: %c",
+                                        polinfo->polcmd);
                exit_nicely(1);
        }
 
@@ -3634,7 +3729,7 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
 
        appendPQExpBuffer(query, "CREATE POLICY %s", fmtId(polinfo->polname));
 
-       appendPQExpBuffer(query, " ON %s%s%s", fmtId(tbinfo->dobj.name),
+       appendPQExpBuffer(query, " ON %s%s%s", fmtQualifiedDumpable(tbinfo),
                                          !polinfo->polpermissive ? " AS RESTRICTIVE" : "", cmd);
 
        if (polinfo->polroles != NULL)
@@ -3646,23 +3741,22 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
        if (polinfo->polwithcheck != NULL)
                appendPQExpBuffer(query, " WITH CHECK (%s)", polinfo->polwithcheck);
 
-       appendPQExpBuffer(query, ";\n");
+       appendPQExpBufferStr(query, ";\n");
 
        appendPQExpBuffer(delqry, "DROP POLICY %s", fmtId(polinfo->polname));
-       appendPQExpBuffer(delqry, " ON %s;\n", fmtId(tbinfo->dobj.name));
+       appendPQExpBuffer(delqry, " ON %s;\n", fmtQualifiedDumpable(tbinfo));
 
        tag = psprintf("%s %s", tbinfo->dobj.name, polinfo->dobj.name);
 
        if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
                ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
-                                        tag,
-                                        polinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        tbinfo->rolname, false,
-                                        "POLICY", SECTION_POST_DATA,
-                                        query->data, delqry->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tag,
+                                                                 .namespace = polinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tbinfo->rolname,
+                                                                 .description = "POLICY",
+                                                                 .section = SECTION_POST_DATA,
+                                                                 .createStmt = query->data,
+                                                                 .dropStmt = delqry->data));
 
        free(tag);
        destroyPQExpBuffer(query);
@@ -3688,6 +3782,7 @@ getPublications(Archive *fout)
        int                     i_pubinsert;
        int                     i_pubupdate;
        int                     i_pubdelete;
+       int                     i_pubtruncate;
        int                     i,
                                ntups;
 
@@ -3698,16 +3793,21 @@ getPublications(Archive *fout)
 
        resetPQExpBuffer(query);
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        /* Get the publications. */
-       appendPQExpBuffer(query,
-                                         "SELECT p.tableoid, p.oid, p.pubname, "
-                                         "(%s p.pubowner) AS rolname, "
-                                         "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete "
-                                         "FROM pg_publication p",
-                                         username_subquery);
+       if (fout->remoteVersion >= 110000)
+               appendPQExpBuffer(query,
+                                                 "SELECT p.tableoid, p.oid, p.pubname, "
+                                                 "(%s p.pubowner) AS rolname, "
+                                                 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, p.pubtruncate "
+                                                 "FROM pg_publication p",
+                                                 username_subquery);
+       else
+               appendPQExpBuffer(query,
+                                                 "SELECT p.tableoid, p.oid, p.pubname, "
+                                                 "(%s p.pubowner) AS rolname, "
+                                                 "p.puballtables, p.pubinsert, p.pubupdate, p.pubdelete, false AS pubtruncate "
+                                                 "FROM pg_publication p",
+                                                 username_subquery);
 
        res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
@@ -3721,6 +3821,7 @@ getPublications(Archive *fout)
        i_pubinsert = PQfnumber(res, "pubinsert");
        i_pubupdate = PQfnumber(res, "pubupdate");
        i_pubdelete = PQfnumber(res, "pubdelete");
+       i_pubtruncate = PQfnumber(res, "pubtruncate");
 
        pubinfo = pg_malloc(ntups * sizeof(PublicationInfo));
 
@@ -3741,10 +3842,12 @@ getPublications(Archive *fout)
                        (strcmp(PQgetvalue(res, i, i_pubupdate), "t") == 0);
                pubinfo[i].pubdelete =
                        (strcmp(PQgetvalue(res, i, i_pubdelete), "t") == 0);
+               pubinfo[i].pubtruncate =
+                       (strcmp(PQgetvalue(res, i, i_pubtruncate), "t") == 0);
 
                if (strlen(pubinfo[i].rolname) == 0)
-                       write_msg(NULL, "WARNING: owner of publication \"%s\" appears to be invalid\n",
-                                         pubinfo[i].dobj.name);
+                       pg_log_warning("owner of publication \"%s\" appears to be invalid",
+                                                  pubinfo[i].dobj.name);
 
                /* Decide whether we want to dump it */
                selectDumpableObject(&(pubinfo[i].dobj), fout);
@@ -3763,7 +3866,7 @@ dumpPublication(Archive *fout, PublicationInfo *pubinfo)
 {
        PQExpBuffer delq;
        PQExpBuffer query;
-       PQExpBuffer labelq;
+       char       *qpubname;
        bool            first = true;
 
        if (!(pubinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
@@ -3771,15 +3874,14 @@ dumpPublication(Archive *fout, PublicationInfo *pubinfo)
 
        delq = createPQExpBuffer();
        query = createPQExpBuffer();
-       labelq = createPQExpBuffer();
+
+       qpubname = pg_strdup(fmtId(pubinfo->dobj.name));
 
        appendPQExpBuffer(delq, "DROP PUBLICATION %s;\n",
-                                         fmtId(pubinfo->dobj.name));
+                                         qpubname);
 
        appendPQExpBuffer(query, "CREATE PUBLICATION %s",
-                                         fmtId(pubinfo->dobj.name));
-
-       appendPQExpBuffer(labelq, "PUBLICATION %s", fmtId(pubinfo->dobj.name));
+                                         qpubname);
 
        if (pubinfo->puballtables)
                appendPQExpBufferStr(query, " FOR ALL TABLES");
@@ -3809,30 +3911,38 @@ dumpPublication(Archive *fout, PublicationInfo *pubinfo)
                first = false;
        }
 
+       if (pubinfo->pubtruncate)
+       {
+               if (!first)
+                       appendPQExpBufferStr(query, ", ");
+
+               appendPQExpBufferStr(query, "truncate");
+               first = false;
+       }
+
        appendPQExpBufferStr(query, "');\n");
 
        ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId,
-                                pubinfo->dobj.name,
-                                NULL,
-                                NULL,
-                                pubinfo->rolname, false,
-                                "PUBLICATION", SECTION_POST_DATA,
-                                query->data, delq->data, NULL,
-                                NULL, 0,
-                                NULL, NULL);
+                                ARCHIVE_OPTS(.tag = pubinfo->dobj.name,
+                                                         .owner = pubinfo->rolname,
+                                                         .description = "PUBLICATION",
+                                                         .section = SECTION_POST_DATA,
+                                                         .createStmt = query->data,
+                                                         .dropStmt = delq->data));
 
        if (pubinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "PUBLICATION", qpubname,
                                        NULL, pubinfo->rolname,
                                        pubinfo->dobj.catId, 0, pubinfo->dobj.dumpId);
 
        if (pubinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, "PUBLICATION", qpubname,
                                         NULL, pubinfo->rolname,
                                         pubinfo->dobj.catId, 0, pubinfo->dobj.dumpId);
 
        destroyPQExpBuffer(delq);
        destroyPQExpBuffer(query);
+       free(qpubname);
 }
 
 /*
@@ -3845,6 +3955,7 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
        PQExpBuffer query;
        PGresult   *res;
        PublicationRelInfo *pubrinfo;
+       DumpOptions *dopt = fout->dopt;
        int                     i_tableoid;
        int                     i_oid;
        int                     i_pubname;
@@ -3852,14 +3963,11 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
                                j,
                                ntups;
 
-       if (fout->remoteVersion < 100000)
+       if (dopt->no_publications || fout->remoteVersion < 100000)
                return;
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        for (i = 0; i < numTables; i++)
        {
                TableInfo  *tbinfo = &tblinfo[i];
@@ -3875,10 +3983,9 @@ getPublicationTables(Archive *fout, TableInfo tblinfo[], int numTables)
                if (!(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
                        continue;
 
-               if (g_verbose)
-                       write_msg(NULL, "reading publication membership for table \"%s.%s\"\n",
-                                         tbinfo->dobj.namespace->dobj.name,
-                                         tbinfo->dobj.name);
+               pg_log_info("reading publication membership for table \"%s.%s\"",
+                                       tbinfo->dobj.namespace->dobj.name,
+                                       tbinfo->dobj.name);
 
                resetPQExpBuffer(query);
 
@@ -3948,22 +4055,19 @@ dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo)
 
        appendPQExpBuffer(query, "ALTER PUBLICATION %s ADD TABLE ONLY",
                                          fmtId(pubrinfo->pubname));
-       appendPQExpBuffer(query, " %s;",
-                                         fmtId(tbinfo->dobj.name));
+       appendPQExpBuffer(query, " %s;\n",
+                                         fmtQualifiedDumpable(tbinfo));
 
        /*
-        * There is no point in creating drop query as drop query as the drop is
-        * done by table drop.
+        * There is no point in creating drop query as the drop is done by table
+        * drop.
         */
        ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
-                                tag,
-                                tbinfo->dobj.namespace->dobj.name,
-                                NULL,
-                                "", false,
-                                "PUBLICATION TABLE", SECTION_POST_DATA,
-                                query->data, "", NULL,
-                                NULL, 0,
-                                NULL, NULL);
+                                ARCHIVE_OPTS(.tag = tag,
+                                                         .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                         .description = "PUBLICATION TABLE",
+                                                         .section = SECTION_POST_DATA,
+                                                         .createStmt = query->data));
 
        free(tag);
        destroyPQExpBuffer(query);
@@ -4011,9 +4115,6 @@ getSubscriptions(Archive *fout)
        if (dopt->no_subscriptions || fout->remoteVersion < 100000)
                return;
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        if (!is_superuser(fout))
        {
                int                     n;
@@ -4025,7 +4126,7 @@ getSubscriptions(Archive *fout)
                                                          PGRES_TUPLES_OK);
                n = atoi(PQgetvalue(res, 0, 0));
                if (n > 0)
-                       write_msg(NULL, "WARNING: subscriptions not dumped because current user is not a superuser\n");
+                       pg_log_warning("subscriptions not dumped because current user is not a superuser");
                PQclear(res);
                return;
        }
@@ -4079,8 +4180,8 @@ getSubscriptions(Archive *fout)
                        pg_strdup(PQgetvalue(res, i, i_subpublications));
 
                if (strlen(subinfo[i].rolname) == 0)
-                       write_msg(NULL, "WARNING: owner of subscription \"%s\" appears to be invalid\n",
-                                         subinfo[i].dobj.name);
+                       pg_log_warning("owner of subscription \"%s\" appears to be invalid",
+                                                  subinfo[i].dobj.name);
 
                /* Decide whether we want to dump it */
                selectDumpableObject(&(subinfo[i].dobj), fout);
@@ -4099,8 +4200,8 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
 {
        PQExpBuffer delq;
        PQExpBuffer query;
-       PQExpBuffer labelq;
        PQExpBuffer publications;
+       char       *qsubname;
        char      **pubnames = NULL;
        int                     npubnames = 0;
        int                     i;
@@ -4110,20 +4211,20 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
 
        delq = createPQExpBuffer();
        query = createPQExpBuffer();
-       labelq = createPQExpBuffer();
+
+       qsubname = pg_strdup(fmtId(subinfo->dobj.name));
 
        appendPQExpBuffer(delq, "DROP SUBSCRIPTION %s;\n",
-                                         fmtId(subinfo->dobj.name));
+                                         qsubname);
 
        appendPQExpBuffer(query, "CREATE SUBSCRIPTION %s CONNECTION ",
-                                         fmtId(subinfo->dobj.name));
+                                         qsubname);
        appendStringLiteralAH(query, subinfo->subconninfo, fout);
 
        /* Build list of quoted publications and append them to query. */
        if (!parsePGArray(subinfo->subpublications, &pubnames, &npubnames))
        {
-               write_msg(NULL,
-                                 "WARNING: could not parse subpublications array\n");
+               pg_log_warning("could not parse subpublications array");
                if (pubnames)
                        free(pubnames);
                pubnames = NULL;
@@ -4150,25 +4251,21 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
 
        appendPQExpBufferStr(query, ");\n");
 
-       appendPQExpBuffer(labelq, "SUBSCRIPTION %s", fmtId(subinfo->dobj.name));
-
        ArchiveEntry(fout, subinfo->dobj.catId, subinfo->dobj.dumpId,
-                                subinfo->dobj.name,
-                                NULL,
-                                NULL,
-                                subinfo->rolname, false,
-                                "SUBSCRIPTION", SECTION_POST_DATA,
-                                query->data, delq->data, NULL,
-                                NULL, 0,
-                                NULL, NULL);
+                                ARCHIVE_OPTS(.tag = subinfo->dobj.name,
+                                                         .owner = subinfo->rolname,
+                                                         .description = "SUBSCRIPTION",
+                                                         .section = SECTION_POST_DATA,
+                                                         .createStmt = query->data,
+                                                         .dropStmt = delq->data));
 
        if (subinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "SUBSCRIPTION", qsubname,
                                        NULL, subinfo->rolname,
                                        subinfo->dobj.catId, 0, subinfo->dobj.dumpId);
 
        if (subinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, "SUBSCRIPTION", qsubname,
                                         NULL, subinfo->rolname,
                                         subinfo->dobj.catId, 0, subinfo->dobj.dumpId);
 
@@ -4178,6 +4275,7 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
 
        destroyPQExpBuffer(delq);
        destroyPQExpBuffer(query);
+       free(qsubname);
 }
 
 static void
@@ -4259,14 +4357,20 @@ binary_upgrade_set_type_oids_by_rel_oid(Archive *fout,
        Oid                     pg_type_oid;
        bool            toast_set = false;
 
-       /* we only support old >= 8.3 for binary upgrades */
+       /*
+        * We only support old >= 8.3 for binary upgrades.
+        *
+        * We purposefully ignore toast OIDs for partitioned tables; the reason is
+        * that versions 10 and 11 have them, but 12 does not, so emitting them
+        * causes the upgrade to fail.
+        */
        appendPQExpBuffer(upgrade_query,
                                          "SELECT c.reltype AS crel, t.reltype AS trel "
                                          "FROM pg_catalog.pg_class c "
                                          "LEFT JOIN pg_catalog.pg_class t ON "
-                                         "  (c.reltoastrelid = t.oid) "
+                                         "  (c.reltoastrelid = t.oid AND c.relkind <> '%c') "
                                          "WHERE c.oid = '%u'::pg_catalog.oid;",
-                                         pg_rel_oid);
+                                         RELKIND_PARTITIONED_TABLE, pg_rel_oid);
 
        upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
 
@@ -4361,11 +4465,16 @@ binary_upgrade_set_pg_class_oids(Archive *fout,
 /*
  * If the DumpableObject is a member of an extension, add a suitable
  * ALTER EXTENSION ADD command to the creation commands in upgrade_buffer.
+ *
+ * For somewhat historical reasons, objname should already be quoted,
+ * but not objnamespace (if any).
  */
 static void
 binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
                                                                DumpableObject *dobj,
-                                                               const char *objlabel)
+                                                               const char *objtype,
+                                                               const char *objname,
+                                                               const char *objnamespace)
 {
        DumpableObject *extobj = NULL;
        int                     i;
@@ -4387,13 +4496,17 @@ binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
                extobj = NULL;
        }
        if (extobj == NULL)
-               exit_horribly(NULL, "could not find parent extension for %s\n", objlabel);
+               fatal("could not find parent extension for %s %s",
+                         objtype, objname);
 
        appendPQExpBufferStr(upgrade_buffer,
                                                 "\n-- For binary upgrade, handle extension membership the hard way\n");
-       appendPQExpBuffer(upgrade_buffer, "ALTER EXTENSION %s ADD %s;\n",
+       appendPQExpBuffer(upgrade_buffer, "ALTER EXTENSION %s ADD %s ",
                                          fmtId(extobj->name),
-                                         objlabel);
+                                         objtype);
+       if (objnamespace && *objnamespace)
+               appendPQExpBuffer(upgrade_buffer, "%s.", fmtId(objnamespace));
+       appendPQExpBuffer(upgrade_buffer, "%s;\n", objname);
 }
 
 /*
@@ -4423,9 +4536,6 @@ getNamespaces(Archive *fout, int *numNamespaces)
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        /*
         * we fetch all namespaces including system ones, so that every object we
         * read in can be linked to a containing namespace.
@@ -4458,7 +4568,7 @@ getNamespaces(Archive *fout, int *numNamespaces)
                                                  init_acl_subquery->data,
                                                  init_racl_subquery->data);
 
-               appendPQExpBuffer(query, ") ");
+               appendPQExpBufferStr(query, ") ");
 
                destroyPQExpBuffer(acl_subquery);
                destroyPQExpBuffer(racl_subquery);
@@ -4518,8 +4628,8 @@ getNamespaces(Archive *fout, int *numNamespaces)
                        nsinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
 
                if (strlen(nsinfo[i].rolname) == 0)
-                       write_msg(NULL, "WARNING: owner of schema \"%s\" appears to be invalid\n",
-                                         nsinfo[i].dobj.name);
+                       pg_log_warning("owner of schema \"%s\" appears to be invalid",
+                                                  nsinfo[i].dobj.name);
        }
 
        PQclear(res);
@@ -4541,7 +4651,7 @@ findNamespace(Archive *fout, Oid nsoid)
 
        nsinfo = findNamespaceByOid(nsoid);
        if (nsinfo == NULL)
-               exit_horribly(NULL, "schema with OID %u does not exist\n", nsoid);
+               fatal("schema with OID %u does not exist", nsoid);
        return nsinfo;
 }
 
@@ -4581,9 +4691,6 @@ getExtensions(Archive *fout, int *numExtensions)
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBufferStr(query, "SELECT x.tableoid, x.oid, "
                                                 "x.extname, n.nspname, x.extrelocatable, x.extversion, x.extconfig, x.extcondition "
                                                 "FROM pg_extension x "
@@ -4681,9 +4788,6 @@ getTypes(Archive *fout, int *numTypes)
         * be revisited if the backend ever allows renaming of array types.
         */
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        if (fout->remoteVersion >= 90600)
        {
                PQExpBuffer acl_subquery = createPQExpBuffer();
@@ -4872,8 +4976,8 @@ getTypes(Archive *fout, int *numTypes)
                }
 
                if (strlen(tyinfo[i].rolname) == 0)
-                       write_msg(NULL, "WARNING: owner of data type \"%s\" appears to be invalid\n",
-                                         tyinfo[i].dobj.name);
+                       pg_log_warning("owner of data type \"%s\" appears to be invalid",
+                                                  tyinfo[i].dobj.name);
        }
 
        *numTypes = ntups;
@@ -4913,9 +5017,6 @@ getOperators(Archive *fout, int *numOprs)
         * system-defined operators at dump-out time.
         */
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBuffer(query, "SELECT tableoid, oid, oprname, "
                                          "oprnamespace, "
                                          "(%s oprowner) AS rolname, "
@@ -4960,8 +5061,8 @@ getOperators(Archive *fout, int *numOprs)
                oprinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
 
                if (strlen(oprinfo[i].rolname) == 0)
-                       write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
-                                         oprinfo[i].dobj.name);
+                       pg_log_warning("owner of operator \"%s\" appears to be invalid",
+                                                  oprinfo[i].dobj.name);
        }
 
        PQclear(res);
@@ -5006,9 +5107,6 @@ getCollations(Archive *fout, int *numCollations)
         * system-defined collations at dump-out time.
         */
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBuffer(query, "SELECT tableoid, oid, collname, "
                                          "collnamespace, "
                                          "(%s collowner) AS rolname "
@@ -5082,9 +5180,6 @@ getConversions(Archive *fout, int *numConversions)
         * system-defined conversions at dump-out time.
         */
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBuffer(query, "SELECT tableoid, oid, conname, "
                                          "connamespace, "
                                          "(%s conowner) AS rolname "
@@ -5160,13 +5255,10 @@ getAccessMethods(Archive *fout, int *numAccessMethods)
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        /* Select all access methods from pg_am table */
-       appendPQExpBuffer(query, "SELECT tableoid, oid, amname, amtype, "
-                                         "amhandler::pg_catalog.regproc AS amhandler "
-                                         "FROM pg_am");
+       appendPQExpBufferStr(query, "SELECT tableoid, oid, amname, amtype, "
+                                                "amhandler::pg_catalog.regproc AS amhandler "
+                                                "FROM pg_am");
 
        res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
@@ -5233,9 +5325,6 @@ getOpclasses(Archive *fout, int *numOpclasses)
         * system-defined opclasses at dump-out time.
         */
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBuffer(query, "SELECT tableoid, oid, opcname, "
                                          "opcnamespace, "
                                          "(%s opcowner) AS rolname "
@@ -5274,8 +5363,8 @@ getOpclasses(Archive *fout, int *numOpclasses)
                opcinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
 
                if (strlen(opcinfo[i].rolname) == 0)
-                       write_msg(NULL, "WARNING: owner of operator class \"%s\" appears to be invalid\n",
-                                         opcinfo[i].dobj.name);
+                       pg_log_warning("owner of operator class \"%s\" appears to be invalid",
+                                                  opcinfo[i].dobj.name);
        }
 
        PQclear(res);
@@ -5320,9 +5409,6 @@ getOpfamilies(Archive *fout, int *numOpfamilies)
         * system-defined opfamilies at dump-out time.
         */
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBuffer(query, "SELECT tableoid, oid, opfname, "
                                          "opfnamespace, "
                                          "(%s opfowner) AS rolname "
@@ -5361,8 +5447,8 @@ getOpfamilies(Archive *fout, int *numOpfamilies)
                opfinfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
 
                if (strlen(opfinfo[i].rolname) == 0)
-                       write_msg(NULL, "WARNING: owner of operator family \"%s\" appears to be invalid\n",
-                                         opfinfo[i].dobj.name);
+                       pg_log_warning("owner of operator family \"%s\" appears to be invalid",
+                                                  opfinfo[i].dobj.name);
        }
 
        PQclear(res);
@@ -5400,9 +5486,6 @@ getAggregates(Archive *fout, int *numAggs)
        int                     i_initaggacl;
        int                     i_initraggacl;
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        /*
         * Find all interesting aggregates.  See comment in getFuncs() for the
         * rationale behind the filtering logic.
@@ -5413,11 +5496,15 @@ getAggregates(Archive *fout, int *numAggs)
                PQExpBuffer racl_subquery = createPQExpBuffer();
                PQExpBuffer initacl_subquery = createPQExpBuffer();
                PQExpBuffer initracl_subquery = createPQExpBuffer();
+               const char *agg_check;
 
                buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
                                                initracl_subquery, "p.proacl", "p.proowner", "'f'",
                                                dopt->binary_upgrade);
 
+               agg_check = (fout->remoteVersion >= 110000 ? "p.prokind = 'a'"
+                                        : "p.proisagg");
+
                appendPQExpBuffer(query, "SELECT p.tableoid, p.oid, "
                                                  "p.proname AS aggname, "
                                                  "p.pronamespace AS aggnamespace, "
@@ -5432,7 +5519,7 @@ getAggregates(Archive *fout, int *numAggs)
                                                  "(p.oid = pip.objoid "
                                                  "AND pip.classoid = 'pg_proc'::regclass "
                                                  "AND pip.objsubid = 0) "
-                                                 "WHERE p.proisagg AND ("
+                                                 "WHERE %s AND ("
                                                  "p.pronamespace != "
                                                  "(SELECT oid FROM pg_namespace "
                                                  "WHERE nspname = 'pg_catalog') OR "
@@ -5441,7 +5528,8 @@ getAggregates(Archive *fout, int *numAggs)
                                                  acl_subquery->data,
                                                  racl_subquery->data,
                                                  initacl_subquery->data,
-                                                 initracl_subquery->data);
+                                                 initracl_subquery->data,
+                                                 agg_check);
                if (dopt->binary_upgrade)
                        appendPQExpBufferStr(query,
                                                                 " OR EXISTS(SELECT 1 FROM pg_depend WHERE "
@@ -5528,8 +5616,8 @@ getAggregates(Archive *fout, int *numAggs)
                                                  atooid(PQgetvalue(res, i, i_aggnamespace)));
                agginfo[i].aggfn.rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
                if (strlen(agginfo[i].aggfn.rolname) == 0)
-                       write_msg(NULL, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n",
-                                         agginfo[i].aggfn.dobj.name);
+                       pg_log_warning("owner of aggregate function \"%s\" appears to be invalid",
+                                                  agginfo[i].aggfn.dobj.name);
                agginfo[i].aggfn.lang = InvalidOid; /* not currently interesting */
                agginfo[i].aggfn.prorettype = InvalidOid;       /* not saved */
                agginfo[i].aggfn.proacl = pg_strdup(PQgetvalue(res, i, i_aggacl));
@@ -5594,9 +5682,6 @@ getFuncs(Archive *fout, int *numFuncs)
        int                     i_initproacl;
        int                     i_initrproacl;
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        /*
         * Find all interesting functions.  This is a bit complicated:
         *
@@ -5625,11 +5710,15 @@ getFuncs(Archive *fout, int *numFuncs)
                PQExpBuffer racl_subquery = createPQExpBuffer();
                PQExpBuffer initacl_subquery = createPQExpBuffer();
                PQExpBuffer initracl_subquery = createPQExpBuffer();
+               const char *not_agg_check;
 
                buildACLQueries(acl_subquery, racl_subquery, initacl_subquery,
                                                initracl_subquery, "p.proacl", "p.proowner", "'f'",
                                                dopt->binary_upgrade);
 
+               not_agg_check = (fout->remoteVersion >= 110000 ? "p.prokind <> 'a'"
+                                                : "NOT p.proisagg");
+
                appendPQExpBuffer(query,
                                                  "SELECT p.tableoid, p.oid, p.proname, p.prolang, "
                                                  "p.pronargs, p.proargtypes, p.prorettype, "
@@ -5644,7 +5733,7 @@ getFuncs(Archive *fout, int *numFuncs)
                                                  "(p.oid = pip.objoid "
                                                  "AND pip.classoid = 'pg_proc'::regclass "
                                                  "AND pip.objsubid = 0) "
-                                                 "WHERE NOT proisagg"
+                                                 "WHERE %s"
                                                  "\n  AND NOT EXISTS (SELECT 1 FROM pg_depend "
                                                  "WHERE classid = 'pg_proc'::regclass AND "
                                                  "objid = p.oid AND deptype = 'i')"
@@ -5664,6 +5753,7 @@ getFuncs(Archive *fout, int *numFuncs)
                                                  initacl_subquery->data,
                                                  initracl_subquery->data,
                                                  username_subquery,
+                                                 not_agg_check,
                                                  g_last_builtin_oid,
                                                  g_last_builtin_oid);
                if (dopt->binary_upgrade)
@@ -5786,9 +5876,8 @@ getFuncs(Archive *fout, int *numFuncs)
                        finfo[i].dobj.dump &= ~DUMP_COMPONENT_ACL;
 
                if (strlen(finfo[i].rolname) == 0)
-                       write_msg(NULL,
-                                         "WARNING: owner of function \"%s\" appears to be invalid\n",
-                                         finfo[i].dobj.name);
+                       pg_log_warning("owner of function \"%s\" appears to be invalid",
+                                                  finfo[i].dobj.name);
        }
 
        PQclear(res);
@@ -5852,9 +5941,7 @@ getTables(Archive *fout, int *numTables)
        int                     i_partkeydef;
        int                     i_ispartition;
        int                     i_partbound;
-
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
+       int                     i_amname;
 
        /*
         * Find all the tables and table-like objects.
@@ -5874,6 +5961,10 @@ getTables(Archive *fout, int *numTables)
         * information about each table, basically just enough to decide if it is
         * interesting. We must fetch all tables in this phase because otherwise
         * we cannot correctly identify inherited columns, owned sequences, etc.
+        *
+        * We purposefully ignore toast OIDs for partitioned tables; the reason is
+        * that versions 10 and 11 have them, but 12 does not, so emitting them
+        * causes the upgrade to fail.
         */
 
        if (fout->remoteVersion >= 90600)
@@ -5881,6 +5972,7 @@ getTables(Archive *fout, int *numTables)
                char       *partkeydef = "NULL";
                char       *ispartition = "false";
                char       *partbound = "NULL";
+               char       *relhasoids = "c.relhasoids";
 
                PQExpBuffer acl_subquery = createPQExpBuffer();
                PQExpBuffer racl_subquery = createPQExpBuffer();
@@ -5904,6 +5996,10 @@ getTables(Archive *fout, int *numTables)
                        partbound = "pg_get_expr(c.relpartbound, c.oid)";
                }
 
+               /* In PG12 upwards WITH OIDS does not exist anymore. */
+               if (fout->remoteVersion >= 120000)
+                       relhasoids = "'f'::bool";
+
                /*
                 * Left join to pick up dependency info linking sequences to their
                 * owning column, if any (note this dependency is AUTO as of 8.2)
@@ -5929,13 +6025,13 @@ getTables(Archive *fout, int *numTables)
                                                  "c.relkind, c.relnamespace, "
                                                  "(%s c.relowner) AS rolname, "
                                                  "c.relchecks, c.relhastriggers, "
-                                                 "c.relhasindex, c.relhasrules, c.relhasoids, "
+                                                 "c.relhasindex, c.relhasrules, %s AS relhasoids, "
                                                  "c.relrowsecurity, c.relforcerowsecurity, "
                                                  "c.relfrozenxid, c.relminmxid, tc.oid AS toid, "
                                                  "tc.relfrozenxid AS tfrozenxid, "
                                                  "tc.relminmxid AS tminmxid, "
                                                  "c.relpersistence, c.relispopulated, "
-                                                 "c.relreplident, c.relpages, "
+                                                 "c.relreplident, c.relpages, am.amname, "
                                                  "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
                                                  "d.refobjid AS owning_tab, "
                                                  "d.refobjsubid AS owning_col, "
@@ -5965,7 +6061,8 @@ getTables(Archive *fout, int *numTables)
                                                  "d.classid = c.tableoid AND d.objid = c.oid AND "
                                                  "d.objsubid = 0 AND "
                                                  "d.refclassid = c.tableoid AND d.deptype IN ('a', 'i')) "
-                                                 "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid) "
+                                                 "LEFT JOIN pg_class tc ON (c.reltoastrelid = tc.oid AND c.relkind <> '%c') "
+                                                 "LEFT JOIN pg_am am ON (c.relam = am.oid) "
                                                  "LEFT JOIN pg_init_privs pip ON "
                                                  "(c.oid = pip.objoid "
                                                  "AND pip.classoid = 'pg_class'::regclass "
@@ -5977,6 +6074,7 @@ getTables(Archive *fout, int *numTables)
                                                  initacl_subquery->data,
                                                  initracl_subquery->data,
                                                  username_subquery,
+                                                 relhasoids,
                                                  RELKIND_SEQUENCE,
                                                  attacl_subquery->data,
                                                  attracl_subquery->data,
@@ -5986,6 +6084,7 @@ getTables(Archive *fout, int *numTables)
                                                  ispartition,
                                                  partbound,
                                                  RELKIND_SEQUENCE,
+                                                 RELKIND_PARTITIONED_TABLE,
                                                  RELKIND_RELATION, RELKIND_SEQUENCE,
                                                  RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
                                                  RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE,
@@ -6022,6 +6121,7 @@ getTables(Archive *fout, int *numTables)
                                                  "tc.relminmxid AS tminmxid, "
                                                  "c.relpersistence, c.relispopulated, "
                                                  "c.relreplident, c.relpages, "
+                                                 "NULL AS amname, "
                                                  "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
                                                  "d.refobjid AS owning_tab, "
                                                  "d.refobjsubid AS owning_col, "
@@ -6071,6 +6171,7 @@ getTables(Archive *fout, int *numTables)
                                                  "tc.relminmxid AS tminmxid, "
                                                  "c.relpersistence, c.relispopulated, "
                                                  "c.relreplident, c.relpages, "
+                                                 "NULL AS amname, "
                                                  "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
                                                  "d.refobjid AS owning_tab, "
                                                  "d.refobjsubid AS owning_col, "
@@ -6120,6 +6221,7 @@ getTables(Archive *fout, int *numTables)
                                                  "tc.relminmxid AS tminmxid, "
                                                  "c.relpersistence, c.relispopulated, "
                                                  "'d' AS relreplident, c.relpages, "
+                                                 "NULL AS amname, "
                                                  "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
                                                  "d.refobjid AS owning_tab, "
                                                  "d.refobjsubid AS owning_col, "
@@ -6169,6 +6271,7 @@ getTables(Archive *fout, int *numTables)
                                                  "0 AS tminmxid, "
                                                  "c.relpersistence, 't' as relispopulated, "
                                                  "'d' AS relreplident, c.relpages, "
+                                                 "NULL AS amname, "
                                                  "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
                                                  "d.refobjid AS owning_tab, "
                                                  "d.refobjsubid AS owning_col, "
@@ -6216,6 +6319,7 @@ getTables(Archive *fout, int *numTables)
                                                  "0 AS tminmxid, "
                                                  "'p' AS relpersistence, 't' as relispopulated, "
                                                  "'d' AS relreplident, c.relpages, "
+                                                 "NULL AS amname, "
                                                  "CASE WHEN c.reloftype <> 0 THEN c.reloftype::pg_catalog.regtype ELSE NULL END AS reloftype, "
                                                  "d.refobjid AS owning_tab, "
                                                  "d.refobjsubid AS owning_col, "
@@ -6262,6 +6366,7 @@ getTables(Archive *fout, int *numTables)
                                                  "0 AS tminmxid, "
                                                  "'p' AS relpersistence, 't' as relispopulated, "
                                                  "'d' AS relreplident, c.relpages, "
+                                                 "NULL AS amname, "
                                                  "NULL AS reloftype, "
                                                  "d.refobjid AS owning_tab, "
                                                  "d.refobjsubid AS owning_col, "
@@ -6308,6 +6413,7 @@ getTables(Archive *fout, int *numTables)
                                                  "0 AS tminmxid, "
                                                  "'p' AS relpersistence, 't' as relispopulated, "
                                                  "'d' AS relreplident, c.relpages, "
+                                                 "NULL AS amname, "
                                                  "NULL AS reloftype, "
                                                  "d.refobjid AS owning_tab, "
                                                  "d.refobjsubid AS owning_col, "
@@ -6353,6 +6459,7 @@ getTables(Archive *fout, int *numTables)
                                                  "0 AS tfrozenxid, 0 AS tminmxid,"
                                                  "'p' AS relpersistence, 't' as relispopulated, "
                                                  "'d' AS relreplident, relpages, "
+                                                 "NULL AS amname, "
                                                  "NULL AS reloftype, "
                                                  "d.refobjid AS owning_tab, "
                                                  "d.refobjsubid AS owning_col, "
@@ -6432,6 +6539,7 @@ getTables(Archive *fout, int *numTables)
        i_partkeydef = PQfnumber(res, "partkeydef");
        i_ispartition = PQfnumber(res, "ispartition");
        i_partbound = PQfnumber(res, "partbound");
+       i_amname = PQfnumber(res, "amname");
 
        if (dopt->lockWaitTimeout)
        {
@@ -6501,6 +6609,10 @@ getTables(Archive *fout, int *numTables)
                else
                        tblinfo[i].checkoption = pg_strdup(PQgetvalue(res, i, i_checkoption));
                tblinfo[i].toast_reloptions = pg_strdup(PQgetvalue(res, i, i_toastreloptions));
+               if (PQgetisnull(res, i, i_amname))
+                       tblinfo[i].amname = NULL;
+               else
+                       tblinfo[i].amname = pg_strdup(PQgetvalue(res, i, i_amname));
 
                /* other fields were zeroed above */
 
@@ -6548,7 +6660,8 @@ getTables(Archive *fout, int *numTables)
                 * alterations to parent tables.
                 *
                 * NOTE: it'd be kinda nice to lock other relations too, not only
-                * plain tables, but the backend doesn't presently allow that.
+                * plain or partitioned tables, but the backend doesn't presently
+                * allow that.
                 *
                 * We only need to lock the table for certain components; see
                 * pg_dump.h
@@ -6561,16 +6674,14 @@ getTables(Archive *fout, int *numTables)
                        resetPQExpBuffer(query);
                        appendPQExpBuffer(query,
                                                          "LOCK TABLE %s IN ACCESS SHARE MODE",
-                                                         fmtQualifiedId(fout->remoteVersion,
-                                                                                        tblinfo[i].dobj.namespace->dobj.name,
-                                                                                        tblinfo[i].dobj.name));
+                                                         fmtQualifiedDumpable(&tblinfo[i]));
                        ExecuteSqlStatement(fout, query->data);
                }
 
                /* Emit notice if join for owner failed */
                if (strlen(tblinfo[i].rolname) == 0)
-                       write_msg(NULL, "WARNING: owner of table \"%s\" appears to be invalid\n",
-                                         tblinfo[i].dobj.name);
+                       pg_log_warning("owner of table \"%s\" appears to be invalid",
+                                                  tblinfo[i].dobj.name);
        }
 
        if (dopt->lockWaitTimeout)
@@ -6611,12 +6722,24 @@ getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables)
 
                owning_tab = findTableByOid(seqinfo->owning_tab);
                if (owning_tab == NULL)
-                       exit_horribly(NULL, "failed sanity check, parent table with OID %u of sequence with OID %u not found\n",
-                                                 seqinfo->owning_tab, seqinfo->dobj.catId.oid);
+                       fatal("failed sanity check, parent table with OID %u of sequence with OID %u not found",
+                                 seqinfo->owning_tab, seqinfo->dobj.catId.oid);
+
+               /*
+                * Only dump identity sequences if we're going to dump the table that
+                * it belongs to.
+                */
+               if (owning_tab->dobj.dump == DUMP_COMPONENT_NONE &&
+                       seqinfo->is_identity_sequence)
+               {
+                       seqinfo->dobj.dump = DUMP_COMPONENT_NONE;
+                       continue;
+               }
 
                /*
-                * We need to dump the components that are being dumped for the table
-                * and any components which the sequence is explicitly marked with.
+                * Otherwise we need to dump the components that are being dumped for
+                * the table and any components which the sequence is explicitly
+                * marked with.
                 *
                 * We can't simply use the set of components which are being dumped
                 * for the table as the table might be in an extension (and only the
@@ -6655,14 +6778,9 @@ getInherits(Archive *fout, int *numInherits)
        int                     i_inhrelid;
        int                     i_inhparent;
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        /*
         * Find all the inheritance information, excluding implicit inheritance
-        * via partitioning.  We handle that case using getPartitions(), because
-        * we want more information about partitions than just the parent-child
-        * relationship.
+        * via partitioning.
         */
        appendPQExpBufferStr(query, "SELECT inhrelid, inhparent FROM pg_inherits");
 
@@ -6711,7 +6829,8 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
                                i_indexname,
                                i_parentidx,
                                i_indexdef,
-                               i_indnkeys,
+                               i_indnkeyatts,
+                               i_indnatts,
                                i_indkey,
                                i_indisclustered,
                                i_indisreplident,
@@ -6724,7 +6843,8 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
                                i_condef,
                                i_tablespace,
                                i_indreloptions,
-                               i_relpages;
+                               i_indstatcols,
+                               i_indstatvals;
        int                     ntups;
 
        for (i = 0; i < numTables; i++)
@@ -6744,13 +6864,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
                        !tbinfo->interesting)
                        continue;
 
-               if (g_verbose)
-                       write_msg(NULL, "reading indexes for table \"%s.%s\"\n",
-                                         tbinfo->dobj.namespace->dobj.name,
-                                         tbinfo->dobj.name);
-
-               /* Make sure we are in proper schema so indexdef is right */
-               selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
+               pg_log_info("reading indexes for table \"%s.%s\"",
+                                       tbinfo->dobj.namespace->dobj.name,
+                                       tbinfo->dobj.name);
 
                /*
                 * The point of the messy-looking outer join is to find a constraint
@@ -6771,16 +6887,25 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
                                                          "t.relname AS indexname, "
                                                          "inh.inhparent AS parentidx, "
                                                          "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
-                                                         "t.relnatts AS indnkeys, "
+                                                         "i.indnkeyatts AS indnkeyatts, "
+                                                         "i.indnatts AS indnatts, "
                                                          "i.indkey, i.indisclustered, "
-                                                         "i.indisreplident, t.relpages, "
+                                                         "i.indisreplident, "
                                                          "c.contype, c.conname, "
                                                          "c.condeferrable, c.condeferred, "
                                                          "c.tableoid AS contableoid, "
                                                          "c.oid AS conoid, "
                                                          "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
                                                          "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
-                                                         "t.reloptions AS indreloptions "
+                                                         "t.reloptions AS indreloptions, "
+                                                         "(SELECT pg_catalog.array_agg(attnum ORDER BY attnum) "
+                                                         "  FROM pg_catalog.pg_attribute "
+                                                         "  WHERE attrelid = i.indexrelid AND "
+                                                         "    attstattarget >= 0) AS indstatcols,"
+                                                         "(SELECT pg_catalog.array_agg(attstattarget ORDER BY attnum) "
+                                                         "  FROM pg_catalog.pg_attribute "
+                                                         "  WHERE attrelid = i.indexrelid AND "
+                                                         "    attstattarget >= 0) AS indstatvals "
                                                          "FROM pg_catalog.pg_index i "
                                                          "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
                                                          "JOIN pg_catalog.pg_class t2 ON (t2.oid = i.indrelid) "
@@ -6807,16 +6932,19 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
                                                          "t.relname AS indexname, "
                                                          "0 AS parentidx, "
                                                          "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
-                                                         "t.relnatts AS indnkeys, "
+                                                         "i.indnatts AS indnkeyatts, "
+                                                         "i.indnatts AS indnatts, "
                                                          "i.indkey, i.indisclustered, "
-                                                         "i.indisreplident, t.relpages, "
+                                                         "i.indisreplident, "
                                                          "c.contype, c.conname, "
                                                          "c.condeferrable, c.condeferred, "
                                                          "c.tableoid AS contableoid, "
                                                          "c.oid AS conoid, "
                                                          "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
                                                          "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
-                                                         "t.reloptions AS indreloptions "
+                                                         "t.reloptions AS indreloptions, "
+                                                         "'' AS indstatcols, "
+                                                         "'' AS indstatvals "
                                                          "FROM pg_catalog.pg_index i "
                                                          "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
                                                          "LEFT JOIN pg_catalog.pg_constraint c "
@@ -6839,16 +6967,19 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
                                                          "t.relname AS indexname, "
                                                          "0 AS parentidx, "
                                                          "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
-                                                         "t.relnatts AS indnkeys, "
+                                                         "i.indnatts AS indnkeyatts, "
+                                                         "i.indnatts AS indnatts, "
                                                          "i.indkey, i.indisclustered, "
-                                                         "false AS indisreplident, t.relpages, "
+                                                         "false AS indisreplident, "
                                                          "c.contype, c.conname, "
                                                          "c.condeferrable, c.condeferred, "
                                                          "c.tableoid AS contableoid, "
                                                          "c.oid AS conoid, "
                                                          "pg_catalog.pg_get_constraintdef(c.oid, false) AS condef, "
                                                          "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
-                                                         "t.reloptions AS indreloptions "
+                                                         "t.reloptions AS indreloptions, "
+                                                         "'' AS indstatcols, "
+                                                         "'' AS indstatvals "
                                                          "FROM pg_catalog.pg_index i "
                                                          "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
                                                          "LEFT JOIN pg_catalog.pg_constraint c "
@@ -6867,16 +6998,19 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
                                                          "t.relname AS indexname, "
                                                          "0 AS parentidx, "
                                                          "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
-                                                         "t.relnatts AS indnkeys, "
+                                                         "i.indnatts AS indnkeyatts, "
+                                                         "i.indnatts AS indnatts, "
                                                          "i.indkey, i.indisclustered, "
-                                                         "false AS indisreplident, t.relpages, "
+                                                         "false AS indisreplident, "
                                                          "c.contype, c.conname, "
                                                          "c.condeferrable, c.condeferred, "
                                                          "c.tableoid AS contableoid, "
                                                          "c.oid AS conoid, "
                                                          "null AS condef, "
                                                          "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
-                                                         "t.reloptions AS indreloptions "
+                                                         "t.reloptions AS indreloptions, "
+                                                         "'' AS indstatcols, "
+                                                         "'' AS indstatvals "
                                                          "FROM pg_catalog.pg_index i "
                                                          "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
                                                          "LEFT JOIN pg_catalog.pg_depend d "
@@ -6898,16 +7032,19 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
                                                          "t.relname AS indexname, "
                                                          "0 AS parentidx, "
                                                          "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
-                                                         "t.relnatts AS indnkeys, "
+                                                         "t.relnatts AS indnkeyatts, "
+                                                         "t.relnatts AS indnatts, "
                                                          "i.indkey, i.indisclustered, "
-                                                         "false AS indisreplident, t.relpages, "
+                                                         "false AS indisreplident, "
                                                          "c.contype, c.conname, "
                                                          "c.condeferrable, c.condeferred, "
                                                          "c.tableoid AS contableoid, "
                                                          "c.oid AS conoid, "
                                                          "null AS condef, "
                                                          "(SELECT spcname FROM pg_catalog.pg_tablespace s WHERE s.oid = t.reltablespace) AS tablespace, "
-                                                         "null AS indreloptions "
+                                                         "null AS indreloptions, "
+                                                         "'' AS indstatcols, "
+                                                         "'' AS indstatvals "
                                                          "FROM pg_catalog.pg_index i "
                                                          "JOIN pg_catalog.pg_class t ON (t.oid = i.indexrelid) "
                                                          "LEFT JOIN pg_catalog.pg_depend d "
@@ -6931,11 +7068,11 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
                i_indexname = PQfnumber(res, "indexname");
                i_parentidx = PQfnumber(res, "parentidx");
                i_indexdef = PQfnumber(res, "indexdef");
-               i_indnkeys = PQfnumber(res, "indnkeys");
+               i_indnkeyatts = PQfnumber(res, "indnkeyatts");
+               i_indnatts = PQfnumber(res, "indnatts");
                i_indkey = PQfnumber(res, "indkey");
                i_indisclustered = PQfnumber(res, "indisclustered");
                i_indisreplident = PQfnumber(res, "indisreplident");
-               i_relpages = PQfnumber(res, "relpages");
                i_contype = PQfnumber(res, "contype");
                i_conname = PQfnumber(res, "conname");
                i_condeferrable = PQfnumber(res, "condeferrable");
@@ -6945,6 +7082,8 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
                i_condef = PQfnumber(res, "condef");
                i_tablespace = PQfnumber(res, "tablespace");
                i_indreloptions = PQfnumber(res, "indreloptions");
+               i_indstatcols = PQfnumber(res, "indstatcols");
+               i_indstatvals = PQfnumber(res, "indstatvals");
 
                tbinfo->indexes = indxinfo =
                        (IndxInfo *) pg_malloc(ntups * sizeof(IndxInfo));
@@ -6964,16 +7103,18 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
                        indxinfo[j].dobj.namespace = tbinfo->dobj.namespace;
                        indxinfo[j].indextable = tbinfo;
                        indxinfo[j].indexdef = pg_strdup(PQgetvalue(res, j, i_indexdef));
-                       indxinfo[j].indnkeys = atoi(PQgetvalue(res, j, i_indnkeys));
+                       indxinfo[j].indnkeyattrs = atoi(PQgetvalue(res, j, i_indnkeyatts));
+                       indxinfo[j].indnattrs = atoi(PQgetvalue(res, j, i_indnatts));
                        indxinfo[j].tablespace = pg_strdup(PQgetvalue(res, j, i_tablespace));
                        indxinfo[j].indreloptions = pg_strdup(PQgetvalue(res, j, i_indreloptions));
-                       indxinfo[j].indkeys = (Oid *) pg_malloc(indxinfo[j].indnkeys * sizeof(Oid));
+                       indxinfo[j].indstatcols = pg_strdup(PQgetvalue(res, j, i_indstatcols));
+                       indxinfo[j].indstatvals = pg_strdup(PQgetvalue(res, j, i_indstatvals));
+                       indxinfo[j].indkeys = (Oid *) pg_malloc(indxinfo[j].indnattrs * sizeof(Oid));
                        parseOidArray(PQgetvalue(res, j, i_indkey),
-                                                 indxinfo[j].indkeys, indxinfo[j].indnkeys);
+                                                 indxinfo[j].indkeys, indxinfo[j].indnattrs);
                        indxinfo[j].indisclustered = (PQgetvalue(res, j, i_indisclustered)[0] == 't');
                        indxinfo[j].indisreplident = (PQgetvalue(res, j, i_indisreplident)[0] == 't');
                        indxinfo[j].parentidx = atooid(PQgetvalue(res, j, i_parentidx));
-                       indxinfo[j].relpages = atoi(PQgetvalue(res, j, i_relpages));
                        contype = *(PQgetvalue(res, j, i_contype));
 
                        if (contype == 'p' || contype == 'u' || contype == 'x')
@@ -7045,9 +7186,6 @@ getExtendedStatistics(Archive *fout)
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBuffer(query, "SELECT tableoid, oid, stxname, "
                                          "stxnamespace, (%s stxowner) AS rolname "
                                          "FROM pg_catalog.pg_statistic_ext",
@@ -7118,29 +7256,37 @@ getConstraints(Archive *fout, TableInfo tblinfo[], int numTables)
        {
                TableInfo  *tbinfo = &tblinfo[i];
 
-               if (!tbinfo->hastriggers ||
+               /*
+                * For partitioned tables, foreign keys have no triggers so they must
+                * be included anyway in case some foreign keys are defined.
+                */
+               if ((!tbinfo->hastriggers &&
+                        tbinfo->relkind != RELKIND_PARTITIONED_TABLE) ||
                        !(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
                        continue;
 
-               if (g_verbose)
-                       write_msg(NULL, "reading foreign key constraints for table \"%s.%s\"\n",
-                                         tbinfo->dobj.namespace->dobj.name,
-                                         tbinfo->dobj.name);
-
-               /*
-                * select table schema to ensure constraint expr is qualified if
-                * needed
-                */
-               selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
+               pg_log_info("reading foreign key constraints for table \"%s.%s\"",
+                                       tbinfo->dobj.namespace->dobj.name,
+                                       tbinfo->dobj.name);
 
                resetPQExpBuffer(query);
-               appendPQExpBuffer(query,
-                                                 "SELECT tableoid, oid, conname, confrelid, "
-                                                 "pg_catalog.pg_get_constraintdef(oid) AS condef "
-                                                 "FROM pg_catalog.pg_constraint "
-                                                 "WHERE conrelid = '%u'::pg_catalog.oid "
-                                                 "AND contype = 'f'",
-                                                 tbinfo->dobj.catId.oid);
+               if (fout->remoteVersion >= 110000)
+                       appendPQExpBuffer(query,
+                                                         "SELECT tableoid, oid, conname, confrelid, "
+                                                         "pg_catalog.pg_get_constraintdef(oid) AS condef "
+                                                         "FROM pg_catalog.pg_constraint "
+                                                         "WHERE conrelid = '%u'::pg_catalog.oid "
+                                                         "AND conparentid = 0 "
+                                                         "AND contype = 'f'",
+                                                         tbinfo->dobj.catId.oid);
+               else
+                       appendPQExpBuffer(query,
+                                                         "SELECT tableoid, oid, conname, confrelid, "
+                                                         "pg_catalog.pg_get_constraintdef(oid) AS condef "
+                                                         "FROM pg_catalog.pg_constraint "
+                                                         "WHERE conrelid = '%u'::pg_catalog.oid "
+                                                         "AND contype = 'f'",
+                                                         tbinfo->dobj.catId.oid);
                res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
                ntups = PQntuples(res);
@@ -7197,12 +7343,6 @@ getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
                                i_consrc;
        int                     ntups;
 
-       /*
-        * select appropriate schema to ensure names in constraint are properly
-        * qualified
-        */
-       selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
-
        query = createPQExpBuffer();
 
        if (fout->remoteVersion >= 90100)
@@ -7297,9 +7437,6 @@ getRules(Archive *fout, int *numRules)
        int                     i_is_instead;
        int                     i_ev_enabled;
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        if (fout->remoteVersion >= 80300)
        {
                appendPQExpBufferStr(query, "SELECT "
@@ -7347,8 +7484,8 @@ getRules(Archive *fout, int *numRules)
                ruletableoid = atooid(PQgetvalue(res, i, i_ruletable));
                ruleinfo[i].ruletable = findTableByOid(ruletableoid);
                if (ruleinfo[i].ruletable == NULL)
-                       exit_horribly(NULL, "failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found\n",
-                                                 ruletableoid, ruleinfo[i].dobj.catId.oid);
+                       fatal("failed sanity check, parent table with OID %u of pg_rewrite entry with OID %u not found",
+                                 ruletableoid, ruleinfo[i].dobj.catId.oid);
                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));
@@ -7430,15 +7567,9 @@ getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
                        !(tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
                        continue;
 
-               if (g_verbose)
-                       write_msg(NULL, "reading triggers for table \"%s.%s\"\n",
-                                         tbinfo->dobj.namespace->dobj.name,
-                                         tbinfo->dobj.name);
-
-               /*
-                * select table schema to ensure regproc name is qualified if needed
-                */
-               selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
+               pg_log_info("reading triggers for table \"%s.%s\"",
+                                       tbinfo->dobj.namespace->dobj.name,
+                                       tbinfo->dobj.name);
 
                resetPQExpBuffer(query);
                if (fout->remoteVersion >= 90000)
@@ -7569,10 +7700,10 @@ getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
                                        if (OidIsValid(tginfo[j].tgconstrrelid))
                                        {
                                                if (PQgetisnull(res, j, i_tgconstrrelname))
-                                                       exit_horribly(NULL, "query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)\n",
-                                                                                 tginfo[j].dobj.name,
-                                                                                 tbinfo->dobj.name,
-                                                                                 tginfo[j].tgconstrrelid);
+                                                       fatal("query produced null referenced table name for foreign key trigger \"%s\" on table \"%s\" (OID of table: %u)",
+                                                                 tginfo[j].dobj.name,
+                                                                 tbinfo->dobj.name,
+                                                                 tginfo[j].tgconstrrelid);
                                                tginfo[j].tgconstrrelname = pg_strdup(PQgetvalue(res, j, i_tgconstrrelname));
                                        }
                                        else
@@ -7623,9 +7754,6 @@ getEventTriggers(Archive *fout, int *numEventTriggers)
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBuffer(query,
                                          "SELECT e.tableoid, e.oid, evtname, evtenabled, "
                                          "evtevent, (%s evtowner) AS evtowner, "
@@ -7713,9 +7841,6 @@ getProcLangs(Archive *fout, int *numProcLangs)
        int                     i_initrlanacl;
        int                     i_lanowner;
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        if (fout->remoteVersion >= 90600)
        {
                PQExpBuffer acl_subquery = createPQExpBuffer();
@@ -7888,9 +8013,6 @@ getCasts(Archive *fout, int *numCasts)
        int                     i_castcontext;
        int                     i_castmethod;
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        if (fout->remoteVersion >= 80400)
        {
                appendPQExpBufferStr(query, "SELECT tableoid, oid, "
@@ -8012,13 +8134,10 @@ getTransforms(Archive *fout, int *numTransforms)
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
-       appendPQExpBuffer(query, "SELECT tableoid, oid, "
-                                         "trftype, trflang, trffromsql::oid, trftosql::oid "
-                                         "FROM pg_transform "
-                                         "ORDER BY 3,4");
+       appendPQExpBufferStr(query, "SELECT tableoid, oid, "
+                                                "trftype, trflang, trffromsql::oid, trftosql::oid "
+                                                "FROM pg_transform "
+                                                "ORDER BY 3,4");
 
        res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
@@ -8105,6 +8224,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
        int                     i_attnotnull;
        int                     i_atthasdef;
        int                     i_attidentity;
+       int                     i_attgenerated;
        int                     i_attisdropped;
        int                     i_attlen;
        int                     i_attalign;
@@ -8112,6 +8232,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
        int                     i_attoptions;
        int                     i_attcollation;
        int                     i_attfdwoptions;
+       int                     i_attmissingval;
        PGresult   *res;
        int                     ntups;
        bool            hasdefaults;
@@ -8128,137 +8249,98 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
                if (!tbinfo->interesting)
                        continue;
 
-               /*
-                * Make sure we are in proper schema for this table; this allows
-                * correct retrieval of formatted type names and default exprs
-                */
-               selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
-
                /* find all the user attributes and their types */
 
                /*
                 * we must read the attribute names in attribute number order! because
                 * we will use the attnum to index into the attnames array later.
                 */
-               if (g_verbose)
-                       write_msg(NULL, "finding the columns and types of table \"%s.%s\"\n",
-                                         tbinfo->dobj.namespace->dobj.name,
-                                         tbinfo->dobj.name);
+               pg_log_info("finding the columns and types of table \"%s.%s\"",
+                                       tbinfo->dobj.namespace->dobj.name,
+                                       tbinfo->dobj.name);
 
                resetPQExpBuffer(q);
 
+               appendPQExpBufferStr(q,
+                                                        "SELECT\n"
+                                                        "a.attnum,\n"
+                                                        "a.attname,\n"
+                                                        "a.atttypmod,\n"
+                                                        "a.attstattarget,\n"
+                                                        "a.attstorage,\n"
+                                                        "t.typstorage,\n"
+                                                        "a.attnotnull,\n"
+                                                        "a.atthasdef,\n"
+                                                        "a.attisdropped,\n"
+                                                        "a.attlen,\n"
+                                                        "a.attalign,\n"
+                                                        "a.attislocal,\n"
+                                                        "pg_catalog.format_type(t.oid, a.atttypmod) AS atttypname,\n");
+
+               if (fout->remoteVersion >= 120000)
+                       appendPQExpBufferStr(q,
+                                                                "a.attgenerated,\n");
+               else
+                       appendPQExpBufferStr(q,
+                                                                "'' AS attgenerated,\n");
+
+               if (fout->remoteVersion >= 110000)
+                       appendPQExpBufferStr(q,
+                                                                "CASE WHEN a.atthasmissing AND NOT a.attisdropped "
+                                                                "THEN a.attmissingval ELSE null END AS attmissingval,\n");
+               else
+                       appendPQExpBufferStr(q,
+                                                                "NULL AS attmissingval,\n");
+
                if (fout->remoteVersion >= 100000)
+                       appendPQExpBufferStr(q,
+                                                                "a.attidentity,\n");
+               else
+                       appendPQExpBufferStr(q,
+                                                                "'' AS attidentity,\n");
+
+               if (fout->remoteVersion >= 90200)
+                       appendPQExpBufferStr(q,
+                                                                "pg_catalog.array_to_string(ARRAY("
+                                                                "SELECT pg_catalog.quote_ident(option_name) || "
+                                                                "' ' || pg_catalog.quote_literal(option_value) "
+                                                                "FROM pg_catalog.pg_options_to_table(attfdwoptions) "
+                                                                "ORDER BY option_name"
+                                                                "), E',\n    ') AS attfdwoptions,\n");
+               else
+                       appendPQExpBufferStr(q,
+                                                                "'' AS attfdwoptions,\n");
+
+               if (fout->remoteVersion >= 90100)
                {
                        /*
-                        * attidentity is new in version 10.
-                        */
-                       appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
-                                                         "a.attstattarget, a.attstorage, t.typstorage, "
-                                                         "a.attnotnull, a.atthasdef, a.attisdropped, "
-                                                         "a.attlen, a.attalign, a.attislocal, "
-                                                         "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
-                                                         "array_to_string(a.attoptions, ', ') AS attoptions, "
-                                                         "CASE WHEN a.attcollation <> t.typcollation "
-                                                         "THEN a.attcollation ELSE 0 END AS attcollation, "
-                                                         "a.attidentity, "
-                                                         "pg_catalog.array_to_string(ARRAY("
-                                                         "SELECT pg_catalog.quote_ident(option_name) || "
-                                                         "' ' || pg_catalog.quote_literal(option_value) "
-                                                         "FROM pg_catalog.pg_options_to_table(attfdwoptions) "
-                                                         "ORDER BY option_name"
-                                                         "), E',\n    ') AS attfdwoptions "
-                                                         "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
-                                                         "ON a.atttypid = t.oid "
-                                                         "WHERE a.attrelid = '%u'::pg_catalog.oid "
-                                                         "AND a.attnum > 0::pg_catalog.int2 "
-                                                         "ORDER BY a.attnum",
-                                                         tbinfo->dobj.catId.oid);
-               }
-               else if (fout->remoteVersion >= 90200)
-               {
-                       /*
-                        * attfdwoptions is new in 9.2.
-                        */
-                       appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
-                                                         "a.attstattarget, a.attstorage, t.typstorage, "
-                                                         "a.attnotnull, a.atthasdef, a.attisdropped, "
-                                                         "a.attlen, a.attalign, a.attislocal, "
-                                                         "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
-                                                         "array_to_string(a.attoptions, ', ') AS attoptions, "
-                                                         "CASE WHEN a.attcollation <> t.typcollation "
-                                                         "THEN a.attcollation ELSE 0 END AS attcollation, "
-                                                         "pg_catalog.array_to_string(ARRAY("
-                                                         "SELECT pg_catalog.quote_ident(option_name) || "
-                                                         "' ' || pg_catalog.quote_literal(option_value) "
-                                                         "FROM pg_catalog.pg_options_to_table(attfdwoptions) "
-                                                         "ORDER BY option_name"
-                                                         "), E',\n    ') AS attfdwoptions "
-                                                         "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
-                                                         "ON a.atttypid = t.oid "
-                                                         "WHERE a.attrelid = '%u'::pg_catalog.oid "
-                                                         "AND a.attnum > 0::pg_catalog.int2 "
-                                                         "ORDER BY a.attnum",
-                                                         tbinfo->dobj.catId.oid);
-               }
-               else if (fout->remoteVersion >= 90100)
-               {
-                       /*
-                        * attcollation is new in 9.1.  Since we only want to dump COLLATE
-                        * clauses for attributes whose collation is different from their
-                        * type's default, we use a CASE here to suppress uninteresting
-                        * attcollations cheaply.
+                        * Since we only want to dump COLLATE clauses for attributes whose
+                        * collation is different from their type's default, we use a CASE
+                        * here to suppress uninteresting attcollations cheaply.
                         */
-                       appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
-                                                         "a.attstattarget, a.attstorage, t.typstorage, "
-                                                         "a.attnotnull, a.atthasdef, a.attisdropped, "
-                                                         "a.attlen, a.attalign, a.attislocal, "
-                                                         "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
-                                                         "array_to_string(a.attoptions, ', ') AS attoptions, "
-                                                         "CASE WHEN a.attcollation <> t.typcollation "
-                                                         "THEN a.attcollation ELSE 0 END AS attcollation, "
-                                                         "NULL AS attfdwoptions "
-                                                         "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
-                                                         "ON a.atttypid = t.oid "
-                                                         "WHERE a.attrelid = '%u'::pg_catalog.oid "
-                                                         "AND a.attnum > 0::pg_catalog.int2 "
-                                                         "ORDER BY a.attnum",
-                                                         tbinfo->dobj.catId.oid);
-               }
-               else if (fout->remoteVersion >= 90000)
-               {
-                       /* attoptions is new in 9.0 */
-                       appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
-                                                         "a.attstattarget, a.attstorage, t.typstorage, "
-                                                         "a.attnotnull, a.atthasdef, a.attisdropped, "
-                                                         "a.attlen, a.attalign, a.attislocal, "
-                                                         "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
-                                                         "array_to_string(a.attoptions, ', ') AS attoptions, "
-                                                         "0 AS attcollation, "
-                                                         "NULL AS attfdwoptions "
-                                                         "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
-                                                         "ON a.atttypid = t.oid "
-                                                         "WHERE a.attrelid = '%u'::pg_catalog.oid "
-                                                         "AND a.attnum > 0::pg_catalog.int2 "
-                                                         "ORDER BY a.attnum",
-                                                         tbinfo->dobj.catId.oid);
+                       appendPQExpBufferStr(q,
+                                                                "CASE WHEN a.attcollation <> t.typcollation "
+                                                                "THEN a.attcollation ELSE 0 END AS attcollation,\n");
                }
                else
-               {
-                       /* need left join here to not fail on dropped columns ... */
-                       appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, "
-                                                         "a.attstattarget, a.attstorage, t.typstorage, "
-                                                         "a.attnotnull, a.atthasdef, a.attisdropped, "
-                                                         "a.attlen, a.attalign, a.attislocal, "
-                                                         "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, "
-                                                         "'' AS attoptions, 0 AS attcollation, "
-                                                         "NULL AS attfdwoptions "
-                                                         "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
-                                                         "ON a.atttypid = t.oid "
-                                                         "WHERE a.attrelid = '%u'::pg_catalog.oid "
-                                                         "AND a.attnum > 0::pg_catalog.int2 "
-                                                         "ORDER BY a.attnum",
-                                                         tbinfo->dobj.catId.oid);
-               }
+                       appendPQExpBufferStr(q,
+                                                                "0 AS attcollation,\n");
+
+               if (fout->remoteVersion >= 90000)
+                       appendPQExpBufferStr(q,
+                                                                "array_to_string(a.attoptions, ', ') AS attoptions\n");
+               else
+                       appendPQExpBufferStr(q,
+                                                                "'' AS attoptions\n");
+
+               /* need left join here to not fail on dropped columns ... */
+               appendPQExpBuffer(q,
+                                                 "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
+                                                 "ON a.atttypid = t.oid\n"
+                                                 "WHERE a.attrelid = '%u'::pg_catalog.oid "
+                                                 "AND a.attnum > 0::pg_catalog.int2\n"
+                                                 "ORDER BY a.attnum",
+                                                 tbinfo->dobj.catId.oid);
 
                res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
 
@@ -8274,6 +8356,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
                i_attnotnull = PQfnumber(res, "attnotnull");
                i_atthasdef = PQfnumber(res, "atthasdef");
                i_attidentity = PQfnumber(res, "attidentity");
+               i_attgenerated = PQfnumber(res, "attgenerated");
                i_attisdropped = PQfnumber(res, "attisdropped");
                i_attlen = PQfnumber(res, "attlen");
                i_attalign = PQfnumber(res, "attalign");
@@ -8281,6 +8364,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
                i_attoptions = PQfnumber(res, "attoptions");
                i_attcollation = PQfnumber(res, "attcollation");
                i_attfdwoptions = PQfnumber(res, "attfdwoptions");
+               i_attmissingval = PQfnumber(res, "attmissingval");
 
                tbinfo->numatts = ntups;
                tbinfo->attnames = (char **) pg_malloc(ntups * sizeof(char *));
@@ -8290,6 +8374,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
                tbinfo->attstorage = (char *) pg_malloc(ntups * sizeof(char));
                tbinfo->typstorage = (char *) pg_malloc(ntups * sizeof(char));
                tbinfo->attidentity = (char *) pg_malloc(ntups * sizeof(char));
+               tbinfo->attgenerated = (char *) pg_malloc(ntups * sizeof(char));
                tbinfo->attisdropped = (bool *) pg_malloc(ntups * sizeof(bool));
                tbinfo->attlen = (int *) pg_malloc(ntups * sizeof(int));
                tbinfo->attalign = (char *) pg_malloc(ntups * sizeof(char));
@@ -8297,6 +8382,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
                tbinfo->attoptions = (char **) pg_malloc(ntups * sizeof(char *));
                tbinfo->attcollation = (Oid *) pg_malloc(ntups * sizeof(Oid));
                tbinfo->attfdwoptions = (char **) pg_malloc(ntups * sizeof(char *));
+               tbinfo->attmissingval = (char **) pg_malloc(ntups * sizeof(char *));
                tbinfo->notnull = (bool *) pg_malloc(ntups * sizeof(bool));
                tbinfo->inhNotNull = (bool *) pg_malloc(ntups * sizeof(bool));
                tbinfo->attrdefs = (AttrDefInfo **) pg_malloc(ntups * sizeof(AttrDefInfo *));
@@ -8305,16 +8391,16 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
                for (j = 0; j < ntups; j++)
                {
                        if (j + 1 != atoi(PQgetvalue(res, j, i_attnum)))
-                               exit_horribly(NULL,
-                                                         "invalid column numbering in table \"%s\"\n",
-                                                         tbinfo->dobj.name);
+                               fatal("invalid column numbering in table \"%s\"",
+                                         tbinfo->dobj.name);
                        tbinfo->attnames[j] = pg_strdup(PQgetvalue(res, j, i_attname));
                        tbinfo->atttypnames[j] = pg_strdup(PQgetvalue(res, j, i_atttypname));
                        tbinfo->atttypmod[j] = atoi(PQgetvalue(res, j, i_atttypmod));
                        tbinfo->attstattarget[j] = atoi(PQgetvalue(res, j, i_attstattarget));
                        tbinfo->attstorage[j] = *(PQgetvalue(res, j, i_attstorage));
                        tbinfo->typstorage[j] = *(PQgetvalue(res, j, i_typstorage));
-                       tbinfo->attidentity[j] = (i_attidentity >= 0 ? *(PQgetvalue(res, j, i_attidentity)) : '\0');
+                       tbinfo->attidentity[j] = *(PQgetvalue(res, j, i_attidentity));
+                       tbinfo->attgenerated[j] = *(PQgetvalue(res, j, i_attgenerated));
                        tbinfo->needs_override = tbinfo->needs_override || (tbinfo->attidentity[j] == ATTRIBUTE_IDENTITY_ALWAYS);
                        tbinfo->attisdropped[j] = (PQgetvalue(res, j, i_attisdropped)[0] == 't');
                        tbinfo->attlen[j] = atoi(PQgetvalue(res, j, i_attlen));
@@ -8324,6 +8410,7 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
                        tbinfo->attoptions[j] = pg_strdup(PQgetvalue(res, j, i_attoptions));
                        tbinfo->attcollation[j] = atooid(PQgetvalue(res, j, i_attcollation));
                        tbinfo->attfdwoptions[j] = pg_strdup(PQgetvalue(res, j, i_attfdwoptions));
+                       tbinfo->attmissingval[j] = pg_strdup(PQgetvalue(res, j, i_attmissingval));
                        tbinfo->attrdefs[j] = NULL; /* fix below */
                        if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
                                hasdefaults = true;
@@ -8341,10 +8428,9 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
                        AttrDefInfo *attrdefs;
                        int                     numDefaults;
 
-                       if (g_verbose)
-                               write_msg(NULL, "finding default expressions of table \"%s.%s\"\n",
-                                                 tbinfo->dobj.namespace->dobj.name,
-                                                 tbinfo->dobj.name);
+                       pg_log_info("finding default expressions of table \"%s.%s\"",
+                                               tbinfo->dobj.namespace->dobj.name,
+                                               tbinfo->dobj.name);
 
                        printfPQExpBuffer(q, "SELECT tableoid, oid, adnum, "
                                                          "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc "
@@ -8364,9 +8450,8 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
                                adnum = atoi(PQgetvalue(res, j, 2));
 
                                if (adnum <= 0 || adnum > ntups)
-                                       exit_horribly(NULL,
-                                                                 "invalid adnum value %d for table \"%s\"\n",
-                                                                 adnum, tbinfo->dobj.name);
+                                       fatal("invalid adnum value %d for table \"%s\"",
+                                                 adnum, tbinfo->dobj.name);
 
                                /*
                                 * dropped columns shouldn't have defaults, but just in case,
@@ -8430,10 +8515,9 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
                        ConstraintInfo *constrs;
                        int                     numConstrs;
 
-                       if (g_verbose)
-                               write_msg(NULL, "finding check constraints for table \"%s.%s\"\n",
-                                                 tbinfo->dobj.namespace->dobj.name,
-                                                 tbinfo->dobj.name);
+                       pg_log_info("finding check constraints for table \"%s.%s\"",
+                                               tbinfo->dobj.namespace->dobj.name,
+                                               tbinfo->dobj.name);
 
                        resetPQExpBuffer(q);
                        if (fout->remoteVersion >= 90200)
@@ -8480,11 +8564,11 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
                        numConstrs = PQntuples(res);
                        if (numConstrs != tbinfo->ncheck)
                        {
-                               write_msg(NULL, ngettext("expected %d check constraint on table \"%s\" but found %d\n",
-                                                                                "expected %d check constraints on table \"%s\" but found %d\n",
-                                                                                tbinfo->ncheck),
-                                                 tbinfo->ncheck, tbinfo->dobj.name, numConstrs);
-                               write_msg(NULL, "(The system catalogs might be corrupted.)\n");
+                               pg_log_error(ngettext("expected %d check constraint on table \"%s\" but found %d",
+                                                                         "expected %d check constraints on table \"%s\" but found %d",
+                                                                         tbinfo->ncheck),
+                                                        tbinfo->ncheck, tbinfo->dobj.name, numConstrs);
+                               pg_log_error("(The system catalogs might be corrupted.)");
                                exit_nicely(1);
                        }
 
@@ -8553,9 +8637,12 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
  * Normally this is always true, but it's false for dropped columns, as well
  * as those that were inherited without any local definition.  (If we print
  * such a column it will mistakenly get pg_attribute.attislocal set to true.)
- * However, in binary_upgrade mode, we must print all such columns anyway and
- * fix the attislocal/attisdropped state later, so as to keep control of the
- * physical column order.
+ * For partitions, it's always true, because we want the partitions to be
+ * created independently and ATTACH PARTITION used afterwards.
+ *
+ * In binary_upgrade mode, we must print all columns and fix the attislocal/
+ * attisdropped state later, so as to keep control of the physical column
+ * order.
  *
  * This function exists because there are scattered nonobvious places that
  * must be kept in sync with this decision.
@@ -8565,7 +8652,9 @@ shouldPrintColumn(DumpOptions *dopt, TableInfo *tbinfo, int colno)
 {
        if (dopt->binary_upgrade)
                return true;
-       return (tbinfo->attislocal[colno] && !tbinfo->attisdropped[colno]);
+       if (tbinfo->attisdropped[colno])
+               return false;
+       return (tbinfo->attislocal[colno] || tbinfo->ispartition);
 }
 
 
@@ -8608,9 +8697,6 @@ getTSParsers(Archive *fout, int *numTSParsers)
         * system-defined objects at dump-out time.
         */
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBufferStr(query, "SELECT tableoid, oid, prsname, prsnamespace, "
                                                 "prsstart::oid, prstoken::oid, "
                                                 "prsend::oid, prsheadline::oid, prslextype::oid "
@@ -8695,9 +8781,6 @@ getTSDictionaries(Archive *fout, int *numTSDicts)
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBuffer(query, "SELECT tableoid, oid, dictname, "
                                          "dictnamespace, (%s dictowner) AS rolname, "
                                          "dicttemplate, dictinitoption "
@@ -8781,9 +8864,6 @@ getTSTemplates(Archive *fout, int *numTSTemplates)
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBufferStr(query, "SELECT tableoid, oid, tmplname, "
                                                 "tmplnamespace, tmplinit::oid, tmpllexize::oid "
                                                 "FROM pg_ts_template");
@@ -8860,9 +8940,6 @@ getTSConfigurations(Archive *fout, int *numTSConfigs)
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBuffer(query, "SELECT tableoid, oid, cfgname, "
                                          "cfgnamespace, (%s cfgowner) AS rolname, cfgparser "
                                          "FROM pg_ts_config",
@@ -8946,9 +9023,6 @@ getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        if (fout->remoteVersion >= 90600)
        {
                PQExpBuffer acl_subquery = createPQExpBuffer();
@@ -9116,9 +9190,6 @@ getForeignServers(Archive *fout, int *numForeignServers)
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        if (fout->remoteVersion >= 90600)
        {
                PQExpBuffer acl_subquery = createPQExpBuffer();
@@ -9265,9 +9336,6 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
 
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        if (fout->remoteVersion >= 90600)
        {
                PQExpBuffer acl_subquery = createPQExpBuffer();
@@ -9368,13 +9436,18 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
  * dumpComment --
  *
  * This routine is used to dump any comments associated with the
- * object handed to this routine. The routine takes a constant character
- * string for the target part of the comment-creation command, plus
+ * object handed to this routine. The routine takes the object type
+ * and object name (ready to print, except for schema decoration), plus
  * the namespace and owner of the object (for labeling the ArchiveEntry),
  * plus catalog ID and subid which are the lookup key for pg_description,
  * plus the dump ID for the object (for setting a dependency).
  * If a matching pg_description entry is found, it is dumped.
  *
+ * Note: in some cases, such as comments for triggers and rules, the "type"
+ * string really looks like, e.g., "TRIGGER name ON".  This is a bit of a hack
+ * but it doesn't seem worth complicating the API for all callers to make
+ * it cleaner.
+ *
  * Note: although this routine takes a dumpId for dependency purposes,
  * that purpose is just to mark the dependency in the emitted dump file
  * for possible future use by pg_restore.  We do NOT use it for determining
@@ -9383,7 +9456,7 @@ getDefaultACLs(Archive *fout, int *numDefaultACLs)
  * calling ArchiveEntry() for the specified object.
  */
 static void
-dumpComment(Archive *fout, const char *target,
+dumpComment(Archive *fout, const char *type, const char *name,
                        const char *namespace, const char *owner,
                        CatalogId catalogId, int subid, DumpId dumpId)
 {
@@ -9396,7 +9469,7 @@ dumpComment(Archive *fout, const char *target,
                return;
 
        /* Comments are schema not data ... except blob comments are data */
-       if (strncmp(target, "LARGE OBJECT ", 13) != 0)
+       if (strcmp(type, "LARGE OBJECT") != 0)
        {
                if (dopt->dataOnly)
                        return;
@@ -9425,24 +9498,34 @@ dumpComment(Archive *fout, const char *target,
        if (ncomments > 0)
        {
                PQExpBuffer query = createPQExpBuffer();
+               PQExpBuffer tag = createPQExpBuffer();
 
-               appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
+               appendPQExpBuffer(query, "COMMENT ON %s ", type);
+               if (namespace && *namespace)
+                       appendPQExpBuffer(query, "%s.", fmtId(namespace));
+               appendPQExpBuffer(query, "%s IS ", name);
                appendStringLiteralAH(query, comments->descr, fout);
                appendPQExpBufferStr(query, ";\n");
 
+               appendPQExpBuffer(tag, "%s %s", type, name);
+
                /*
                 * We mark comments as SECTION_NONE because they really belong in the
                 * same section as their parent, whether that is pre-data or
                 * post-data.
                 */
                ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                        target, namespace, NULL, owner,
-                                        false, "COMMENT", SECTION_NONE,
-                                        query->data, "", NULL,
-                                        &(dumpId), 1,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tag->data,
+                                                                 .namespace = namespace,
+                                                                 .owner = owner,
+                                                                 .description = "COMMENT",
+                                                                 .section = SECTION_NONE,
+                                                                 .createStmt = query->data,
+                                                                 .deps = &dumpId,
+                                                                 .nDeps = 1));
 
                destroyPQExpBuffer(query);
+               destroyPQExpBuffer(tag);
        }
 }
 
@@ -9460,7 +9543,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
        CommentItem *comments;
        int                     ncomments;
        PQExpBuffer query;
-       PQExpBuffer target;
+       PQExpBuffer tag;
 
        /* do nothing, if --no-comments is supplied */
        if (dopt->no_comments)
@@ -9481,7 +9564,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
                return;
 
        query = createPQExpBuffer();
-       target = createPQExpBuffer();
+       tag = createPQExpBuffer();
 
        while (ncomments > 0)
        {
@@ -9490,44 +9573,50 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
 
                if (objsubid == 0)
                {
-                       resetPQExpBuffer(target);
-                       appendPQExpBuffer(target, "%s %s", reltypename,
+                       resetPQExpBuffer(tag);
+                       appendPQExpBuffer(tag, "%s %s", reltypename,
                                                          fmtId(tbinfo->dobj.name));
 
                        resetPQExpBuffer(query);
-                       appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
+                       appendPQExpBuffer(query, "COMMENT ON %s %s IS ", reltypename,
+                                                         fmtQualifiedDumpable(tbinfo));
                        appendStringLiteralAH(query, descr, fout);
                        appendPQExpBufferStr(query, ";\n");
 
                        ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                                target->data,
-                                                tbinfo->dobj.namespace->dobj.name,
-                                                NULL, tbinfo->rolname,
-                                                false, "COMMENT", SECTION_NONE,
-                                                query->data, "", NULL,
-                                                &(tbinfo->dobj.dumpId), 1,
-                                                NULL, NULL);
+                                                ARCHIVE_OPTS(.tag = tag->data,
+                                                                         .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                         .owner = tbinfo->rolname,
+                                                                         .description = "COMMENT",
+                                                                         .section = SECTION_NONE,
+                                                                         .createStmt = query->data,
+                                                                         .deps = &(tbinfo->dobj.dumpId),
+                                                                         .nDeps = 1));
                }
                else if (objsubid > 0 && objsubid <= tbinfo->numatts)
                {
-                       resetPQExpBuffer(target);
-                       appendPQExpBuffer(target, "COLUMN %s.",
+                       resetPQExpBuffer(tag);
+                       appendPQExpBuffer(tag, "COLUMN %s.",
                                                          fmtId(tbinfo->dobj.name));
-                       appendPQExpBufferStr(target, fmtId(tbinfo->attnames[objsubid - 1]));
+                       appendPQExpBufferStr(tag, fmtId(tbinfo->attnames[objsubid - 1]));
 
                        resetPQExpBuffer(query);
-                       appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
+                       appendPQExpBuffer(query, "COMMENT ON COLUMN %s.",
+                                                         fmtQualifiedDumpable(tbinfo));
+                       appendPQExpBuffer(query, "%s IS ",
+                                                         fmtId(tbinfo->attnames[objsubid - 1]));
                        appendStringLiteralAH(query, descr, fout);
                        appendPQExpBufferStr(query, ";\n");
 
                        ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                                target->data,
-                                                tbinfo->dobj.namespace->dobj.name,
-                                                NULL, tbinfo->rolname,
-                                                false, "COMMENT", SECTION_NONE,
-                                                query->data, "", NULL,
-                                                &(tbinfo->dobj.dumpId), 1,
-                                                NULL, NULL);
+                                                ARCHIVE_OPTS(.tag = tag->data,
+                                                                         .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                         .owner = tbinfo->rolname,
+                                                                         .description = "COMMENT",
+                                                                         .section = SECTION_NONE,
+                                                                         .createStmt = query->data,
+                                                                         .deps = &(tbinfo->dobj.dumpId),
+                                                                         .nDeps = 1));
                }
 
                comments++;
@@ -9535,7 +9624,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
        }
 
        destroyPQExpBuffer(query);
-       destroyPQExpBuffer(target);
+       destroyPQExpBuffer(tag);
 }
 
 /*
@@ -9642,11 +9731,6 @@ collectComments(Archive *fout, CommentItem **items)
        int                     i;
        CommentItem *comments;
 
-       /*
-        * Note we do NOT change source schema here; preserve the caller's
-        * setting, instead.
-        */
-
        query = createPQExpBuffer();
 
        appendPQExpBufferStr(query, "SELECT description, classoid, objoid, objsubid "
@@ -9805,12 +9889,30 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
                        break;
                case DO_BLOB_DATA:
                        if (dobj->dump & DUMP_COMPONENT_DATA)
-                               ArchiveEntry(fout, dobj->catId, dobj->dumpId,
-                                                        dobj->name, NULL, NULL, "",
-                                                        false, "BLOBS", SECTION_DATA,
-                                                        "", "", NULL,
-                                                        NULL, 0,
-                                                        dumpBlobs, NULL);
+                       {
+                               TocEntry   *te;
+
+                               te = ArchiveEntry(fout, dobj->catId, dobj->dumpId,
+                                                                 ARCHIVE_OPTS(.tag = dobj->name,
+                                                                                          .description = "BLOBS",
+                                                                                          .section = SECTION_DATA,
+                                                                                          .dumpFn = dumpBlobs));
+
+                               /*
+                                * Set the TocEntry's dataLength in case we are doing a
+                                * parallel dump and want to order dump jobs by table size.
+                                * (We need some size estimate for every TocEntry with a
+                                * DataDumper function.)  We don't currently have any cheap
+                                * way to estimate the size of blobs, but it doesn't matter;
+                                * let's just set the size to a large value so parallel dumps
+                                * will launch this job first.  If there's lots of blobs, we
+                                * win, and if there aren't, we don't lose much.  (If you want
+                                * to improve on this, really what you should be thinking
+                                * about is allowing blob dumping to be parallelized, not just
+                                * getting a smarter estimate for the single TOC entry.)
+                                */
+                               te->dataLength = MaxBlockNumber;
+                       }
                        break;
                case DO_POLICY:
                        dumpPolicy(fout, (PolicyInfo *) dobj);
@@ -9841,7 +9943,6 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
        char       *qnspname;
 
        /* Skip if not to be dumped */
@@ -9850,7 +9951,6 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
 
        qnspname = pg_strdup(fmtId(nspinfo->dobj.name));
 
@@ -9858,35 +9958,33 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 
        appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
 
-       appendPQExpBuffer(labelq, "SCHEMA %s", qnspname);
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &nspinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &nspinfo->dobj,
+                                                                               "SCHEMA", qnspname, NULL);
 
        if (nspinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
-                                        nspinfo->dobj.name,
-                                        NULL, NULL,
-                                        nspinfo->rolname,
-                                        false, "SCHEMA", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = nspinfo->dobj.name,
+                                                                 .owner = nspinfo->rolname,
+                                                                 .description = "SCHEMA",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Schema Comments and Security Labels */
        if (nspinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "SCHEMA", qnspname,
                                        NULL, nspinfo->rolname,
                                        nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
 
        if (nspinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, "SCHEMA", qnspname,
                                         NULL, nspinfo->rolname,
                                         nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
 
        if (nspinfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, "SCHEMA",
-                               qnspname, NULL, labelq->data, NULL,
+                               qnspname, NULL, NULL,
                                nspinfo->rolname, nspinfo->nspacl, nspinfo->rnspacl,
                                nspinfo->initnspacl, nspinfo->initrnspacl);
 
@@ -9894,7 +9992,6 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -9907,7 +10004,6 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
        char       *qextname;
 
        /* Skip if not to be dumped */
@@ -9916,7 +10012,6 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
 
        qextname = pg_strdup(fmtId(extinfo->dobj.name));
 
@@ -10002,26 +10097,22 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo)
                appendPQExpBufferStr(q, ");\n");
        }
 
-       appendPQExpBuffer(labelq, "EXTENSION %s", qextname);
-
        if (extinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, extinfo->dobj.catId, extinfo->dobj.dumpId,
-                                        extinfo->dobj.name,
-                                        NULL, NULL,
-                                        "",
-                                        false, "EXTENSION", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = extinfo->dobj.name,
+                                                                 .description = "EXTENSION",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Extension Comments and Security Labels */
        if (extinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "EXTENSION", qextname,
                                        NULL, "",
                                        extinfo->dobj.catId, 0, extinfo->dobj.dumpId);
 
        if (extinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, "EXTENSION", qextname,
                                         NULL, "",
                                         extinfo->dobj.catId, 0, extinfo->dobj.dumpId);
 
@@ -10029,7 +10120,6 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo)
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -10059,8 +10149,8 @@ dumpType(Archive *fout, TypeInfo *tyinfo)
        else if (tyinfo->typtype == TYPTYPE_PSEUDO && !tyinfo->isDefined)
                dumpUndefinedType(fout, tyinfo);
        else
-               write_msg(NULL, "WARNING: typtype of data type \"%s\" appears to be invalid\n",
-                                 tyinfo->dobj.name);
+               pg_log_warning("typtype of data type \"%s\" appears to be invalid",
+                                          tyinfo->dobj.name);
 }
 
 /*
@@ -10073,18 +10163,15 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
-       PQExpBuffer labelq = createPQExpBuffer();
        PQExpBuffer query = createPQExpBuffer();
        PGresult   *res;
        int                     num,
                                i;
        Oid                     enum_oid;
        char       *qtypname;
+       char       *qualtypname;
        char       *label;
 
-       /* Set proper schema search path */
-       selectSourceSchema(fout, "pg_catalog");
-
        if (fout->remoteVersion >= 90100)
                appendPQExpBuffer(query, "SELECT oid, enumlabel "
                                                  "FROM pg_catalog.pg_enum "
@@ -10103,16 +10190,13 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
        num = PQntuples(res);
 
        qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+       qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
 
        /*
-        * 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(tyinfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delq, "%s;\n",
-                                         qtypname);
+       appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname);
 
        if (dopt->binary_upgrade)
                binary_upgrade_set_type_oids_by_type_oid(fout, q,
@@ -10120,7 +10204,7 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
                                                                                                 false);
 
        appendPQExpBuffer(q, "CREATE TYPE %s AS ENUM (",
-                                         qtypname);
+                                         qualtypname);
 
        if (!dopt->binary_upgrade)
        {
@@ -10150,45 +10234,41 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
                        appendPQExpBuffer(q,
                                                          "SELECT pg_catalog.binary_upgrade_set_next_pg_enum_oid('%u'::pg_catalog.oid);\n",
                                                          enum_oid);
-                       appendPQExpBuffer(q, "ALTER TYPE %s.",
-                                                         fmtId(tyinfo->dobj.namespace->dobj.name));
-                       appendPQExpBuffer(q, "%s ADD VALUE ",
-                                                         qtypname);
+                       appendPQExpBuffer(q, "ALTER TYPE %s ADD VALUE ", qualtypname);
                        appendStringLiteralAH(q, label, fout);
                        appendPQExpBufferStr(q, ";\n\n");
                }
        }
 
-       appendPQExpBuffer(labelq, "TYPE %s", qtypname);
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &tyinfo->dobj,
+                                                                               "TYPE", qtypname,
+                                                                               tyinfo->dobj.namespace->dobj.name);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-                                        tyinfo->dobj.name,
-                                        tyinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        tyinfo->rolname, false,
-                                        "TYPE", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+                                                                 .namespace = tyinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tyinfo->rolname,
+                                                                 .description = "TYPE",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Type Comments and Security Labels */
        if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "TYPE", qtypname,
                                        tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                        tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, "TYPE", qtypname,
                                         tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                         tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
-                               qtypname, NULL, labelq->data,
+                               qtypname, NULL,
                                tyinfo->dobj.namespace->dobj.name,
                                tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
                                tyinfo->inittypacl, tyinfo->initrtypacl);
@@ -10196,8 +10276,9 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
        PQclear(res);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
+       free(qtypname);
+       free(qualtypname);
 }
 
 /*
@@ -10210,19 +10291,13 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
-       PQExpBuffer labelq = createPQExpBuffer();
        PQExpBuffer query = createPQExpBuffer();
        PGresult   *res;
        Oid                     collationOid;
        char       *qtypname;
+       char       *qualtypname;
        char       *procname;
 
-       /*
-        * select appropriate schema to ensure names in CREATE are properly
-        * qualified
-        */
-       selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
-
        appendPQExpBuffer(query,
                                          "SELECT pg_catalog.format_type(rngsubtype, NULL) AS rngsubtype, "
                                          "opc.opcname AS opcname, "
@@ -10241,16 +10316,13 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
        res = ExecuteSqlQueryForSingleRow(fout, query->data);
 
        qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+       qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
 
        /*
-        * 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(tyinfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delq, "%s;\n",
-                                         qtypname);
+       appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname);
 
        if (dopt->binary_upgrade)
                binary_upgrade_set_type_oids_by_type_oid(fout, q,
@@ -10258,7 +10330,7 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
                                                                                                 false);
 
        appendPQExpBuffer(q, "CREATE TYPE %s AS RANGE (",
-                                         qtypname);
+                                         qualtypname);
 
        appendPQExpBuffer(q, "\n    subtype = %s",
                                          PQgetvalue(res, 0, PQfnumber(res, "rngsubtype")));
@@ -10269,7 +10341,6 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
                char       *opcname = PQgetvalue(res, 0, PQfnumber(res, "opcname"));
                char       *nspname = PQgetvalue(res, 0, PQfnumber(res, "opcnsp"));
 
-               /* always schema-qualify, don't try to be smart */
                appendPQExpBuffer(q, ",\n    subtype_opclass = %s.",
                                                  fmtId(nspname));
                appendPQExpBufferStr(q, fmtId(opcname));
@@ -10281,12 +10352,8 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
                CollInfo   *coll = findCollationByOid(collationOid);
 
                if (coll)
-               {
-                       /* always schema-qualify, don't try to be smart */
-                       appendPQExpBuffer(q, ",\n    collation = %s.",
-                                                         fmtId(coll->dobj.namespace->dobj.name));
-                       appendPQExpBufferStr(q, fmtId(coll->dobj.name));
-               }
+                       appendPQExpBuffer(q, ",\n    collation = %s",
+                                                         fmtQualifiedDumpable(coll));
        }
 
        procname = PQgetvalue(res, 0, PQfnumber(res, "rngcanonical"));
@@ -10299,36 +10366,35 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
 
        appendPQExpBufferStr(q, "\n);\n");
 
-       appendPQExpBuffer(labelq, "TYPE %s", qtypname);
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &tyinfo->dobj,
+                                                                               "TYPE", qtypname,
+                                                                               tyinfo->dobj.namespace->dobj.name);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-                                        tyinfo->dobj.name,
-                                        tyinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        tyinfo->rolname, false,
-                                        "TYPE", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+                                                                 .namespace = tyinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tyinfo->rolname,
+                                                                 .description = "TYPE",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Type Comments and Security Labels */
        if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "TYPE", qtypname,
                                        tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                        tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, "TYPE", qtypname,
                                         tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                         tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
-                               qtypname, NULL, labelq->data,
+                               qtypname, NULL,
                                tyinfo->dobj.namespace->dobj.name,
                                tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
                                tyinfo->inittypacl, tyinfo->initrtypacl);
@@ -10336,8 +10402,9 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
        PQclear(res);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
+       free(qtypname);
+       free(qualtypname);
 }
 
 /*
@@ -10355,18 +10422,13 @@ dumpUndefinedType(Archive *fout, TypeInfo *tyinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
-       PQExpBuffer labelq = createPQExpBuffer();
        char       *qtypname;
+       char       *qualtypname;
 
        qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+       qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
 
-       /*
-        * DROP must be fully qualified in case same name appears in pg_catalog.
-        */
-       appendPQExpBuffer(delq, "DROP TYPE %s.",
-                                         fmtId(tyinfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delq, "%s;\n",
-                                         qtypname);
+       appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname);
 
        if (dopt->binary_upgrade)
                binary_upgrade_set_type_oids_by_type_oid(fout, q,
@@ -10374,45 +10436,45 @@ dumpUndefinedType(Archive *fout, TypeInfo *tyinfo)
                                                                                                 false);
 
        appendPQExpBuffer(q, "CREATE TYPE %s;\n",
-                                         qtypname);
-
-       appendPQExpBuffer(labelq, "TYPE %s", qtypname);
+                                         qualtypname);
 
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &tyinfo->dobj,
+                                                                               "TYPE", qtypname,
+                                                                               tyinfo->dobj.namespace->dobj.name);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-                                        tyinfo->dobj.name,
-                                        tyinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        tyinfo->rolname, false,
-                                        "TYPE", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+                                                                 .namespace = tyinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tyinfo->rolname,
+                                                                 .description = "TYPE",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Type Comments and Security Labels */
        if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "TYPE", qtypname,
                                        tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                        tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, "TYPE", qtypname,
                                         tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                         tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
-                               qtypname, NULL, labelq->data,
+                               qtypname, NULL,
                                tyinfo->dobj.namespace->dobj.name,
                                tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
                                tyinfo->inittypacl, tyinfo->initrtypacl);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
+       free(qtypname);
+       free(qualtypname);
 }
 
 /*
@@ -10425,10 +10487,10 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
-       PQExpBuffer labelq = createPQExpBuffer();
        PQExpBuffer query = createPQExpBuffer();
        PGresult   *res;
        char       *qtypname;
+       char       *qualtypname;
        char       *typlen;
        char       *typinput;
        char       *typoutput;
@@ -10452,9 +10514,6 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
        char       *typdefault;
        bool            typdefault_is_literal = false;
 
-       /* Set proper schema search path so regproc references list correctly */
-       selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
-
        /* Fetch type-specific details */
        if (fout->remoteVersion >= 90100)
        {
@@ -10563,17 +10622,14 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
                typdefault = NULL;
 
        qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+       qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
 
        /*
-        * 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(tyinfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delq, "%s CASCADE;\n",
-                                         qtypname);
+       appendPQExpBuffer(delq, "DROP TYPE %s CASCADE;\n", qualtypname);
 
        /*
         * We might already have a shell type, but setting pg_type_oid is
@@ -10587,7 +10643,7 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
        appendPQExpBuffer(q,
                                          "CREATE TYPE %s (\n"
                                          "    INTERNALLENGTH = %s",
-                                         qtypname,
+                                         qualtypname,
                                          (strcmp(typlen, "-1") == 0) ? "variable" : typlen);
 
        /* regproc result is sufficiently quoted already */
@@ -10620,8 +10676,6 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
        {
                char       *elemType;
 
-               /* reselect schema in case changed by function dump */
-               selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
                elemType = getFormattedTypeName(fout, tyinfo->typelem, zeroAsOpaque);
                appendPQExpBuffer(q, ",\n    ELEMENT = %s", elemType);
                free(elemType);
@@ -10665,36 +10719,35 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
 
        appendPQExpBufferStr(q, "\n);\n");
 
-       appendPQExpBuffer(labelq, "TYPE %s", qtypname);
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &tyinfo->dobj,
+                                                                               "TYPE", qtypname,
+                                                                               tyinfo->dobj.namespace->dobj.name);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-                                        tyinfo->dobj.name,
-                                        tyinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        tyinfo->rolname, false,
-                                        "TYPE", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+                                                                 .namespace = tyinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tyinfo->rolname,
+                                                                 .description = "TYPE",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Type Comments and Security Labels */
        if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "TYPE", qtypname,
                                        tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                        tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, "TYPE", qtypname,
                                         tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                         tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
-                               qtypname, NULL, labelq->data,
+                               qtypname, NULL,
                                tyinfo->dobj.namespace->dobj.name,
                                tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
                                tyinfo->inittypacl, tyinfo->initrtypacl);
@@ -10702,8 +10755,9 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
        PQclear(res);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
+       free(qtypname);
+       free(qualtypname);
 }
 
 /*
@@ -10716,20 +10770,17 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
-       PQExpBuffer labelq = createPQExpBuffer();
        PQExpBuffer query = createPQExpBuffer();
        PGresult   *res;
        int                     i;
        char       *qtypname;
+       char       *qualtypname;
        char       *typnotnull;
        char       *typdefn;
        char       *typdefault;
        Oid                     typcollation;
        bool            typdefault_is_literal = false;
 
-       /* Set proper schema search path so type references list correctly */
-       selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
-
        /* Fetch domain specific details */
        if (fout->remoteVersion >= 90100)
        {
@@ -10777,10 +10828,11 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
                                                                                                 true); /* force array type */
 
        qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+       qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
 
        appendPQExpBuffer(q,
                                          "CREATE DOMAIN %s AS %s",
-                                         qtypname,
+                                         qualtypname,
                                          typdefn);
 
        /* Print collation only if different from base type's collation */
@@ -10790,12 +10842,7 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
 
                coll = findCollationByOid(typcollation);
                if (coll)
-               {
-                       /* always schema-qualify, don't try to be smart */
-                       appendPQExpBuffer(q, " COLLATE %s.",
-                                                         fmtId(coll->dobj.namespace->dobj.name));
-                       appendPQExpBufferStr(q, fmtId(coll->dobj.name));
-               }
+                       appendPQExpBuffer(q, " COLLATE %s", fmtQualifiedDumpable(coll));
        }
 
        if (typnotnull[0] == 't')
@@ -10826,44 +10873,37 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
 
        appendPQExpBufferStr(q, ";\n");
 
-       /*
-        * DROP must be fully qualified in case same name appears in pg_catalog
-        */
-       appendPQExpBuffer(delq, "DROP DOMAIN %s.",
-                                         fmtId(tyinfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delq, "%s;\n",
-                                         qtypname);
-
-       appendPQExpBuffer(labelq, "DOMAIN %s", qtypname);
+       appendPQExpBuffer(delq, "DROP DOMAIN %s;\n", qualtypname);
 
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &tyinfo->dobj,
+                                                                               "DOMAIN", qtypname,
+                                                                               tyinfo->dobj.namespace->dobj.name);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-                                        tyinfo->dobj.name,
-                                        tyinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        tyinfo->rolname, false,
-                                        "DOMAIN", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+                                                                 .namespace = tyinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tyinfo->rolname,
+                                                                 .description = "DOMAIN",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Domain Comments and Security Labels */
        if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "DOMAIN", qtypname,
                                        tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                        tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, "DOMAIN", qtypname,
                                         tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                         tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
-                               qtypname, NULL, labelq->data,
+                               qtypname, NULL,
                                tyinfo->dobj.namespace->dobj.name,
                                tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
                                tyinfo->inittypacl, tyinfo->initrtypacl);
@@ -10872,26 +10912,25 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
        for (i = 0; i < tyinfo->nDomChecks; i++)
        {
                ConstraintInfo *domcheck = &(tyinfo->domChecks[i]);
-               PQExpBuffer labelq = createPQExpBuffer();
+               PQExpBuffer conprefix = createPQExpBuffer();
 
-               appendPQExpBuffer(labelq, "CONSTRAINT %s ",
+               appendPQExpBuffer(conprefix, "CONSTRAINT %s ON DOMAIN",
                                                  fmtId(domcheck->dobj.name));
-               appendPQExpBuffer(labelq, "ON DOMAIN %s",
-                                                 qtypname);
 
                if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-                       dumpComment(fout, labelq->data,
+                       dumpComment(fout, conprefix->data, qtypname,
                                                tyinfo->dobj.namespace->dobj.name,
                                                tyinfo->rolname,
                                                domcheck->dobj.catId, 0, tyinfo->dobj.dumpId);
 
-               destroyPQExpBuffer(labelq);
+               destroyPQExpBuffer(conprefix);
        }
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
+       free(qtypname);
+       free(qualtypname);
 }
 
 /*
@@ -10906,10 +10945,10 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer dropped = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
-       PQExpBuffer labelq = createPQExpBuffer();
        PQExpBuffer query = createPQExpBuffer();
        PGresult   *res;
        char       *qtypname;
+       char       *qualtypname;
        int                     ntups;
        int                     i_attname;
        int                     i_atttypdefn;
@@ -10920,9 +10959,6 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
        int                     i;
        int                     actual_atts;
 
-       /* Set proper schema search path so type references list correctly */
-       selectSourceSchema(fout, tyinfo->dobj.namespace->dobj.name);
-
        /* Fetch type specific details */
        if (fout->remoteVersion >= 90100)
        {
@@ -10982,9 +11018,10 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
        }
 
        qtypname = pg_strdup(fmtId(tyinfo->dobj.name));
+       qualtypname = pg_strdup(fmtQualifiedDumpable(tyinfo));
 
        appendPQExpBuffer(q, "CREATE TYPE %s AS (",
-                                         qtypname);
+                                         qualtypname);
 
        actual_atts = 0;
        for (i = 0; i < ntups; i++)
@@ -11022,12 +11059,8 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
 
                                coll = findCollationByOid(attcollation);
                                if (coll)
-                               {
-                                       /* always schema-qualify, don't try to be smart */
-                                       appendPQExpBuffer(q, " COLLATE %s.",
-                                                                         fmtId(coll->dobj.namespace->dobj.name));
-                                       appendPQExpBufferStr(q, fmtId(coll->dobj.name));
-                               }
+                                       appendPQExpBuffer(q, " COLLATE %s",
+                                                                         fmtQualifiedDumpable(coll));
                        }
                }
                else
@@ -11049,11 +11082,11 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
                                                          "WHERE attname = ", attlen, attalign);
                        appendStringLiteralAH(dropped, attname, fout);
                        appendPQExpBufferStr(dropped, "\n  AND attrelid = ");
-                       appendStringLiteralAH(dropped, qtypname, fout);
+                       appendStringLiteralAH(dropped, qualtypname, fout);
                        appendPQExpBufferStr(dropped, "::pg_catalog.regclass;\n");
 
                        appendPQExpBuffer(dropped, "ALTER TYPE %s ",
-                                                         qtypname);
+                                                         qualtypname);
                        appendPQExpBuffer(dropped, "DROP ATTRIBUTE %s;\n",
                                                          fmtId(attname));
                }
@@ -11061,45 +11094,38 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
        appendPQExpBufferStr(q, "\n);\n");
        appendPQExpBufferStr(q, dropped->data);
 
-       /*
-        * DROP must be fully qualified in case same name appears in pg_catalog
-        */
-       appendPQExpBuffer(delq, "DROP TYPE %s.",
-                                         fmtId(tyinfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delq, "%s;\n",
-                                         qtypname);
-
-       appendPQExpBuffer(labelq, "TYPE %s", qtypname);
+       appendPQExpBuffer(delq, "DROP TYPE %s;\n", qualtypname);
 
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &tyinfo->dobj,
+                                                                               "TYPE", qtypname,
+                                                                               tyinfo->dobj.namespace->dobj.name);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-                                        tyinfo->dobj.name,
-                                        tyinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        tyinfo->rolname, false,
-                                        "TYPE", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+                                                                 .namespace = tyinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tyinfo->rolname,
+                                                                 .description = "TYPE",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
 
        /* Dump Type Comments and Security Labels */
        if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "TYPE", qtypname,
                                        tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                        tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, "TYPE", qtypname,
                                         tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                         tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
-                               qtypname, NULL, labelq->data,
+                               qtypname, NULL,
                                tyinfo->dobj.namespace->dobj.name,
                                tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
                                tyinfo->inittypacl, tyinfo->initrtypacl);
@@ -11108,8 +11134,9 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(dropped);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
+       free(qtypname);
+       free(qualtypname);
 
        /* Dump any per-column comments */
        if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -11204,18 +11231,21 @@ dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo)
                        appendPQExpBufferStr(target, fmtId(attname));
 
                        resetPQExpBuffer(query);
-                       appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
+                       appendPQExpBuffer(query, "COMMENT ON COLUMN %s.",
+                                                         fmtQualifiedDumpable(tyinfo));
+                       appendPQExpBuffer(query, "%s IS ", fmtId(attname));
                        appendStringLiteralAH(query, descr, fout);
                        appendPQExpBufferStr(query, ";\n");
 
                        ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                                target->data,
-                                                tyinfo->dobj.namespace->dobj.name,
-                                                NULL, tyinfo->rolname,
-                                                false, "COMMENT", SECTION_NONE,
-                                                query->data, "", NULL,
-                                                &(tyinfo->dobj.dumpId), 1,
-                                                NULL, NULL);
+                                                ARCHIVE_OPTS(.tag = target->data,
+                                                                         .namespace = tyinfo->dobj.namespace->dobj.name,
+                                                                         .owner = tyinfo->rolname,
+                                                                         .description = "COMMENT",
+                                                                         .section = SECTION_NONE,
+                                                                         .createStmt = query->data,
+                                                                         .deps = &(tyinfo->dobj.dumpId),
+                                                                         .nDeps = 1));
                }
 
                comments++;
@@ -11260,18 +11290,16 @@ dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
                                                                                                 false);
 
        appendPQExpBuffer(q, "CREATE TYPE %s;\n",
-                                         fmtId(stinfo->dobj.name));
+                                         fmtQualifiedDumpable(stinfo));
 
        if (stinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId,
-                                        stinfo->dobj.name,
-                                        stinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        stinfo->baseType->rolname, false,
-                                        "SHELL TYPE", SECTION_PRE_DATA,
-                                        q->data, "", NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = stinfo->dobj.name,
+                                                                 .namespace = stinfo->dobj.namespace->dobj.name,
+                                                                 .owner = stinfo->baseType->rolname,
+                                                                 .description = "SHELL TYPE",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data));
 
        destroyPQExpBuffer(q);
 }
@@ -11287,10 +11315,8 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer defqry;
        PQExpBuffer delqry;
-       PQExpBuffer labelq;
        bool            useParams;
        char       *qlanname;
-       char       *lanschema;
        FuncInfo   *funcInfo;
        FuncInfo   *inlineInfo = NULL;
        FuncInfo   *validatorInfo = NULL;
@@ -11336,20 +11362,9 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 
        defqry = createPQExpBuffer();
        delqry = createPQExpBuffer();
-       labelq = createPQExpBuffer();
 
        qlanname = pg_strdup(fmtId(plang->dobj.name));
 
-       /*
-        * If dumping a HANDLER clause, treat the language as being in the handler
-        * function's schema; this avoids cluttering the HANDLER clause. Otherwise
-        * it doesn't really have a schema.
-        */
-       if (useParams)
-               lanschema = funcInfo->dobj.namespace->dobj.name;
-       else
-               lanschema = NULL;
-
        appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n",
                                          qlanname);
 
@@ -11359,25 +11374,13 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
                                                  plang->lanpltrusted ? "TRUSTED " : "",
                                                  qlanname);
                appendPQExpBuffer(defqry, " HANDLER %s",
-                                                 fmtId(funcInfo->dobj.name));
+                                                 fmtQualifiedDumpable(funcInfo));
                if (OidIsValid(plang->laninline))
-               {
-                       appendPQExpBufferStr(defqry, " INLINE ");
-                       /* Cope with possibility that inline is in different schema */
-                       if (inlineInfo->dobj.namespace != funcInfo->dobj.namespace)
-                               appendPQExpBuffer(defqry, "%s.",
-                                                                 fmtId(inlineInfo->dobj.namespace->dobj.name));
-                       appendPQExpBufferStr(defqry, fmtId(inlineInfo->dobj.name));
-               }
+                       appendPQExpBuffer(defqry, " INLINE %s",
+                                                         fmtQualifiedDumpable(inlineInfo));
                if (OidIsValid(plang->lanvalidator))
-               {
-                       appendPQExpBufferStr(defqry, " VALIDATOR ");
-                       /* Cope with possibility that validator is in different schema */
-                       if (validatorInfo->dobj.namespace != funcInfo->dobj.namespace)
-                               appendPQExpBuffer(defqry, "%s.",
-                                                                 fmtId(validatorInfo->dobj.namespace->dobj.name));
-                       appendPQExpBufferStr(defqry, fmtId(validatorInfo->dobj.name));
-               }
+                       appendPQExpBuffer(defqry, " VALIDATOR %s",
+                                                         fmtQualifiedDumpable(validatorInfo));
        }
        else
        {
@@ -11395,35 +11398,34 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
        }
        appendPQExpBufferStr(defqry, ";\n");
 
-       appendPQExpBuffer(labelq, "LANGUAGE %s", qlanname);
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(defqry, &plang->dobj, labelq->data);
+               binary_upgrade_extension_member(defqry, &plang->dobj,
+                                                                               "LANGUAGE", qlanname, NULL);
 
        if (plang->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
-                                        plang->dobj.name,
-                                        lanschema, NULL, plang->lanowner,
-                                        false, "PROCEDURAL LANGUAGE", SECTION_PRE_DATA,
-                                        defqry->data, delqry->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = plang->dobj.name,
+                                                                 .owner = plang->lanowner,
+                                                                 .description = "PROCEDURAL LANGUAGE",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = defqry->data,
+                                                                 .dropStmt = delqry->data,
+                                                                 ));
 
        /* Dump Proc Lang Comments and Security Labels */
        if (plang->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
-                                       lanschema, plang->lanowner,
+               dumpComment(fout, "LANGUAGE", qlanname,
+                                       NULL, plang->lanowner,
                                        plang->dobj.catId, 0, plang->dobj.dumpId);
 
        if (plang->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
-                                        lanschema, plang->lanowner,
+               dumpSecLabel(fout, "LANGUAGE", qlanname,
+                                        NULL, plang->lanowner,
                                         plang->dobj.catId, 0, plang->dobj.dumpId);
 
        if (plang->lanpltrusted && plang->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
-                               qlanname, NULL, labelq->data,
-                               lanschema,
+                               qlanname, NULL, NULL,
                                plang->lanowner, plang->lanacl, plang->rlanacl,
                                plang->initlanacl, plang->initrlanacl);
 
@@ -11431,7 +11433,6 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 
        destroyPQExpBuffer(defqry);
        destroyPQExpBuffer(delqry);
-       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -11502,7 +11503,7 @@ format_function_arguments_old(Archive *fout,
                                        argmode = "INOUT ";
                                        break;
                                default:
-                                       write_msg(NULL, "WARNING: bogus value in proargmodes array\n");
+                                       pg_log_warning("bogus value in proargmodes array");
                                        argmode = "";
                                        break;
                        }
@@ -11575,7 +11576,6 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delqry;
-       PQExpBuffer labelq;
        PQExpBuffer asPart;
        PGresult   *res;
        char       *funcsig;            /* identity signature */
@@ -11587,12 +11587,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        char       *funcargs;
        char       *funciargs;
        char       *funcresult;
-       bool            is_procedure;
        char       *proallargtypes;
        char       *proargmodes;
        char       *proargnames;
        char       *protrftypes;
-       char       *proiswindow;
+       char       *prokind;
        char       *provolatile;
        char       *proisstrict;
        char       *prosecdef;
@@ -11600,6 +11599,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        char       *proconfig;
        char       *procost;
        char       *prorows;
+       char       *prosupport;
        char       *proparallel;
        char       *lanname;
        char       *rettypename;
@@ -11619,14 +11619,48 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        query = createPQExpBuffer();
        q = createPQExpBuffer();
        delqry = createPQExpBuffer();
-       labelq = createPQExpBuffer();
        asPart = createPQExpBuffer();
 
-       /* Set proper schema search path so type references list correctly */
-       selectSourceSchema(fout, finfo->dobj.namespace->dobj.name);
-
        /* Fetch function-specific details */
-       if (fout->remoteVersion >= 90600)
+       if (fout->remoteVersion >= 120000)
+       {
+               /*
+                * prosupport was added in 12
+                */
+               appendPQExpBuffer(query,
+                                                 "SELECT proretset, prosrc, probin, "
+                                                 "pg_catalog.pg_get_function_arguments(oid) AS funcargs, "
+                                                 "pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
+                                                 "pg_catalog.pg_get_function_result(oid) AS funcresult, "
+                                                 "array_to_string(protrftypes, ' ') AS protrftypes, "
+                                                 "prokind, provolatile, proisstrict, prosecdef, "
+                                                 "proleakproof, proconfig, procost, prorows, "
+                                                 "prosupport, proparallel, "
+                                                 "(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 (fout->remoteVersion >= 110000)
+       {
+               /*
+                * prokind was added in 11
+                */
+               appendPQExpBuffer(query,
+                                                 "SELECT proretset, prosrc, probin, "
+                                                 "pg_catalog.pg_get_function_arguments(oid) AS funcargs, "
+                                                 "pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
+                                                 "pg_catalog.pg_get_function_result(oid) AS funcresult, "
+                                                 "array_to_string(protrftypes, ' ') AS protrftypes, "
+                                                 "prokind, provolatile, proisstrict, prosecdef, "
+                                                 "proleakproof, proconfig, procost, prorows, "
+                                                 "'-' AS prosupport, proparallel, "
+                                                 "(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 (fout->remoteVersion >= 90600)
        {
                /*
                 * proparallel was added in 9.6
@@ -11637,9 +11671,10 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                                                  "pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
                                                  "pg_catalog.pg_get_function_result(oid) AS funcresult, "
                                                  "array_to_string(protrftypes, ' ') AS protrftypes, "
-                                                 "proiswindow, provolatile, proisstrict, prosecdef, "
+                                                 "CASE WHEN proiswindow THEN 'w' ELSE 'f' END AS prokind, "
+                                                 "provolatile, proisstrict, prosecdef, "
                                                  "proleakproof, proconfig, procost, prorows, "
-                                                 "proparallel, "
+                                                 "'-' AS prosupport, proparallel, "
                                                  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
                                                  "FROM pg_catalog.pg_proc "
                                                  "WHERE oid = '%u'::pg_catalog.oid",
@@ -11656,8 +11691,10 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                                                  "pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
                                                  "pg_catalog.pg_get_function_result(oid) AS funcresult, "
                                                  "array_to_string(protrftypes, ' ') AS protrftypes, "
-                                                 "proiswindow, provolatile, proisstrict, prosecdef, "
+                                                 "CASE WHEN proiswindow THEN 'w' ELSE 'f' END AS prokind, "
+                                                 "provolatile, proisstrict, prosecdef, "
                                                  "proleakproof, proconfig, procost, prorows, "
+                                                 "'-' AS prosupport, "
                                                  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
                                                  "FROM pg_catalog.pg_proc "
                                                  "WHERE oid = '%u'::pg_catalog.oid",
@@ -11673,8 +11710,10 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                                                  "pg_catalog.pg_get_function_arguments(oid) AS funcargs, "
                                                  "pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
                                                  "pg_catalog.pg_get_function_result(oid) AS funcresult, "
-                                                 "proiswindow, provolatile, proisstrict, prosecdef, "
+                                                 "CASE WHEN proiswindow THEN 'w' ELSE 'f' END AS prokind, "
+                                                 "provolatile, proisstrict, prosecdef, "
                                                  "proleakproof, proconfig, procost, prorows, "
+                                                 "'-' AS prosupport, "
                                                  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
                                                  "FROM pg_catalog.pg_proc "
                                                  "WHERE oid = '%u'::pg_catalog.oid",
@@ -11691,9 +11730,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                                                  "pg_catalog.pg_get_function_arguments(oid) AS funcargs, "
                                                  "pg_catalog.pg_get_function_identity_arguments(oid) AS funciargs, "
                                                  "pg_catalog.pg_get_function_result(oid) AS funcresult, "
-                                                 "proiswindow, provolatile, proisstrict, prosecdef, "
+                                                 "CASE WHEN proiswindow THEN 'w' ELSE 'f' END AS prokind, "
+                                                 "provolatile, proisstrict, prosecdef, "
                                                  "false AS proleakproof, "
                                                  " proconfig, procost, prorows, "
+                                                 "'-' AS prosupport, "
                                                  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
                                                  "FROM pg_catalog.pg_proc "
                                                  "WHERE oid = '%u'::pg_catalog.oid",
@@ -11704,10 +11745,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                appendPQExpBuffer(query,
                                                  "SELECT proretset, prosrc, probin, "
                                                  "proallargtypes, proargmodes, proargnames, "
-                                                 "false AS proiswindow, "
+                                                 "'f' AS prokind, "
                                                  "provolatile, proisstrict, prosecdef, "
                                                  "false AS proleakproof, "
                                                  "proconfig, procost, prorows, "
+                                                 "'-' AS prosupport, "
                                                  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
                                                  "FROM pg_catalog.pg_proc "
                                                  "WHERE oid = '%u'::pg_catalog.oid",
@@ -11718,10 +11760,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                appendPQExpBuffer(query,
                                                  "SELECT proretset, prosrc, probin, "
                                                  "proallargtypes, proargmodes, proargnames, "
-                                                 "false AS proiswindow, "
+                                                 "'f' AS prokind, "
                                                  "provolatile, proisstrict, prosecdef, "
                                                  "false AS proleakproof, "
                                                  "null AS proconfig, 0 AS procost, 0 AS prorows, "
+                                                 "'-' AS prosupport, "
                                                  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
                                                  "FROM pg_catalog.pg_proc "
                                                  "WHERE oid = '%u'::pg_catalog.oid",
@@ -11734,10 +11777,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                                                  "null AS proallargtypes, "
                                                  "null AS proargmodes, "
                                                  "proargnames, "
-                                                 "false AS proiswindow, "
+                                                 "'f' AS prokind, "
                                                  "provolatile, proisstrict, prosecdef, "
                                                  "false AS proleakproof, "
                                                  "null AS proconfig, 0 AS procost, 0 AS prorows, "
+                                                 "'-' AS prosupport, "
                                                  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname "
                                                  "FROM pg_catalog.pg_proc "
                                                  "WHERE oid = '%u'::pg_catalog.oid",
@@ -11753,11 +11797,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        {
                funcargs = PQgetvalue(res, 0, PQfnumber(res, "funcargs"));
                funciargs = PQgetvalue(res, 0, PQfnumber(res, "funciargs"));
-               is_procedure = PQgetisnull(res, 0, PQfnumber(res, "funcresult"));
-               if (is_procedure)
-                       funcresult = NULL;
-               else
-                       funcresult = PQgetvalue(res, 0, PQfnumber(res, "funcresult"));
+               funcresult = PQgetvalue(res, 0, PQfnumber(res, "funcresult"));
                proallargtypes = proargmodes = proargnames = NULL;
        }
        else
@@ -11766,13 +11806,12 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                proargmodes = PQgetvalue(res, 0, PQfnumber(res, "proargmodes"));
                proargnames = PQgetvalue(res, 0, PQfnumber(res, "proargnames"));
                funcargs = funciargs = funcresult = NULL;
-               is_procedure = false;
        }
        if (PQfnumber(res, "protrftypes") != -1)
                protrftypes = PQgetvalue(res, 0, PQfnumber(res, "protrftypes"));
        else
                protrftypes = NULL;
-       proiswindow = PQgetvalue(res, 0, PQfnumber(res, "proiswindow"));
+       prokind = PQgetvalue(res, 0, PQfnumber(res, "prokind"));
        provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
        proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
        prosecdef = PQgetvalue(res, 0, PQfnumber(res, "prosecdef"));
@@ -11780,6 +11819,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        proconfig = PQgetvalue(res, 0, PQfnumber(res, "proconfig"));
        procost = PQgetvalue(res, 0, PQfnumber(res, "procost"));
        prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows"));
+       prosupport = PQgetvalue(res, 0, PQfnumber(res, "prosupport"));
 
        if (PQfnumber(res, "proparallel") != -1)
                proparallel = PQgetvalue(res, 0, PQfnumber(res, "proparallel"));
@@ -11835,7 +11875,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                if (!parsePGArray(proallargtypes, &allargtypes, &nitems) ||
                        nitems < finfo->nargs)
                {
-                       write_msg(NULL, "WARNING: could not parse proallargtypes array\n");
+                       pg_log_warning("could not parse proallargtypes array");
                        if (allargtypes)
                                free(allargtypes);
                        allargtypes = NULL;
@@ -11851,7 +11891,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                if (!parsePGArray(proargmodes, &argmodes, &nitems) ||
                        nitems != nallargs)
                {
-                       write_msg(NULL, "WARNING: could not parse proargmodes array\n");
+                       pg_log_warning("could not parse proargmodes array");
                        if (argmodes)
                                free(argmodes);
                        argmodes = NULL;
@@ -11865,7 +11905,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                if (!parsePGArray(proargnames, &argnames, &nitems) ||
                        nitems != nallargs)
                {
-                       write_msg(NULL, "WARNING: could not parse proargnames array\n");
+                       pg_log_warning("could not parse proargnames array");
                        if (argnames)
                                free(argnames);
                        argnames = NULL;
@@ -11876,7 +11916,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        {
                if (!parsePGArray(proconfig, &configitems, &nconfigitems))
                {
-                       write_msg(NULL, "WARNING: could not parse proconfig array\n");
+                       pg_log_warning("could not parse proconfig array");
                        if (configitems)
                                free(configitems);
                        configitems = NULL;
@@ -11898,22 +11938,24 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 
        funcsig_tag = format_function_signature(fout, finfo, false);
 
-       keyword = is_procedure ? "PROCEDURE" : "FUNCTION";
+       if (prokind[0] == PROKIND_PROCEDURE)
+               keyword = "PROCEDURE";
+       else
+               keyword = "FUNCTION";   /* works for window functions too */
 
-       /*
-        * DROP must be fully qualified in case same name appears in pg_catalog
-        */
        appendPQExpBuffer(delqry, "DROP %s %s.%s;\n",
                                          keyword,
                                          fmtId(finfo->dobj.namespace->dobj.name),
                                          funcsig);
 
-       appendPQExpBuffer(q, "CREATE %s %s",
+       appendPQExpBuffer(q, "CREATE %s %s.%s",
                                          keyword,
+                                         fmtId(finfo->dobj.namespace->dobj.name),
                                          funcfullsig ? funcfullsig :
                                          funcsig);
-       if (is_procedure)
-               ;
+
+       if (prokind[0] == PROKIND_PROCEDURE)
+                /* no result type to output */ ;
        else if (funcresult)
                appendPQExpBuffer(q, " RETURNS %s", funcresult);
        else
@@ -11944,7 +11986,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                }
        }
 
-       if (proiswindow[0] == 't')
+       if (prokind[0] == PROKIND_WINDOW)
                appendPQExpBufferStr(q, " WINDOW");
 
        if (provolatile[0] != PROVOLATILE_VOLATILE)
@@ -11954,8 +11996,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                else if (provolatile[0] == PROVOLATILE_STABLE)
                        appendPQExpBufferStr(q, " STABLE");
                else if (provolatile[0] != PROVOLATILE_VOLATILE)
-                       exit_horribly(NULL, "unrecognized provolatile value for function \"%s\"\n",
-                                                 finfo->dobj.name);
+                       fatal("unrecognized provolatile value for function \"%s\"",
+                                 finfo->dobj.name);
        }
 
        if (proisstrict[0] == 't')
@@ -11991,6 +12033,12 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                strcmp(prorows, "0") != 0 && strcmp(prorows, "1000") != 0)
                appendPQExpBuffer(q, " ROWS %s", prorows);
 
+       if (strcmp(prosupport, "-") != 0)
+       {
+               /* We rely on regprocout to provide quoting and qualification */
+               appendPQExpBuffer(q, " SUPPORT %s", prosupport);
+       }
+
        if (proparallel != NULL && proparallel[0] != PROPARALLEL_UNSAFE)
        {
                if (proparallel[0] == PROPARALLEL_SAFE)
@@ -11998,8 +12046,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                else if (proparallel[0] == PROPARALLEL_RESTRICTED)
                        appendPQExpBufferStr(q, " PARALLEL RESTRICTED");
                else if (proparallel[0] != PROPARALLEL_UNSAFE)
-                       exit_horribly(NULL, "unrecognized proparallel value for function \"%s\"\n",
-                                                 finfo->dobj.name);
+                       fatal("unrecognized proparallel value for function \"%s\"",
+                                 finfo->dobj.name);
        }
 
        for (i = 0; i < nconfigitems; i++)
@@ -12015,48 +12063,73 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                appendPQExpBuffer(q, "\n    SET %s TO ", fmtId(configitem));
 
                /*
-                * Some GUC variable names are 'LIST' type and hence must not be
-                * quoted.
+                * Variables that are marked GUC_LIST_QUOTE were already fully quoted
+                * by flatten_set_variable_args() before they were put into the
+                * proconfig array.  However, because the quoting rules used there
+                * aren't exactly like SQL's, we have to break the list value apart
+                * and then quote the elements as string literals.  (The elements may
+                * be double-quoted as-is, but we can't just feed them to the SQL
+                * parser; it would do the wrong thing with elements that are
+                * zero-length or longer than NAMEDATALEN.)
+                *
+                * Variables that are not so marked should just be emitted as simple
+                * string literals.  If the variable is not known to
+                * variable_is_guc_list_quote(), we'll do that; this makes it unsafe
+                * to use GUC_LIST_QUOTE for extension variables.
                 */
-               if (pg_strcasecmp(configitem, "DateStyle") == 0
-                       || pg_strcasecmp(configitem, "search_path") == 0)
-                       appendPQExpBufferStr(q, pos);
+               if (variable_is_guc_list_quote(configitem))
+               {
+                       char      **namelist;
+                       char      **nameptr;
+
+                       /* Parse string into list of identifiers */
+                       /* this shouldn't fail really */
+                       if (SplitGUCList(pos, ',', &namelist))
+                       {
+                               for (nameptr = namelist; *nameptr; nameptr++)
+                               {
+                                       if (nameptr != namelist)
+                                               appendPQExpBufferStr(q, ", ");
+                                       appendStringLiteralAH(q, *nameptr, fout);
+                               }
+                       }
+                       pg_free(namelist);
+               }
                else
                        appendStringLiteralAH(q, pos, fout);
        }
 
        appendPQExpBuffer(q, "\n    %s;\n", asPart->data);
 
-       appendPQExpBuffer(labelq, "%s %s", keyword, funcsig);
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &finfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &finfo->dobj,
+                                                                               keyword, funcsig,
+                                                                               finfo->dobj.namespace->dobj.name);
 
        if (finfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
-                                        funcsig_tag,
-                                        finfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        finfo->rolname, false,
-                                        keyword, SECTION_PRE_DATA,
-                                        q->data, delqry->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = funcsig_tag,
+                                                                 .namespace = finfo->dobj.namespace->dobj.name,
+                                                                 .owner = finfo->rolname,
+                                                                 .description = keyword,
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delqry->data));
 
        /* Dump Function Comments and Security Labels */
        if (finfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, keyword, funcsig,
                                        finfo->dobj.namespace->dobj.name, finfo->rolname,
                                        finfo->dobj.catId, 0, finfo->dobj.dumpId);
 
        if (finfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, keyword, funcsig,
                                         finfo->dobj.namespace->dobj.name, finfo->rolname,
                                         finfo->dobj.catId, 0, finfo->dobj.dumpId);
 
        if (finfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, finfo->dobj.catId, finfo->dobj.dumpId, keyword,
-                               funcsig, NULL, labelq->data,
+                               funcsig, NULL,
                                finfo->dobj.namespace->dobj.name,
                                finfo->rolname, finfo->proacl, finfo->rproacl,
                                finfo->initproacl, finfo->initrproacl);
@@ -12066,7 +12139,6 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delqry);
-       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(asPart);
        free(funcsig);
        if (funcfullsig)
@@ -12093,6 +12165,7 @@ dumpCast(Archive *fout, CastInfo *cast)
        PQExpBuffer defqry;
        PQExpBuffer delqry;
        PQExpBuffer labelq;
+       PQExpBuffer castargs;
        FuncInfo   *funcInfo = NULL;
        char       *sourceType;
        char       *targetType;
@@ -12106,19 +12179,14 @@ dumpCast(Archive *fout, CastInfo *cast)
        {
                funcInfo = findFuncByOid(cast->castfunc);
                if (funcInfo == NULL)
-                       exit_horribly(NULL, "could not find function definition for function with OID %u\n",
-                                                 cast->castfunc);
+                       fatal("could not find function definition for function with OID %u",
+                                 cast->castfunc);
        }
 
-       /*
-        * Make sure we are in proper schema (needed for getFormattedTypeName).
-        * Casts don't have a schema of their own, so use pg_catalog.
-        */
-       selectSourceSchema(fout, "pg_catalog");
-
        defqry = createPQExpBuffer();
        delqry = createPQExpBuffer();
        labelq = createPQExpBuffer();
+       castargs = createPQExpBuffer();
 
        sourceType = getFormattedTypeName(fout, cast->castsource, zeroAsNone);
        targetType = getFormattedTypeName(fout, cast->casttarget, zeroAsNone);
@@ -12142,19 +12210,18 @@ dumpCast(Archive *fout, CastInfo *cast)
                                char       *fsig = format_function_signature(fout, funcInfo, true);
 
                                /*
-                                * Always qualify the function name, in case it is not in
-                                * pg_catalog schema (format_function_signature won't qualify
-                                * it).
+                                * Always qualify the function name (format_function_signature
+                                * won't qualify it).
                                 */
                                appendPQExpBuffer(defqry, "WITH FUNCTION %s.%s",
                                                                  fmtId(funcInfo->dobj.namespace->dobj.name), fsig);
                                free(fsig);
                        }
                        else
-                               write_msg(NULL, "WARNING: bogus value in pg_cast.castfunc or pg_cast.castmethod field\n");
+                               pg_log_warning("bogus value in pg_cast.castfunc or pg_cast.castmethod field");
                        break;
                default:
-                       write_msg(NULL, "WARNING: bogus value in pg_cast.castmethod field\n");
+                       pg_log_warning("bogus value in pg_cast.castmethod field");
        }
 
        if (cast->castcontext == 'a')
@@ -12166,22 +12233,25 @@ dumpCast(Archive *fout, CastInfo *cast)
        appendPQExpBuffer(labelq, "CAST (%s AS %s)",
                                          sourceType, targetType);
 
+       appendPQExpBuffer(castargs, "(%s AS %s)",
+                                         sourceType, targetType);
+
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(defqry, &cast->dobj, labelq->data);
+               binary_upgrade_extension_member(defqry, &cast->dobj,
+                                                                               "CAST", castargs->data, NULL);
 
        if (cast->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId,
-                                        labelq->data,
-                                        "pg_catalog", NULL, "",
-                                        false, "CAST", SECTION_PRE_DATA,
-                                        defqry->data, delqry->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = labelq->data,
+                                                                 .description = "CAST",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = defqry->data,
+                                                                 .dropStmt = delqry->data));
 
        /* Dump Cast Comments */
        if (cast->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
-                                       "pg_catalog", "",
+               dumpComment(fout, "CAST", castargs->data,
+                                       NULL, "",
                                        cast->dobj.catId, 0, cast->dobj.dumpId);
 
        free(sourceType);
@@ -12190,6 +12260,7 @@ dumpCast(Archive *fout, CastInfo *cast)
        destroyPQExpBuffer(defqry);
        destroyPQExpBuffer(delqry);
        destroyPQExpBuffer(labelq);
+       destroyPQExpBuffer(castargs);
 }
 
 /*
@@ -12202,6 +12273,7 @@ dumpTransform(Archive *fout, TransformInfo *transform)
        PQExpBuffer defqry;
        PQExpBuffer delqry;
        PQExpBuffer labelq;
+       PQExpBuffer transformargs;
        FuncInfo   *fromsqlFuncInfo = NULL;
        FuncInfo   *tosqlFuncInfo = NULL;
        char       *lanname;
@@ -12216,23 +12288,21 @@ dumpTransform(Archive *fout, TransformInfo *transform)
        {
                fromsqlFuncInfo = findFuncByOid(transform->trffromsql);
                if (fromsqlFuncInfo == NULL)
-                       exit_horribly(NULL, "could not find function definition for function with OID %u\n",
-                                                 transform->trffromsql);
+                       fatal("could not find function definition for function with OID %u",
+                                 transform->trffromsql);
        }
        if (OidIsValid(transform->trftosql))
        {
                tosqlFuncInfo = findFuncByOid(transform->trftosql);
                if (tosqlFuncInfo == NULL)
-                       exit_horribly(NULL, "could not find function definition for function with OID %u\n",
-                                                 transform->trftosql);
+                       fatal("could not find function definition for function with OID %u",
+                                 transform->trftosql);
        }
 
-       /* Make sure we are in proper schema (needed for getFormattedTypeName) */
-       selectSourceSchema(fout, "pg_catalog");
-
        defqry = createPQExpBuffer();
        delqry = createPQExpBuffer();
        labelq = createPQExpBuffer();
+       transformargs = createPQExpBuffer();
 
        lanname = get_language_name(fout, transform->trflang);
        transformType = getFormattedTypeName(fout, transform->trftype, zeroAsNone);
@@ -12244,7 +12314,7 @@ dumpTransform(Archive *fout, TransformInfo *transform)
                                          transformType, lanname);
 
        if (!transform->trffromsql && !transform->trftosql)
-               write_msg(NULL, "WARNING: bogus transform definition, at least one of trffromsql and trftosql should be nonzero\n");
+               pg_log_warning("bogus transform definition, at least one of trffromsql and trftosql should be nonzero");
 
        if (transform->trffromsql)
        {
@@ -12253,59 +12323,64 @@ dumpTransform(Archive *fout, TransformInfo *transform)
                        char       *fsig = format_function_signature(fout, fromsqlFuncInfo, true);
 
                        /*
-                        * Always qualify the function name, in case it is not in
-                        * pg_catalog schema (format_function_signature won't qualify it).
+                        * Always qualify the function name (format_function_signature
+                        * won't qualify it).
                         */
                        appendPQExpBuffer(defqry, "FROM SQL WITH FUNCTION %s.%s",
                                                          fmtId(fromsqlFuncInfo->dobj.namespace->dobj.name), fsig);
                        free(fsig);
                }
                else
-                       write_msg(NULL, "WARNING: bogus value in pg_transform.trffromsql field\n");
+                       pg_log_warning("bogus value in pg_transform.trffromsql field");
        }
 
        if (transform->trftosql)
        {
                if (transform->trffromsql)
-                       appendPQExpBuffer(defqry, ", ");
+                       appendPQExpBufferStr(defqry, ", ");
 
                if (tosqlFuncInfo)
                {
                        char       *fsig = format_function_signature(fout, tosqlFuncInfo, true);
 
                        /*
-                        * Always qualify the function name, in case it is not in
-                        * pg_catalog schema (format_function_signature won't qualify it).
+                        * Always qualify the function name (format_function_signature
+                        * won't qualify it).
                         */
                        appendPQExpBuffer(defqry, "TO SQL WITH FUNCTION %s.%s",
                                                          fmtId(tosqlFuncInfo->dobj.namespace->dobj.name), fsig);
                        free(fsig);
                }
                else
-                       write_msg(NULL, "WARNING: bogus value in pg_transform.trftosql field\n");
+                       pg_log_warning("bogus value in pg_transform.trftosql field");
        }
 
-       appendPQExpBuffer(defqry, ");\n");
+       appendPQExpBufferStr(defqry, ");\n");
 
        appendPQExpBuffer(labelq, "TRANSFORM FOR %s LANGUAGE %s",
                                          transformType, lanname);
 
+       appendPQExpBuffer(transformargs, "FOR %s LANGUAGE %s",
+                                         transformType, lanname);
+
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(defqry, &transform->dobj, labelq->data);
+               binary_upgrade_extension_member(defqry, &transform->dobj,
+                                                                               "TRANSFORM", transformargs->data, NULL);
 
        if (transform->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, transform->dobj.catId, transform->dobj.dumpId,
-                                        labelq->data,
-                                        "pg_catalog", NULL, "",
-                                        false, "TRANSFORM", SECTION_PRE_DATA,
-                                        defqry->data, delqry->data, NULL,
-                                        transform->dobj.dependencies, transform->dobj.nDeps,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = labelq->data,
+                                                                 .description = "TRANSFORM",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = defqry->data,
+                                                                 .dropStmt = delqry->data,
+                                                                 .deps = transform->dobj.dependencies,
+                                                                 .nDeps = transform->dobj.nDeps));
 
        /* Dump Transform Comments */
        if (transform->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
-                                       "pg_catalog", "",
+               dumpComment(fout, "TRANSFORM", transformargs->data,
+                                       NULL, "",
                                        transform->dobj.catId, 0, transform->dobj.dumpId);
 
        free(lanname);
@@ -12313,6 +12388,7 @@ dumpTransform(Archive *fout, TransformInfo *transform)
        destroyPQExpBuffer(defqry);
        destroyPQExpBuffer(delqry);
        destroyPQExpBuffer(labelq);
+       destroyPQExpBuffer(transformargs);
 }
 
 
@@ -12327,7 +12403,6 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
        PQExpBuffer oprid;
        PQExpBuffer details;
        PGresult   *res;
@@ -12368,21 +12443,17 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        query = createPQExpBuffer();
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
        oprid = createPQExpBuffer();
        details = createPQExpBuffer();
 
-       /* Make sure we are in proper schema so regoperator works correctly */
-       selectSourceSchema(fout, oprinfo->dobj.namespace->dobj.name);
-
        if (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, "
+                                                 "oprcom, "
+                                                 "oprnegate, "
                                                  "oprrest::pg_catalog.regprocedure, "
                                                  "oprjoin::pg_catalog.regprocedure, "
                                                  "oprcanmerge, oprcanhash "
@@ -12396,8 +12467,8 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
                                                  "oprcode::pg_catalog.regprocedure, "
                                                  "oprleft::pg_catalog.regtype, "
                                                  "oprright::pg_catalog.regtype, "
-                                                 "oprcom::pg_catalog.regoperator, "
-                                                 "oprnegate::pg_catalog.regoperator, "
+                                                 "oprcom, "
+                                                 "oprnegate, "
                                                  "oprrest::pg_catalog.regprocedure, "
                                                  "oprjoin::pg_catalog.regprocedure, "
                                                  "(oprlsortop != 0) AS oprcanmerge, "
@@ -12434,7 +12505,7 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        oprregproc = convertRegProcReference(fout, oprcode);
        if (oprregproc)
        {
-               appendPQExpBuffer(details, "    PROCEDURE = %s", oprregproc);
+               appendPQExpBuffer(details, "    FUNCTION = %s", oprregproc);
                free(oprregproc);
        }
 
@@ -12463,14 +12534,14 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        else
                appendPQExpBufferStr(oprid, ", NONE)");
 
-       oprref = convertOperatorReference(fout, oprcom);
+       oprref = getFormattedOperatorName(fout, oprcom);
        if (oprref)
        {
                appendPQExpBuffer(details, ",\n    COMMUTATOR = %s", oprref);
                free(oprref);
        }
 
-       oprref = convertOperatorReference(fout, oprnegate);
+       oprref = getFormattedOperatorName(fout, oprnegate);
        if (oprref)
        {
                appendPQExpBuffer(details, ",\n    NEGATOR = %s", oprref);
@@ -12497,35 +12568,32 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
                free(oprregproc);
        }
 
-       /*
-        * DROP must be fully qualified in case same name appears in pg_catalog
-        */
        appendPQExpBuffer(delq, "DROP OPERATOR %s.%s;\n",
                                          fmtId(oprinfo->dobj.namespace->dobj.name),
                                          oprid->data);
 
-       appendPQExpBuffer(q, "CREATE OPERATOR %s (\n%s\n);\n",
+       appendPQExpBuffer(q, "CREATE OPERATOR %s.%s (\n%s\n);\n",
+                                         fmtId(oprinfo->dobj.namespace->dobj.name),
                                          oprinfo->dobj.name, details->data);
 
-       appendPQExpBuffer(labelq, "OPERATOR %s", oprid->data);
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &oprinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &oprinfo->dobj,
+                                                                               "OPERATOR", oprid->data,
+                                                                               oprinfo->dobj.namespace->dobj.name);
 
        if (oprinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId,
-                                        oprinfo->dobj.name,
-                                        oprinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        oprinfo->rolname,
-                                        false, "OPERATOR", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = oprinfo->dobj.name,
+                                                                 .namespace = oprinfo->dobj.namespace->dobj.name,
+                                                                 .owner = oprinfo->rolname,
+                                                                 .description = "OPERATOR",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Operator Comments */
        if (oprinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "OPERATOR", oprid->data,
                                        oprinfo->dobj.namespace->dobj.name, oprinfo->rolname,
                                        oprinfo->dobj.catId, 0, oprinfo->dobj.dumpId);
 
@@ -12534,7 +12602,6 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(oprid);
        destroyPQExpBuffer(details);
 }
@@ -12576,49 +12643,39 @@ convertRegProcReference(Archive *fout, const char *proc)
 }
 
 /*
- * Convert an operator cross-reference obtained from pg_operator
+ * getFormattedOperatorName - retrieve the operator name for the
+ * given operator OID (presented in string form).
  *
- * Returns an allocated string of what to print, or NULL to print nothing.
+ * Returns an allocated string, or NULL if the given OID is invalid.
  * Caller is responsible for free'ing result string.
  *
- * The input is a REGOPERATOR display; we have to strip the argument-types
- * part, and add OPERATOR() decoration if the name is schema-qualified.
+ * What we produce has the format "OPERATOR(schema.oprname)".  This is only
+ * useful in commands where the operator's argument types can be inferred from
+ * context.  We always schema-qualify the name, though.  The predecessor to
+ * this code tried to skip the schema qualification if possible, but that led
+ * to wrong results in corner cases, such as if an operator and its negator
+ * are in different schemas.
  */
 static char *
-convertOperatorReference(Archive *fout, const char *opr)
+getFormattedOperatorName(Archive *fout, const char *oproid)
 {
-       char       *name;
-       char       *oname;
-       char       *ptr;
-       bool            inquote;
-       bool            sawdot;
+       OprInfo    *oprInfo;
 
        /* In all cases "0" means a null reference */
-       if (strcmp(opr, "0") == 0)
+       if (strcmp(oproid, "0") == 0)
                return NULL;
 
-       name = pg_strdup(opr);
-       /* find non-double-quoted left paren, and check for non-quoted dot */
-       inquote = false;
-       sawdot = false;
-       for (ptr = name; *ptr; ptr++)
+       oprInfo = findOprByOid(atooid(oproid));
+       if (oprInfo == NULL)
        {
-               if (*ptr == '"')
-                       inquote = !inquote;
-               else if (*ptr == '.' && !inquote)
-                       sawdot = true;
-               else if (*ptr == '(' && !inquote)
-               {
-                       *ptr = '\0';
-                       break;
-               }
+               pg_log_warning("could not find operator with OID %s",
+                                          oproid);
+               return NULL;
        }
-       /* If not schema-qualified, don't need to add OPERATOR() */
-       if (!sawdot)
-               return name;
-       oname = psprintf("OPERATOR(%s)", name);
-       free(name);
-       return oname;
+
+       return psprintf("OPERATOR(%s.%s)",
+                                       fmtId(oprInfo->dobj.namespace->dobj.name),
+                                       oprInfo->dobj.name);
 }
 
 /*
@@ -12657,7 +12714,6 @@ dumpAccessMethod(Archive *fout, AccessMethodInfo *aminfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
        char       *qamname;
 
        /* Skip if not to be dumped */
@@ -12666,7 +12722,6 @@ dumpAccessMethod(Archive *fout, AccessMethodInfo *aminfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
 
        qamname = pg_strdup(fmtId(aminfo->dobj.name));
 
@@ -12675,15 +12730,17 @@ dumpAccessMethod(Archive *fout, AccessMethodInfo *aminfo)
        switch (aminfo->amtype)
        {
                case AMTYPE_INDEX:
-                       appendPQExpBuffer(q, "TYPE INDEX ");
+                       appendPQExpBufferStr(q, "TYPE INDEX ");
+                       break;
+               case AMTYPE_TABLE:
+                       appendPQExpBufferStr(q, "TYPE TABLE ");
                        break;
                default:
-                       write_msg(NULL, "WARNING: invalid type \"%c\" of access method \"%s\"\n",
-                                         aminfo->amtype, qamname);
-                       pg_free(qamname);
+                       pg_log_warning("invalid type \"%c\" of access method \"%s\"",
+                                                  aminfo->amtype, qamname);
                        destroyPQExpBuffer(q);
                        destroyPQExpBuffer(delq);
-                       destroyPQExpBuffer(labelq);
+                       free(qamname);
                        return;
        }
 
@@ -12692,34 +12749,27 @@ dumpAccessMethod(Archive *fout, AccessMethodInfo *aminfo)
        appendPQExpBuffer(delq, "DROP ACCESS METHOD %s;\n",
                                          qamname);
 
-       appendPQExpBuffer(labelq, "ACCESS METHOD %s",
-                                         qamname);
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &aminfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &aminfo->dobj,
+                                                                               "ACCESS METHOD", qamname, NULL);
 
        if (aminfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, aminfo->dobj.catId, aminfo->dobj.dumpId,
-                                        aminfo->dobj.name,
-                                        NULL,
-                                        NULL,
-                                        "",
-                                        false, "ACCESS METHOD", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = aminfo->dobj.name,
+                                                                 .description = "ACCESS METHOD",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Access Method Comments */
        if (aminfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "ACCESS METHOD", qamname,
                                        NULL, "",
                                        aminfo->dobj.catId, 0, aminfo->dobj.dumpId);
 
-       pg_free(qamname);
-
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
+       free(qamname);
 }
 
 /*
@@ -12733,7 +12783,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
+       PQExpBuffer nameusing;
        PGresult   *res;
        int                     ntups;
        int                     i_opcintype;
@@ -12778,10 +12828,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        query = createPQExpBuffer();
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
-
-       /* Make sure we are in proper schema so regoperator works correctly */
-       selectSourceSchema(fout, opcinfo->dobj.namespace->dobj.name);
+       nameusing = createPQExpBuffer();
 
        /* Get additional fields from the pg_opclass row */
        if (fout->remoteVersion >= 80300)
@@ -12832,19 +12879,14 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        /* amname will still be needed after we PQclear res */
        amname = pg_strdup(PQgetvalue(res, 0, i_amname));
 
-       /*
-        * DROP must be fully qualified in case same name appears in pg_catalog
-        */
        appendPQExpBuffer(delq, "DROP OPERATOR CLASS %s",
-                                         fmtId(opcinfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delq, ".%s",
-                                         fmtId(opcinfo->dobj.name));
+                                         fmtQualifiedDumpable(opcinfo));
        appendPQExpBuffer(delq, " USING %s;\n",
                                          fmtId(amname));
 
        /* Build the fixed portion of the CREATE command */
        appendPQExpBuffer(q, "CREATE OPERATOR CLASS %s\n    ",
-                                         fmtId(opcinfo->dobj.name));
+                                         fmtQualifiedDumpable(opcinfo));
        if (strcmp(opcdefault, "t") == 0)
                appendPQExpBufferStr(q, "DEFAULT ");
        appendPQExpBuffer(q, "FOR TYPE %s USING %s",
@@ -12853,8 +12895,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        if (strlen(opcfamilyname) > 0)
        {
                appendPQExpBufferStr(q, " FAMILY ");
-               if (strcmp(opcfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
-                       appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp));
+               appendPQExpBuffer(q, "%s.", fmtId(opcfamilynsp));
                appendPQExpBufferStr(q, fmtId(opcfamilyname));
        }
        appendPQExpBufferStr(q, " AS\n    ");
@@ -12972,8 +13013,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
                if (strlen(sortfamily) > 0)
                {
                        appendPQExpBufferStr(q, " FOR ORDER BY ");
-                       if (strcmp(sortfamilynsp, opcinfo->dobj.namespace->dobj.name) != 0)
-                               appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
+                       appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
                        appendPQExpBufferStr(q, fmtId(sortfamily));
                }
 
@@ -13067,28 +13107,28 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
 
        appendPQExpBufferStr(q, ";\n");
 
-       appendPQExpBuffer(labelq, "OPERATOR CLASS %s",
-                                         fmtId(opcinfo->dobj.name));
-       appendPQExpBuffer(labelq, " USING %s",
+       appendPQExpBufferStr(nameusing, fmtId(opcinfo->dobj.name));
+       appendPQExpBuffer(nameusing, " USING %s",
                                          fmtId(amname));
 
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &opcinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &opcinfo->dobj,
+                                                                               "OPERATOR CLASS", nameusing->data,
+                                                                               opcinfo->dobj.namespace->dobj.name);
 
        if (opcinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId,
-                                        opcinfo->dobj.name,
-                                        opcinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        opcinfo->rolname,
-                                        false, "OPERATOR CLASS", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = opcinfo->dobj.name,
+                                                                 .namespace = opcinfo->dobj.namespace->dobj.name,
+                                                                 .owner = opcinfo->rolname,
+                                                                 .description = "OPERATOR CLASS",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Operator Class Comments */
        if (opcinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "OPERATOR CLASS", nameusing->data,
                                        opcinfo->dobj.namespace->dobj.name, opcinfo->rolname,
                                        opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId);
 
@@ -13098,7 +13138,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
+       destroyPQExpBuffer(nameusing);
 }
 
 /*
@@ -13115,7 +13155,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
+       PQExpBuffer nameusing;
        PGresult   *res;
        PGresult   *res_ops;
        PGresult   *res_procs;
@@ -13150,10 +13190,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
        query = createPQExpBuffer();
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
-
-       /* Make sure we are in proper schema so regoperator works correctly */
-       selectSourceSchema(fout, opfinfo->dobj.namespace->dobj.name);
+       nameusing = createPQExpBuffer();
 
        /*
         * Fetch only those opfamily members that are tied directly to the
@@ -13245,19 +13282,14 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
        /* amname will still be needed after we PQclear res */
        amname = pg_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));
+                                         fmtQualifiedDumpable(opfinfo));
        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));
+                                         fmtQualifiedDumpable(opfinfo));
        appendPQExpBuffer(q, " USING %s;\n",
                                          fmtId(amname));
 
@@ -13267,7 +13299,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
        if (PQntuples(res_ops) > 0 || PQntuples(res_procs) > 0)
        {
                appendPQExpBuffer(q, "ALTER OPERATOR FAMILY %s",
-                                                 fmtId(opfinfo->dobj.name));
+                                                 fmtQualifiedDumpable(opfinfo));
                appendPQExpBuffer(q, " USING %s ADD\n    ",
                                                  fmtId(amname));
 
@@ -13301,8 +13333,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
                        if (strlen(sortfamily) > 0)
                        {
                                appendPQExpBufferStr(q, " FOR ORDER BY ");
-                               if (strcmp(sortfamilynsp, opfinfo->dobj.namespace->dobj.name) != 0)
-                                       appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
+                               appendPQExpBuffer(q, "%s.", fmtId(sortfamilynsp));
                                appendPQExpBufferStr(q, fmtId(sortfamily));
                        }
 
@@ -13342,28 +13373,28 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
                appendPQExpBufferStr(q, ";\n");
        }
 
-       appendPQExpBuffer(labelq, "OPERATOR FAMILY %s",
-                                         fmtId(opfinfo->dobj.name));
-       appendPQExpBuffer(labelq, " USING %s",
+       appendPQExpBufferStr(nameusing, fmtId(opfinfo->dobj.name));
+       appendPQExpBuffer(nameusing, " USING %s",
                                          fmtId(amname));
 
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &opfinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &opfinfo->dobj,
+                                                                               "OPERATOR FAMILY", nameusing->data,
+                                                                               opfinfo->dobj.namespace->dobj.name);
 
        if (opfinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId,
-                                        opfinfo->dobj.name,
-                                        opfinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        opfinfo->rolname,
-                                        false, "OPERATOR FAMILY", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = opfinfo->dobj.name,
+                                                                 .namespace = opfinfo->dobj.namespace->dobj.name,
+                                                                 .owner = opfinfo->rolname,
+                                                                 .description = "OPERATOR FAMILY",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Operator Family Comments */
        if (opfinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "OPERATOR FAMILY", nameusing->data,
                                        opfinfo->dobj.namespace->dobj.name, opfinfo->rolname,
                                        opfinfo->dobj.catId, 0, opfinfo->dobj.dumpId);
 
@@ -13373,7 +13404,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
+       destroyPQExpBuffer(nameusing);
 }
 
 /*
@@ -13387,9 +13418,10 @@ dumpCollation(Archive *fout, CollInfo *collinfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
+       char       *qcollname;
        PGresult   *res;
        int                     i_collprovider;
+       int                     i_collisdeterministic;
        int                     i_collcollate;
        int                     i_collctype;
        const char *collprovider;
@@ -13403,34 +13435,39 @@ dumpCollation(Archive *fout, CollInfo *collinfo)
        query = createPQExpBuffer();
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, collinfo->dobj.namespace->dobj.name);
+       qcollname = pg_strdup(fmtId(collinfo->dobj.name));
 
        /* Get collation-specific details */
+       appendPQExpBufferStr(query, "SELECT ");
+
        if (fout->remoteVersion >= 100000)
-               appendPQExpBuffer(query, "SELECT "
-                                                 "collprovider, "
-                                                 "collcollate, "
-                                                 "collctype, "
-                                                 "collversion "
-                                                 "FROM pg_catalog.pg_collation c "
-                                                 "WHERE c.oid = '%u'::pg_catalog.oid",
-                                                 collinfo->dobj.catId.oid);
+               appendPQExpBufferStr(query,
+                                                        "collprovider, "
+                                                        "collversion, ");
        else
-               appendPQExpBuffer(query, "SELECT "
-                                                 "'c' AS collprovider, "
-                                                 "collcollate, "
-                                                 "collctype, "
-                                                 "NULL AS collversion "
-                                                 "FROM pg_catalog.pg_collation c "
-                                                 "WHERE c.oid = '%u'::pg_catalog.oid",
-                                                 collinfo->dobj.catId.oid);
+               appendPQExpBufferStr(query,
+                                                        "'c' AS collprovider, "
+                                                        "NULL AS collversion, ");
+
+       if (fout->remoteVersion >= 120000)
+               appendPQExpBufferStr(query,
+                                                        "collisdeterministic, ");
+       else
+               appendPQExpBufferStr(query,
+                                                        "true AS collisdeterministic, ");
+
+       appendPQExpBuffer(query,
+                                         "collcollate, "
+                                         "collctype "
+                                         "FROM pg_catalog.pg_collation c "
+                                         "WHERE c.oid = '%u'::pg_catalog.oid",
+                                         collinfo->dobj.catId.oid);
 
        res = ExecuteSqlQueryForSingleRow(fout, query->data);
 
        i_collprovider = PQfnumber(res, "collprovider");
+       i_collisdeterministic = PQfnumber(res, "collisdeterministic");
        i_collcollate = PQfnumber(res, "collcollate");
        i_collctype = PQfnumber(res, "collctype");
 
@@ -13438,16 +13475,11 @@ dumpCollation(Archive *fout, CollInfo *collinfo)
        collcollate = PQgetvalue(res, 0, i_collcollate);
        collctype = PQgetvalue(res, 0, i_collctype);
 
-       /*
-        * DROP must be fully qualified in case same name appears in pg_catalog
-        */
-       appendPQExpBuffer(delq, "DROP COLLATION %s",
-                                         fmtId(collinfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delq, ".%s;\n",
-                                         fmtId(collinfo->dobj.name));
+       appendPQExpBuffer(delq, "DROP COLLATION %s;\n",
+                                         fmtQualifiedDumpable(collinfo));
 
        appendPQExpBuffer(q, "CREATE COLLATION %s (",
-                                         fmtId(collinfo->dobj.name));
+                                         fmtQualifiedDumpable(collinfo));
 
        appendPQExpBufferStr(q, "provider = ");
        if (collprovider[0] == 'c')
@@ -13458,9 +13490,11 @@ dumpCollation(Archive *fout, CollInfo *collinfo)
                /* to allow dumping pg_catalog; not accepted on input */
                appendPQExpBufferStr(q, "default");
        else
-               exit_horribly(NULL,
-                                         "unrecognized collation provider: %s\n",
-                                         collprovider);
+               fatal("unrecognized collation provider: %s",
+                         collprovider);
+
+       if (strcmp(PQgetvalue(res, 0, i_collisdeterministic), "f") == 0)
+               appendPQExpBufferStr(q, ", deterministic = false");
 
        if (strcmp(collcollate, collctype) == 0)
        {
@@ -13495,25 +13529,24 @@ dumpCollation(Archive *fout, CollInfo *collinfo)
 
        appendPQExpBufferStr(q, ");\n");
 
-       appendPQExpBuffer(labelq, "COLLATION %s", fmtId(collinfo->dobj.name));
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &collinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &collinfo->dobj,
+                                                                               "COLLATION", qcollname,
+                                                                               collinfo->dobj.namespace->dobj.name);
 
        if (collinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, collinfo->dobj.catId, collinfo->dobj.dumpId,
-                                        collinfo->dobj.name,
-                                        collinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        collinfo->rolname,
-                                        false, "COLLATION", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = collinfo->dobj.name,
+                                                                 .namespace = collinfo->dobj.namespace->dobj.name,
+                                                                 .owner = collinfo->rolname,
+                                                                 .description = "COLLATION",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Collation Comments */
        if (collinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "COLLATION", qcollname,
                                        collinfo->dobj.namespace->dobj.name, collinfo->rolname,
                                        collinfo->dobj.catId, 0, collinfo->dobj.dumpId);
 
@@ -13522,7 +13555,7 @@ dumpCollation(Archive *fout, CollInfo *collinfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
+       free(qcollname);
 }
 
 /*
@@ -13536,7 +13569,7 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
+       char       *qconvname;
        PGresult   *res;
        int                     i_conforencoding;
        int                     i_contoencoding;
@@ -13554,10 +13587,8 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        query = createPQExpBuffer();
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, convinfo->dobj.namespace->dobj.name);
+       qconvname = pg_strdup(fmtId(convinfo->dobj.name));
 
        /* Get conversion-specific details */
        appendPQExpBuffer(query, "SELECT "
@@ -13580,42 +13611,36 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        conproc = PQgetvalue(res, 0, i_conproc);
        condefault = (PQgetvalue(res, 0, i_condefault)[0] == 't');
 
-       /*
-        * DROP must be fully qualified in case same name appears in pg_catalog
-        */
-       appendPQExpBuffer(delq, "DROP CONVERSION %s",
-                                         fmtId(convinfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delq, ".%s;\n",
-                                         fmtId(convinfo->dobj.name));
+       appendPQExpBuffer(delq, "DROP CONVERSION %s;\n",
+                                         fmtQualifiedDumpable(convinfo));
 
        appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
                                          (condefault) ? "DEFAULT " : "",
-                                         fmtId(convinfo->dobj.name));
+                                         fmtQualifiedDumpable(convinfo));
        appendStringLiteralAH(q, conforencoding, fout);
        appendPQExpBufferStr(q, " TO ");
        appendStringLiteralAH(q, contoencoding, fout);
        /* regproc output is already sufficiently quoted */
        appendPQExpBuffer(q, " FROM %s;\n", conproc);
 
-       appendPQExpBuffer(labelq, "CONVERSION %s", fmtId(convinfo->dobj.name));
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &convinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &convinfo->dobj,
+                                                                               "CONVERSION", qconvname,
+                                                                               convinfo->dobj.namespace->dobj.name);
 
        if (convinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId,
-                                        convinfo->dobj.name,
-                                        convinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        convinfo->rolname,
-                                        false, "CONVERSION", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = convinfo->dobj.name,
+                                                                 .namespace = convinfo->dobj.namespace->dobj.name,
+                                                                 .owner = convinfo->rolname,
+                                                                 .description = "CONVERSION",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Conversion Comments */
        if (convinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "CONVERSION", qconvname,
                                        convinfo->dobj.namespace->dobj.name, convinfo->rolname,
                                        convinfo->dobj.catId, 0, convinfo->dobj.dumpId);
 
@@ -13624,7 +13649,7 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
+       free(qconvname);
 }
 
 /*
@@ -13646,7 +13671,7 @@ format_aggregate_signature(AggInfo *agginfo, Archive *fout, bool honor_quotes)
                appendPQExpBufferStr(&buf, agginfo->aggfn.dobj.name);
 
        if (agginfo->aggfn.nargs == 0)
-               appendPQExpBuffer(&buf, "(*)");
+               appendPQExpBufferStr(&buf, "(*)");
        else
        {
                appendPQExpBufferChar(&buf, '(');
@@ -13678,7 +13703,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
        PQExpBuffer details;
        char       *aggsig;                     /* identity signature */
        char       *aggfullsig = NULL;  /* full signature */
@@ -13738,12 +13762,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        query = createPQExpBuffer();
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
        details = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, agginfo->aggfn.dobj.namespace->dobj.name);
-
        /* Get aggregate-specific details */
        if (fout->remoteVersion >= 110000)
        {
@@ -13753,7 +13773,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "aggminvtransfn, aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
                                                  "aggfinalextra, aggmfinalextra, "
                                                  "aggfinalmodify, aggmfinalmodify, "
-                                                 "aggsortop::pg_catalog.regoperator, "
+                                                 "aggsortop, "
                                                  "aggkind, "
                                                  "aggtransspace, agginitval, "
                                                  "aggmtransspace, aggminitval, "
@@ -13774,7 +13794,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "aggminvtransfn, aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
                                                  "aggfinalextra, aggmfinalextra, "
                                                  "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
-                                                 "aggsortop::pg_catalog.regoperator, "
+                                                 "aggsortop, "
                                                  "aggkind, "
                                                  "aggtransspace, agginitval, "
                                                  "aggmtransspace, aggminitval, "
@@ -13796,7 +13816,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "aggmfinalfn, aggmtranstype::pg_catalog.regtype, "
                                                  "aggfinalextra, aggmfinalextra, "
                                                  "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
-                                                 "aggsortop::pg_catalog.regoperator, "
+                                                 "aggsortop, "
                                                  "aggkind, "
                                                  "aggtransspace, agginitval, "
                                                  "aggmtransspace, aggminitval, "
@@ -13818,7 +13838,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "0 AS aggmtranstype, false AS aggfinalextra, "
                                                  "false AS aggmfinalextra, "
                                                  "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
-                                                 "aggsortop::pg_catalog.regoperator, "
+                                                 "aggsortop, "
                                                  "'n' AS aggkind, "
                                                  "0 AS aggtransspace, agginitval, "
                                                  "0 AS aggmtransspace, NULL AS aggminitval, "
@@ -13840,7 +13860,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                                  "0 AS aggmtranstype, false AS aggfinalextra, "
                                                  "false AS aggmfinalextra, "
                                                  "'0' AS aggfinalmodify, '0' AS aggmfinalmodify, "
-                                                 "aggsortop::pg_catalog.regoperator, "
+                                                 "aggsortop, "
                                                  "'n' AS aggkind, "
                                                  "0 AS aggtransspace, agginitval, "
                                                  "0 AS aggmtransspace, NULL AS aggminitval, "
@@ -13942,8 +13962,8 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
 
        if (!convertok)
        {
-               write_msg(NULL, "WARNING: aggregate function %s could not be dumped correctly for this database version; ignored\n",
-                                 aggsig);
+               pg_log_warning("aggregate function %s could not be dumped correctly for this database version; ignored",
+                                          aggsig);
 
                if (aggfullsig)
                        free(aggfullsig);
@@ -13990,15 +14010,15 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                case AGGMODIFY_READ_ONLY:
                                        appendPQExpBufferStr(details, ",\n    FINALFUNC_MODIFY = READ_ONLY");
                                        break;
-                               case AGGMODIFY_SHARABLE:
-                                       appendPQExpBufferStr(details, ",\n    FINALFUNC_MODIFY = SHARABLE");
+                               case AGGMODIFY_SHAREABLE:
+                                       appendPQExpBufferStr(details, ",\n    FINALFUNC_MODIFY = SHAREABLE");
                                        break;
                                case AGGMODIFY_READ_WRITE:
                                        appendPQExpBufferStr(details, ",\n    FINALFUNC_MODIFY = READ_WRITE");
                                        break;
                                default:
-                                       exit_horribly(NULL, "unrecognized aggfinalmodify value for aggregate \"%s\"\n",
-                                                                 agginfo->aggfn.dobj.name);
+                                       fatal("unrecognized aggfinalmodify value for aggregate \"%s\"",
+                                                 agginfo->aggfn.dobj.name);
                                        break;
                        }
                }
@@ -14046,21 +14066,21 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                case AGGMODIFY_READ_ONLY:
                                        appendPQExpBufferStr(details, ",\n    MFINALFUNC_MODIFY = READ_ONLY");
                                        break;
-                               case AGGMODIFY_SHARABLE:
-                                       appendPQExpBufferStr(details, ",\n    MFINALFUNC_MODIFY = SHARABLE");
+                               case AGGMODIFY_SHAREABLE:
+                                       appendPQExpBufferStr(details, ",\n    MFINALFUNC_MODIFY = SHAREABLE");
                                        break;
                                case AGGMODIFY_READ_WRITE:
                                        appendPQExpBufferStr(details, ",\n    MFINALFUNC_MODIFY = READ_WRITE");
                                        break;
                                default:
-                                       exit_horribly(NULL, "unrecognized aggmfinalmodify value for aggregate \"%s\"\n",
-                                                                 agginfo->aggfn.dobj.name);
+                                       fatal("unrecognized aggmfinalmodify value for aggregate \"%s\"",
+                                                 agginfo->aggfn.dobj.name);
                                        break;
                        }
                }
        }
 
-       aggsortconvop = convertOperatorReference(fout, aggsortop);
+       aggsortconvop = getFormattedOperatorName(fout, aggsortop);
        if (aggsortconvop)
        {
                appendPQExpBuffer(details, ",\n    SORTOP = %s",
@@ -14078,46 +14098,43 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                else if (proparallel[0] == PROPARALLEL_RESTRICTED)
                        appendPQExpBufferStr(details, ",\n    PARALLEL = restricted");
                else if (proparallel[0] != PROPARALLEL_UNSAFE)
-                       exit_horribly(NULL, "unrecognized proparallel value for function \"%s\"\n",
-                                                 agginfo->aggfn.dobj.name);
+                       fatal("unrecognized proparallel value for function \"%s\"",
+                                 agginfo->aggfn.dobj.name);
        }
 
-       /*
-        * 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",
+       appendPQExpBuffer(q, "CREATE AGGREGATE %s.%s (\n%s\n);\n",
+                                         fmtId(agginfo->aggfn.dobj.namespace->dobj.name),
                                          aggfullsig ? aggfullsig : aggsig, details->data);
 
-       appendPQExpBuffer(labelq, "AGGREGATE %s", aggsig);
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &agginfo->aggfn.dobj, labelq->data);
+               binary_upgrade_extension_member(q, &agginfo->aggfn.dobj,
+                                                                               "AGGREGATE", aggsig,
+                                                                               agginfo->aggfn.dobj.namespace->dobj.name);
 
        if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, agginfo->aggfn.dobj.catId,
                                         agginfo->aggfn.dobj.dumpId,
-                                        aggsig_tag,
-                                        agginfo->aggfn.dobj.namespace->dobj.name,
-                                        NULL,
-                                        agginfo->aggfn.rolname,
-                                        false, "AGGREGATE", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = aggsig_tag,
+                                                                 .namespace = agginfo->aggfn.dobj.namespace->dobj.name,
+                                                                 .owner = agginfo->aggfn.rolname,
+                                                                 .description = "AGGREGATE",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Aggregate Comments */
        if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "AGGREGATE", aggsig,
                                        agginfo->aggfn.dobj.namespace->dobj.name,
                                        agginfo->aggfn.rolname,
                                        agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
 
        if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, "AGGREGATE", aggsig,
                                         agginfo->aggfn.dobj.namespace->dobj.name,
                                         agginfo->aggfn.rolname,
                                         agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
@@ -14133,8 +14150,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
 
        if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
-                               "FUNCTION",
-                               aggsig, NULL, labelq->data,
+                               "FUNCTION", aggsig, NULL,
                                agginfo->aggfn.dobj.namespace->dobj.name,
                                agginfo->aggfn.rolname, agginfo->aggfn.proacl,
                                agginfo->aggfn.rproacl,
@@ -14150,7 +14166,6 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(details);
 }
 
@@ -14164,7 +14179,7 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
+       char       *qprsname;
 
        /* Skip if not to be dumped */
        if (!prsinfo->dobj.dump || dopt->dataOnly)
@@ -14172,13 +14187,11 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, prsinfo->dobj.namespace->dobj.name);
+       qprsname = pg_strdup(fmtId(prsinfo->dobj.name));
 
        appendPQExpBuffer(q, "CREATE TEXT SEARCH PARSER %s (\n",
-                                         fmtId(prsinfo->dobj.name));
+                                         fmtQualifiedDumpable(prsinfo));
 
        appendPQExpBuffer(q, "    START = %s,\n",
                                          convertTSFunction(fout, prsinfo->prsstart));
@@ -14192,40 +14205,32 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
        appendPQExpBuffer(q, "    LEXTYPES = %s );\n",
                                          convertTSFunction(fout, 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));
-
-       appendPQExpBuffer(labelq, "TEXT SEARCH PARSER %s",
-                                         fmtId(prsinfo->dobj.name));
+       appendPQExpBuffer(delq, "DROP TEXT SEARCH PARSER %s;\n",
+                                         fmtQualifiedDumpable(prsinfo));
 
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &prsinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &prsinfo->dobj,
+                                                                               "TEXT SEARCH PARSER", qprsname,
+                                                                               prsinfo->dobj.namespace->dobj.name);
 
        if (prsinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId,
-                                        prsinfo->dobj.name,
-                                        prsinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        "",
-                                        false, "TEXT SEARCH PARSER", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = prsinfo->dobj.name,
+                                                                 .namespace = prsinfo->dobj.namespace->dobj.name,
+                                                                 .description = "TEXT SEARCH PARSER",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Parser Comments */
        if (prsinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "TEXT SEARCH PARSER", qprsname,
                                        prsinfo->dobj.namespace->dobj.name, "",
                                        prsinfo->dobj.catId, 0, prsinfo->dobj.dumpId);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
+       free(qprsname);
 }
 
 /*
@@ -14238,8 +14243,8 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
        PQExpBuffer query;
+       char       *qdictname;
        PGresult   *res;
        char       *nspname;
        char       *tmplname;
@@ -14250,11 +14255,11 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
        query = createPQExpBuffer();
 
+       qdictname = pg_strdup(fmtId(dictinfo->dobj.name));
+
        /* Fetch name and namespace of the dictionary's template */
-       selectSourceSchema(fout, "pg_catalog");
        appendPQExpBuffer(query, "SELECT nspname, tmplname "
                                          "FROM pg_ts_template p, pg_namespace n "
                                          "WHERE p.oid = '%u' AND n.oid = tmplnamespace",
@@ -14263,15 +14268,11 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
        nspname = PQgetvalue(res, 0, 0);
        tmplname = PQgetvalue(res, 0, 1);
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, dictinfo->dobj.namespace->dobj.name);
-
        appendPQExpBuffer(q, "CREATE TEXT SEARCH DICTIONARY %s (\n",
-                                         fmtId(dictinfo->dobj.name));
+                                         fmtQualifiedDumpable(dictinfo));
 
        appendPQExpBufferStr(q, "    TEMPLATE = ");
-       if (strcmp(nspname, dictinfo->dobj.namespace->dobj.name) != 0)
-               appendPQExpBuffer(q, "%s.", fmtId(nspname));
+       appendPQExpBuffer(q, "%s.", fmtId(nspname));
        appendPQExpBufferStr(q, fmtId(tmplname));
 
        PQclear(res);
@@ -14282,41 +14283,34 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
 
        appendPQExpBufferStr(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));
-
-       appendPQExpBuffer(labelq, "TEXT SEARCH DICTIONARY %s",
-                                         fmtId(dictinfo->dobj.name));
+       appendPQExpBuffer(delq, "DROP TEXT SEARCH DICTIONARY %s;\n",
+                                         fmtQualifiedDumpable(dictinfo));
 
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &dictinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &dictinfo->dobj,
+                                                                               "TEXT SEARCH DICTIONARY", qdictname,
+                                                                               dictinfo->dobj.namespace->dobj.name);
 
        if (dictinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId,
-                                        dictinfo->dobj.name,
-                                        dictinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        dictinfo->rolname,
-                                        false, "TEXT SEARCH DICTIONARY", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = dictinfo->dobj.name,
+                                                                 .namespace = dictinfo->dobj.namespace->dobj.name,
+                                                                 .owner = dictinfo->rolname,
+                                                                 .description = "TEXT SEARCH DICTIONARY",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Dictionary Comments */
        if (dictinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "TEXT SEARCH DICTIONARY", qdictname,
                                        dictinfo->dobj.namespace->dobj.name, dictinfo->rolname,
                                        dictinfo->dobj.catId, 0, dictinfo->dobj.dumpId);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
+       free(qdictname);
 }
 
 /*
@@ -14329,7 +14323,7 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
+       char       *qtmplname;
 
        /* Skip if not to be dumped */
        if (!tmplinfo->dobj.dump || dopt->dataOnly)
@@ -14337,13 +14331,11 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, tmplinfo->dobj.namespace->dobj.name);
+       qtmplname = pg_strdup(fmtId(tmplinfo->dobj.name));
 
        appendPQExpBuffer(q, "CREATE TEXT SEARCH TEMPLATE %s (\n",
-                                         fmtId(tmplinfo->dobj.name));
+                                         fmtQualifiedDumpable(tmplinfo));
 
        if (tmplinfo->tmplinit != InvalidOid)
                appendPQExpBuffer(q, "    INIT = %s,\n",
@@ -14351,40 +14343,32 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
        appendPQExpBuffer(q, "    LEXIZE = %s );\n",
                                          convertTSFunction(fout, 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));
-
-       appendPQExpBuffer(labelq, "TEXT SEARCH TEMPLATE %s",
-                                         fmtId(tmplinfo->dobj.name));
+       appendPQExpBuffer(delq, "DROP TEXT SEARCH TEMPLATE %s;\n",
+                                         fmtQualifiedDumpable(tmplinfo));
 
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &tmplinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &tmplinfo->dobj,
+                                                                               "TEXT SEARCH TEMPLATE", qtmplname,
+                                                                               tmplinfo->dobj.namespace->dobj.name);
 
        if (tmplinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId,
-                                        tmplinfo->dobj.name,
-                                        tmplinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        "",
-                                        false, "TEXT SEARCH TEMPLATE", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tmplinfo->dobj.name,
+                                                                 .namespace = tmplinfo->dobj.namespace->dobj.name,
+                                                                 .description = "TEXT SEARCH TEMPLATE",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Template Comments */
        if (tmplinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "TEXT SEARCH TEMPLATE", qtmplname,
                                        tmplinfo->dobj.namespace->dobj.name, "",
                                        tmplinfo->dobj.catId, 0, tmplinfo->dobj.dumpId);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
+       free(qtmplname);
 }
 
 /*
@@ -14397,8 +14381,8 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
        PQExpBuffer query;
+       char       *qcfgname;
        PGresult   *res;
        char       *nspname;
        char       *prsname;
@@ -14413,11 +14397,11 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
        query = createPQExpBuffer();
 
+       qcfgname = pg_strdup(fmtId(cfginfo->dobj.name));
+
        /* Fetch name and namespace of the config's parser */
-       selectSourceSchema(fout, "pg_catalog");
        appendPQExpBuffer(query, "SELECT nspname, prsname "
                                          "FROM pg_ts_parser p, pg_namespace n "
                                          "WHERE p.oid = '%u' AND n.oid = prsnamespace",
@@ -14426,15 +14410,10 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
        nspname = PQgetvalue(res, 0, 0);
        prsname = PQgetvalue(res, 0, 1);
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, cfginfo->dobj.namespace->dobj.name);
-
        appendPQExpBuffer(q, "CREATE TEXT SEARCH CONFIGURATION %s (\n",
-                                         fmtId(cfginfo->dobj.name));
+                                         fmtQualifiedDumpable(cfginfo));
 
-       appendPQExpBufferStr(q, "    PARSER = ");
-       if (strcmp(nspname, cfginfo->dobj.namespace->dobj.name) != 0)
-               appendPQExpBuffer(q, "%s.", fmtId(nspname));
+       appendPQExpBuffer(q, "    PARSER = %s.", fmtId(nspname));
        appendPQExpBuffer(q, "%s );\n", fmtId(prsname));
 
        PQclear(res);
@@ -14468,7 +14447,7 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
                        if (i > 0)
                                appendPQExpBufferStr(q, ";\n");
                        appendPQExpBuffer(q, "\nALTER TEXT SEARCH CONFIGURATION %s\n",
-                                                         fmtId(cfginfo->dobj.name));
+                                                         fmtQualifiedDumpable(cfginfo));
                        /* tokenname needs quoting, dictname does NOT */
                        appendPQExpBuffer(q, "    ADD MAPPING FOR %s WITH %s",
                                                          fmtId(tokenname), dictname);
@@ -14482,41 +14461,34 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
 
        PQclear(res);
 
-       /*
-        * DROP must be fully qualified in case same name appears in pg_catalog
-        */
-       appendPQExpBuffer(delq, "DROP TEXT SEARCH CONFIGURATION %s",
-                                         fmtId(cfginfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delq, ".%s;\n",
-                                         fmtId(cfginfo->dobj.name));
-
-       appendPQExpBuffer(labelq, "TEXT SEARCH CONFIGURATION %s",
-                                         fmtId(cfginfo->dobj.name));
+       appendPQExpBuffer(delq, "DROP TEXT SEARCH CONFIGURATION %s;\n",
+                                         fmtQualifiedDumpable(cfginfo));
 
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &cfginfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &cfginfo->dobj,
+                                                                               "TEXT SEARCH CONFIGURATION", qcfgname,
+                                                                               cfginfo->dobj.namespace->dobj.name);
 
        if (cfginfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId,
-                                        cfginfo->dobj.name,
-                                        cfginfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        cfginfo->rolname,
-                                        false, "TEXT SEARCH CONFIGURATION", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = cfginfo->dobj.name,
+                                                                 .namespace = cfginfo->dobj.namespace->dobj.name,
+                                                                 .owner = cfginfo->rolname,
+                                                                 .description = "TEXT SEARCH CONFIGURATION",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Configuration Comments */
        if (cfginfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "TEXT SEARCH CONFIGURATION", qcfgname,
                                        cfginfo->dobj.namespace->dobj.name, cfginfo->rolname,
                                        cfginfo->dobj.catId, 0, cfginfo->dobj.dumpId);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
+       free(qcfgname);
 }
 
 /*
@@ -14529,7 +14501,6 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
        char       *qfdwname;
 
        /* Skip if not to be dumped */
@@ -14538,7 +14509,6 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
 
        qfdwname = pg_strdup(fmtId(fdwinfo->dobj.name));
 
@@ -14559,34 +14529,30 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
        appendPQExpBuffer(delq, "DROP FOREIGN DATA WRAPPER %s;\n",
                                          qfdwname);
 
-       appendPQExpBuffer(labelq, "FOREIGN DATA WRAPPER %s",
-                                         qfdwname);
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &fdwinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &fdwinfo->dobj,
+                                                                               "FOREIGN DATA WRAPPER", qfdwname,
+                                                                               NULL);
 
        if (fdwinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
-                                        fdwinfo->dobj.name,
-                                        NULL,
-                                        NULL,
-                                        fdwinfo->rolname,
-                                        false, "FOREIGN DATA WRAPPER", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = fdwinfo->dobj.name,
+                                                                 .owner = fdwinfo->rolname,
+                                                                 .description = "FOREIGN DATA WRAPPER",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Foreign Data Wrapper Comments */
        if (fdwinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "FOREIGN DATA WRAPPER", qfdwname,
                                        NULL, fdwinfo->rolname,
                                        fdwinfo->dobj.catId, 0, fdwinfo->dobj.dumpId);
 
        /* Handle the ACL */
        if (fdwinfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
-                               "FOREIGN DATA WRAPPER",
-                               qfdwname, NULL, labelq->data,
+                               "FOREIGN DATA WRAPPER", qfdwname, NULL,
                                NULL, fdwinfo->rolname,
                                fdwinfo->fdwacl, fdwinfo->rfdwacl,
                                fdwinfo->initfdwacl, fdwinfo->initrfdwacl);
@@ -14595,7 +14561,6 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -14608,7 +14573,6 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
        PQExpBuffer query;
        PGresult   *res;
        char       *qsrvname;
@@ -14620,13 +14584,11 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
        query = createPQExpBuffer();
 
        qsrvname = pg_strdup(fmtId(srvinfo->dobj.name));
 
        /* look up the foreign-data wrapper */
-       selectSourceSchema(fout, "pg_catalog");
        appendPQExpBuffer(query, "SELECT fdwname "
                                          "FROM pg_foreign_data_wrapper w "
                                          "WHERE w.oid = '%u'",
@@ -14657,33 +14619,29 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
        appendPQExpBuffer(delq, "DROP SERVER %s;\n",
                                          qsrvname);
 
-       appendPQExpBuffer(labelq, "SERVER %s", qsrvname);
-
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &srvinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &srvinfo->dobj,
+                                                                               "SERVER", qsrvname, NULL);
 
        if (srvinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
-                                        srvinfo->dobj.name,
-                                        NULL,
-                                        NULL,
-                                        srvinfo->rolname,
-                                        false, "SERVER", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = srvinfo->dobj.name,
+                                                                 .owner = srvinfo->rolname,
+                                                                 .description = "SERVER",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Foreign Server Comments */
        if (srvinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "SERVER", qsrvname,
                                        NULL, srvinfo->rolname,
                                        srvinfo->dobj.catId, 0, srvinfo->dobj.dumpId);
 
        /* Handle the ACL */
        if (srvinfo->dobj.dump & DUMP_COMPONENT_ACL)
                dumpACL(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
-                               "FOREIGN SERVER",
-                               qsrvname, NULL, labelq->data,
+                               "FOREIGN SERVER", qsrvname, NULL,
                                NULL, srvinfo->rolname,
                                srvinfo->srvacl, srvinfo->rsrvacl,
                                srvinfo->initsrvacl, srvinfo->initrsrvacl);
@@ -14699,7 +14657,6 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
 }
 
@@ -14739,8 +14696,6 @@ dumpUserMappings(Archive *fout,
         * OPTIONS clause.  A possible alternative is to skip such mappings
         * altogether, but it's not clear that that's an improvement.
         */
-       selectSourceSchema(fout, "pg_catalog");
-
        appendPQExpBuffer(query,
                                          "SELECT usename, "
                                          "array_to_string(ARRAY("
@@ -14786,14 +14741,13 @@ dumpUserMappings(Archive *fout,
                                                  usename, servername);
 
                ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                        tag->data,
-                                        namespace,
-                                        NULL,
-                                        owner, false,
-                                        "USER MAPPING", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        &dumpId, 1,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tag->data,
+                                                                 .namespace = namespace,
+                                                                 .owner = owner,
+                                                                 .description = "USER MAPPING",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
        }
 
        PQclear(res);
@@ -14841,9 +14795,8 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
                        break;
                default:
                        /* shouldn't get here */
-                       exit_horribly(NULL,
-                                                 "unrecognized object type in default privileges: %d\n",
-                                                 (int) daclinfo->defaclobjtype);
+                       fatal("unrecognized object type in default privileges: %d",
+                                 (int) daclinfo->defaclobjtype);
                        type = "";                      /* keep compiler quiet */
        }
 
@@ -14860,19 +14813,18 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
                                                                 daclinfo->defaclrole,
                                                                 fout->remoteVersion,
                                                                 q))
-               exit_horribly(NULL, "could not parse default ACL list (%s)\n",
-                                         daclinfo->defaclacl);
+               fatal("could not parse default ACL list (%s)",
+                         daclinfo->defaclacl);
 
        if (daclinfo->dobj.dump & DUMP_COMPONENT_ACL)
                ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId,
-                                        tag->data,
-                                        daclinfo->dobj.namespace ? daclinfo->dobj.namespace->dobj.name : NULL,
-                                        NULL,
-                                        daclinfo->defaclrole,
-                                        false, "DEFAULT ACL", SECTION_POST_DATA,
-                                        q->data, "", NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tag->data,
+                                                                 .namespace = daclinfo->dobj.namespace ?
+                                                                 daclinfo->dobj.namespace->dobj.name : NULL,
+                                                                 .owner = daclinfo->defaclrole,
+                                                                 .description = "DEFAULT ACL",
+                                                                 .section = SECTION_POST_DATA,
+                                                                 .createStmt = q->data));
 
        destroyPQExpBuffer(tag);
        destroyPQExpBuffer(q);
@@ -14888,8 +14840,7 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
  *             FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT.
  * 'name' is the formatted name of the object.  Must be quoted etc. already.
  * 'subname' is the formatted name of the sub-object, if any.  Must be quoted.
- * 'tag' is the tag for the archive entry (should be the same tag as would be
- *             used for comments etc; for example "TABLE foo").
+ *             (Currently we assume that subname is only provided for table columns.)
  * 'nspname' is the namespace the object is in (NULL if none).
  * 'owner' is the owner, NULL if there is no owner (for languages).
  * 'acls' contains the ACL string of the object from the appropriate system
@@ -14911,7 +14862,7 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
 static void
 dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
                const char *type, const char *name, const char *subname,
-               const char *tag, const char *nspname, const char *owner,
+               const char *nspname, const char *owner,
                const char *acls, const char *racls,
                const char *initacls, const char *initracls)
 {
@@ -14938,30 +14889,41 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
         */
        if (strlen(initacls) != 0 || strlen(initracls) != 0)
        {
-               appendPQExpBuffer(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
-               if (!buildACLCommands(name, subname, type, initacls, initracls, owner,
+               appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\n");
+               if (!buildACLCommands(name, subname, nspname, type,
+                                                         initacls, initracls, owner,
                                                          "", fout->remoteVersion, sql))
-                       exit_horribly(NULL,
-                                                 "could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)\n",
-                                                 initacls, initracls, name, type);
-               appendPQExpBuffer(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
+                       fatal("could not parse initial GRANT ACL list (%s) or initial REVOKE ACL list (%s) for object \"%s\" (%s)",
+                                 initacls, initracls, name, type);
+               appendPQExpBufferStr(sql, "SELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\n");
        }
 
-       if (!buildACLCommands(name, subname, type, acls, racls, owner,
+       if (!buildACLCommands(name, subname, nspname, type,
+                                                 acls, racls, owner,
                                                  "", fout->remoteVersion, sql))
-               exit_horribly(NULL,
-                                         "could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)\n",
-                                         acls, racls, name, type);
+               fatal("could not parse GRANT ACL list (%s) or REVOKE ACL list (%s) for object \"%s\" (%s)",
+                         acls, racls, name, type);
 
        if (sql->len > 0)
+       {
+               PQExpBuffer tag = createPQExpBuffer();
+
+               if (subname)
+                       appendPQExpBuffer(tag, "COLUMN %s.%s", name, subname);
+               else
+                       appendPQExpBuffer(tag, "%s %s", type, name);
+
                ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                        tag, nspname,
-                                        NULL,
-                                        owner ? owner : "",
-                                        false, "ACL", SECTION_NONE,
-                                        sql->data, "", NULL,
-                                        &(objDumpId), 1,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tag->data,
+                                                                 .namespace = nspname,
+                                                                 .owner = owner,
+                                                                 .description = "ACL",
+                                                                 .section = SECTION_NONE,
+                                                                 .createStmt = sql->data,
+                                                                 .deps = &objDumpId,
+                                                                 .nDeps = 1));
+               destroyPQExpBuffer(tag);
+       }
 
        destroyPQExpBuffer(sql);
 }
@@ -14970,8 +14932,8 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
  * dumpSecLabel
  *
  * This routine is used to dump any security labels associated with the
- * object handed to this routine. The routine takes a constant character
- * string for the target part of the security-label command, plus
+ * object handed to this routine. The routine takes the object type
+ * and object name (ready to print, except for schema decoration), plus
  * the namespace and owner of the object (for labeling the ArchiveEntry),
  * plus catalog ID and subid which are the lookup key for pg_seclabel,
  * plus the dump ID for the object (for setting a dependency).
@@ -14985,7 +14947,7 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
  * calling ArchiveEntry() for the specified object.
  */
 static void
-dumpSecLabel(Archive *fout, const char *target,
+dumpSecLabel(Archive *fout, const char *type, const char *name,
                         const char *namespace, const char *owner,
                         CatalogId catalogId, int subid, DumpId dumpId)
 {
@@ -15000,7 +14962,7 @@ dumpSecLabel(Archive *fout, const char *target,
                return;
 
        /* Security labels are schema not data ... except blob labels are data */
-       if (strncmp(target, "LARGE OBJECT ", 13) != 0)
+       if (strcmp(type, "LARGE OBJECT") != 0)
        {
                if (dopt->dataOnly)
                        return;
@@ -15026,21 +14988,32 @@ dumpSecLabel(Archive *fout, const char *target,
                        continue;
 
                appendPQExpBuffer(query,
-                                                 "SECURITY LABEL FOR %s ON %s IS ",
-                                                 fmtId(labels[i].provider), target);
+                                                 "SECURITY LABEL FOR %s ON %s ",
+                                                 fmtId(labels[i].provider), type);
+               if (namespace && *namespace)
+                       appendPQExpBuffer(query, "%s.", fmtId(namespace));
+               appendPQExpBuffer(query, "%s IS ", name);
                appendStringLiteralAH(query, labels[i].label, fout);
                appendPQExpBufferStr(query, ";\n");
        }
 
        if (query->len > 0)
        {
+               PQExpBuffer tag = createPQExpBuffer();
+
+               appendPQExpBuffer(tag, "%s %s", type, name);
                ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                        target, namespace, NULL, owner,
-                                        false, "SECURITY LABEL", SECTION_NONE,
-                                        query->data, "", NULL,
-                                        &(dumpId), 1,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tag->data,
+                                                                 .namespace = namespace,
+                                                                 .owner = owner,
+                                                                 .description = "SECURITY LABEL",
+                                                                 .section = SECTION_NONE,
+                                                                 .createStmt = query->data,
+                                                                 .deps = &dumpId,
+                                                                 .nDeps = 1));
+               destroyPQExpBuffer(tag);
        }
+
        destroyPQExpBuffer(query);
 }
 
@@ -15092,13 +15065,14 @@ dumpTableSecLabel(Archive *fout, TableInfo *tbinfo, const char *reltypename)
                if (objsubid == 0)
                {
                        appendPQExpBuffer(target, "%s %s", reltypename,
-                                                         fmtId(tbinfo->dobj.name));
+                                                         fmtQualifiedDumpable(tbinfo));
                }
                else
                {
                        colname = getAttrName(objsubid, tbinfo);
-                       /* first fmtId result must be consumed before calling it again */
-                       appendPQExpBuffer(target, "COLUMN %s", fmtId(tbinfo->dobj.name));
+                       /* first fmtXXX result must be consumed before calling again */
+                       appendPQExpBuffer(target, "COLUMN %s",
+                                                         fmtQualifiedDumpable(tbinfo));
                        appendPQExpBuffer(target, ".%s", fmtId(colname));
                }
                appendPQExpBuffer(query, "SECURITY LABEL FOR %s ON %s IS ",
@@ -15112,13 +15086,14 @@ dumpTableSecLabel(Archive *fout, TableInfo *tbinfo, const char *reltypename)
                appendPQExpBuffer(target, "%s %s", reltypename,
                                                  fmtId(tbinfo->dobj.name));
                ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                        target->data,
-                                        tbinfo->dobj.namespace->dobj.name,
-                                        NULL, tbinfo->rolname,
-                                        false, "SECURITY LABEL", SECTION_NONE,
-                                        query->data, "", NULL,
-                                        &(tbinfo->dobj.dumpId), 1,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = target->data,
+                                                                 .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tbinfo->rolname,
+                                                                 .description = "SECURITY LABEL",
+                                                                 .section = SECTION_NONE,
+                                                                 .createStmt = query->data,
+                                                                 .deps = &(tbinfo->dobj.dumpId),
+                                                                 .nDeps = 1));
        }
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(target);
@@ -15296,14 +15271,12 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
        {
                const char *objtype =
                (tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" : "TABLE";
-               char       *acltag = psprintf("%s %s", objtype, namecopy);
 
                dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
-                               objtype, namecopy, NULL, acltag,
+                               objtype, namecopy, NULL,
                                tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                                tbinfo->relacl, tbinfo->rrelacl,
                                tbinfo->initrelacl, tbinfo->initrrelacl);
-               free(acltag);
        }
 
        /*
@@ -15385,17 +15358,14 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
                        char       *initattacl = PQgetvalue(res, i, 3);
                        char       *initrattacl = PQgetvalue(res, i, 4);
                        char       *attnamecopy;
-                       char       *acltag;
 
                        attnamecopy = pg_strdup(fmtId(attname));
-                       acltag = psprintf("COLUMN %s.%s", namecopy, attnamecopy);
                        /* Column's GRANT type is always TABLE */
-                       dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE",
-                                       namecopy, attnamecopy, acltag,
+                       dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
+                                       "TABLE", namecopy, attnamecopy,
                                        tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                                        attacl, rattacl, initattacl, initrattacl);
                        free(attnamecopy);
-                       free(acltag);
                }
                PQclear(res);
                destroyPQExpBuffer(query);
@@ -15430,18 +15400,18 @@ createViewAsClause(Archive *fout, TableInfo *tbinfo)
        if (PQntuples(res) != 1)
        {
                if (PQntuples(res) < 1)
-                       exit_horribly(NULL, "query to obtain definition of view \"%s\" returned no data\n",
-                                                 tbinfo->dobj.name);
+                       fatal("query to obtain definition of view \"%s\" returned no data",
+                                 tbinfo->dobj.name);
                else
-                       exit_horribly(NULL, "query to obtain definition of view \"%s\" returned more than one definition\n",
-                                                 tbinfo->dobj.name);
+                       fatal("query to obtain definition of view \"%s\" returned more than one definition",
+                                 tbinfo->dobj.name);
        }
 
        len = PQgetlength(res, 0, 0);
 
        if (len == 0)
-               exit_horribly(NULL, "definition of view \"%s\" appears to be empty (length zero)\n",
-                                         tbinfo->dobj.name);
+               fatal("definition of view \"%s\" appears to be empty (length zero)",
+                         tbinfo->dobj.name);
 
        /* Strip off the trailing semicolon so that other things may follow. */
        Assert(PQgetvalue(res, 0, 0)[len - 1] == ';');
@@ -15487,12 +15457,8 @@ createDummyViewAsClause(Archive *fout, TableInfo *tbinfo)
 
                        coll = findCollationByOid(tbinfo->attcollation[j]);
                        if (coll)
-                       {
-                               /* always schema-qualify, don't try to be smart */
-                               appendPQExpBuffer(result, " COLLATE %s.",
-                                                                 fmtId(coll->dobj.namespace->dobj.name));
-                               appendPQExpBufferStr(result, fmtId(coll->dobj.name));
-                       }
+                               appendPQExpBuffer(result, " COLLATE %s",
+                                                                 fmtQualifiedDumpable(coll));
                }
 
                appendPQExpBuffer(result, " AS %s", fmtId(tbinfo->attnames[j]));
@@ -15511,19 +15477,23 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
-       PQExpBuffer labelq = createPQExpBuffer();
+       char       *qrelname;
+       char       *qualrelname;
        int                     numParents;
        TableInfo **parents;
        int                     actual_atts;    /* number of attrs in this CREATE statement */
        const char *reltypename;
        char       *storage;
-       char       *srvname;
-       char       *ftoptions;
        int                     j,
                                k;
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
+       qrelname = pg_strdup(fmtId(tbinfo->dobj.name));
+       qualrelname = pg_strdup(fmtQualifiedDumpable(tbinfo));
+
+
+       if (tbinfo->hasoids)
+               pg_log_warning("WITH OIDS is not supported anymore (table \"%s\")",
+                                          qrelname);
 
        if (dopt->binary_upgrade)
                binary_upgrade_set_type_oids_by_rel_oid(fout, q,
@@ -15540,20 +15510,14 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 
                reltypename = "VIEW";
 
-               /*
-                * DROP must be fully qualified in case same name appears in
-                * pg_catalog
-                */
-               appendPQExpBuffer(delq, "DROP VIEW %s.",
-                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
-               appendPQExpBuffer(delq, "%s;\n",
-                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(delq, "DROP VIEW %s;\n", qualrelname);
 
                if (dopt->binary_upgrade)
                        binary_upgrade_set_pg_class_oids(fout, q,
                                                                                         tbinfo->dobj.catId.oid, false);
 
-               appendPQExpBuffer(q, "CREATE VIEW %s", fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(q, "CREATE VIEW %s", qualrelname);
+
                if (tbinfo->dummy_view)
                        result = createDummyViewAsClause(fout, tbinfo);
                else
@@ -15572,12 +15536,12 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                if (tbinfo->checkoption != NULL && !tbinfo->dummy_view)
                        appendPQExpBuffer(q, "\n  WITH %s CHECK OPTION", tbinfo->checkoption);
                appendPQExpBufferStr(q, ";\n");
-
-               appendPQExpBuffer(labelq, "VIEW %s",
-                                                 fmtId(tbinfo->dobj.name));
        }
        else
        {
+               char       *ftoptions = NULL;
+               char       *srvname = NULL;
+
                switch (tbinfo->relkind)
                {
                        case RELKIND_FOREIGN_TABLE:
@@ -15614,29 +15578,15 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                }
                        case RELKIND_MATVIEW:
                                reltypename = "MATERIALIZED VIEW";
-                               srvname = NULL;
-                               ftoptions = NULL;
                                break;
                        default:
                                reltypename = "TABLE";
-                               srvname = NULL;
-                               ftoptions = NULL;
                }
 
                numParents = tbinfo->numParents;
                parents = tbinfo->parents;
 
-               /*
-                * DROP must be fully qualified in case same name appears in
-                * pg_catalog
-                */
-               appendPQExpBuffer(delq, "DROP %s %s.", reltypename,
-                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
-               appendPQExpBuffer(delq, "%s;\n",
-                                                 fmtId(tbinfo->dobj.name));
-
-               appendPQExpBuffer(labelq, "%s %s", reltypename,
-                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(delq, "DROP %s %s;\n", reltypename, qualrelname);
 
                if (dopt->binary_upgrade)
                        binary_upgrade_set_pg_class_oids(fout, q,
@@ -15646,7 +15596,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                                  tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED ?
                                                  "UNLOGGED " : "",
                                                  reltypename,
-                                                 fmtId(tbinfo->dobj.name));
+                                                 qualrelname);
 
                /*
                 * Attach to type, if reloftype; except in case of a binary upgrade,
@@ -15655,30 +15605,6 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                if (tbinfo->reloftype && !dopt->binary_upgrade)
                        appendPQExpBuffer(q, " OF %s", tbinfo->reloftype);
 
-               /*
-                * If the table is a partition, dump it as such; except in the case of
-                * a binary upgrade, we dump the table normally and attach it to the
-                * parent afterward.
-                */
-               if (tbinfo->ispartition && !dopt->binary_upgrade)
-               {
-                       TableInfo  *parentRel = tbinfo->parents[0];
-
-                       /*
-                        * With partitions, unlike inheritance, there can only be one
-                        * parent.
-                        */
-                       if (tbinfo->numParents != 1)
-                               exit_horribly(NULL, "invalid number of parents %d for table \"%s\"\n",
-                                                         tbinfo->numParents, tbinfo->dobj.name);
-
-                       appendPQExpBuffer(q, " PARTITION OF ");
-                       if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
-                               appendPQExpBuffer(q, "%s.",
-                                                                 fmtId(parentRel->dobj.namespace->dobj.name));
-                       appendPQExpBufferStr(q, fmtId(parentRel->dobj.name));
-               }
-
                if (tbinfo->relkind != RELKIND_MATVIEW)
                {
                        /* Dump the attributes */
@@ -15693,26 +15619,30 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                 */
                                if (shouldPrintColumn(dopt, tbinfo, j))
                                {
+                                       bool            print_default;
+                                       bool            print_notnull;
+
                                        /*
                                         * Default value --- suppress if to be printed separately.
                                         */
-                                       bool            has_default = (tbinfo->attrdefs[j] != NULL &&
-                                                                                          !tbinfo->attrdefs[j]->separate);
+                                       print_default = (tbinfo->attrdefs[j] != NULL &&
+                                                                        !tbinfo->attrdefs[j]->separate);
 
                                        /*
                                         * Not Null constraint --- suppress if inherited, except
-                                        * in binary-upgrade case where that won't work.
+                                        * if partition, or in binary-upgrade case where that
+                                        * won't work.
                                         */
-                                       bool            has_notnull = (tbinfo->notnull[j] &&
-                                                                                          (!tbinfo->inhNotNull[j] ||
-                                                                                               dopt->binary_upgrade));
+                                       print_notnull = (tbinfo->notnull[j] &&
+                                                                        (!tbinfo->inhNotNull[j] ||
+                                                                         tbinfo->ispartition || dopt->binary_upgrade));
 
                                        /*
-                                        * Skip column if fully defined by reloftype or the
-                                        * partition parent.
+                                        * Skip column if fully defined by reloftype, except in
+                                        * binary upgrade
                                         */
-                                       if ((tbinfo->reloftype || tbinfo->ispartition) &&
-                                               !has_default && !has_notnull && !dopt->binary_upgrade)
+                                       if (tbinfo->reloftype && !print_default && !print_notnull &&
+                                               !dopt->binary_upgrade)
                                                continue;
 
                                        /* Format properly if not first attr */
@@ -15735,25 +15665,35 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                                 * clean things up later.
                                                 */
                                                appendPQExpBufferStr(q, " INTEGER /* dummy */");
-                                               /* Skip all the rest, too */
+                                               /* and skip to the next column */
                                                continue;
                                        }
 
                                        /*
-                                        * Attribute type
-                                        *
-                                        * In binary-upgrade mode, we always include the type. If
-                                        * we aren't in binary-upgrade mode, then we skip the type
-                                        * when creating a typed table ('OF type_name') or a
-                                        * partition ('PARTITION OF'), since the type comes from
-                                        * the parent/partitioned table.
+                                        * Attribute type; print it except when creating a typed
+                                        * table ('OF type_name'), but in binary-upgrade mode,
+                                        * print it in that case too.
                                         */
-                                       if (dopt->binary_upgrade || (!tbinfo->reloftype && !tbinfo->ispartition))
+                                       if (dopt->binary_upgrade || !tbinfo->reloftype)
                                        {
                                                appendPQExpBuffer(q, " %s",
                                                                                  tbinfo->atttypnames[j]);
                                        }
 
+                                       if (print_default)
+                                       {
+                                               if (tbinfo->attgenerated[j] == ATTRIBUTE_GENERATED_STORED)
+                                                       appendPQExpBuffer(q, " GENERATED ALWAYS AS (%s) STORED",
+                                                                                         tbinfo->attrdefs[j]->adef_expr);
+                                               else
+                                                       appendPQExpBuffer(q, " DEFAULT %s",
+                                                                                         tbinfo->attrdefs[j]->adef_expr);
+                                       }
+
+
+                                       if (print_notnull)
+                                               appendPQExpBufferStr(q, " NOT NULL");
+
                                        /* Add collation if not default for the type */
                                        if (OidIsValid(tbinfo->attcollation[j]))
                                        {
@@ -15761,31 +15701,26 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 
                                                coll = findCollationByOid(tbinfo->attcollation[j]);
                                                if (coll)
-                                               {
-                                                       /* always schema-qualify, don't try to be smart */
-                                                       appendPQExpBuffer(q, " COLLATE %s.",
-                                                                                         fmtId(coll->dobj.namespace->dobj.name));
-                                                       appendPQExpBufferStr(q, fmtId(coll->dobj.name));
-                                               }
+                                                       appendPQExpBuffer(q, " COLLATE %s",
+                                                                                         fmtQualifiedDumpable(coll));
                                        }
-
-                                       if (has_default)
-                                               appendPQExpBuffer(q, " DEFAULT %s",
-                                                                                 tbinfo->attrdefs[j]->adef_expr);
-
-                                       if (has_notnull)
-                                               appendPQExpBufferStr(q, " NOT NULL");
                                }
                        }
 
                        /*
                         * Add non-inherited CHECK constraints, if any.
+                        *
+                        * For partitions, we need to include check constraints even if
+                        * they're not defined locally, because the ALTER TABLE ATTACH
+                        * PARTITION that we'll emit later expects the constraint to be
+                        * there.  (No need to fix conislocal: ATTACH PARTITION does that)
                         */
                        for (j = 0; j < tbinfo->ncheck; j++)
                        {
                                ConstraintInfo *constr = &(tbinfo->checkexprs[j]);
 
-                               if (constr->separate || !constr->conislocal)
+                               if (constr->separate ||
+                                       (!constr->conislocal && !tbinfo->ispartition))
                                        continue;
 
                                if (actual_atts == 0)
@@ -15802,25 +15737,20 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 
                        if (actual_atts)
                                appendPQExpBufferStr(q, "\n)");
-                       else if (!((tbinfo->reloftype || tbinfo->ispartition) &&
-                                          !dopt->binary_upgrade))
+                       else if (!(tbinfo->reloftype && !dopt->binary_upgrade))
                        {
                                /*
-                                * We must have a parenthesized attribute list, even though
-                                * empty, when not using the OF TYPE or PARTITION OF syntax.
+                                * No attributes? we must have a parenthesized attribute list,
+                                * even though empty, when not using the OF TYPE syntax.
                                 */
                                appendPQExpBufferStr(q, " (\n)");
                        }
 
-                       if (tbinfo->ispartition && !dopt->binary_upgrade)
-                       {
-                               appendPQExpBufferChar(q, '\n');
-                               appendPQExpBufferStr(q, tbinfo->partbound);
-                       }
-
-                       /* Emit the INHERITS clause, except if this is a partition. */
-                       if (numParents > 0 &&
-                               !tbinfo->ispartition &&
+                       /*
+                        * Emit the INHERITS clause (not for partitions), except in
+                        * binary-upgrade mode.
+                        */
+                       if (numParents > 0 && !tbinfo->ispartition &&
                                !dopt->binary_upgrade)
                        {
                                appendPQExpBufferStr(q, "\nINHERITS (");
@@ -15830,10 +15760,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 
                                        if (k > 0)
                                                appendPQExpBufferStr(q, ", ");
-                                       if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
-                                               appendPQExpBuffer(q, "%s.",
-                                                                                 fmtId(parentRel->dobj.namespace->dobj.name));
-                                       appendPQExpBufferStr(q, fmtId(parentRel->dobj.name));
+                                       appendPQExpBufferStr(q, fmtQualifiedDumpable(parentRel));
                                }
                                appendPQExpBufferChar(q, ')');
                        }
@@ -15886,6 +15813,29 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                else
                        appendPQExpBufferStr(q, ";\n");
 
+               /*
+                * in binary upgrade mode, update the catalog with any missing values
+                * that might be present.
+                */
+               if (dopt->binary_upgrade)
+               {
+                       for (j = 0; j < tbinfo->numatts; j++)
+                       {
+                               if (tbinfo->attmissingval[j][0] != '\0')
+                               {
+                                       appendPQExpBufferStr(q, "\n-- set missing value.\n");
+                                       appendPQExpBufferStr(q,
+                                                                                "SELECT pg_catalog.binary_upgrade_set_missing_value(");
+                                       appendStringLiteralAH(q, qualrelname, fout);
+                                       appendPQExpBufferStr(q, "::pg_catalog.regclass,");
+                                       appendStringLiteralAH(q, tbinfo->attnames[j], fout);
+                                       appendPQExpBufferStr(q, ",");
+                                       appendStringLiteralAH(q, tbinfo->attmissingval[j], fout);
+                                       appendPQExpBufferStr(q, ");\n\n");
+                               }
+                       }
+               }
+
                /*
                 * To create binary-compatible heap files, we have to ensure the same
                 * physical column order, including dropped columns, as in the
@@ -15898,6 +15848,14 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                 * column order.  That also means we have to take care about setting
                 * attislocal correctly, plus fix up any inherited CHECK constraints.
                 * Analogously, we set up typed tables using ALTER TABLE / OF here.
+                *
+                * We process foreign and partitioned tables here, even though they
+                * lack heap storage, because they can participate in inheritance
+                * relationships and we want this stuff to be consistent across the
+                * inheritance tree.  We can exclude indexes, toast tables, sequences
+                * and matviews, even though they have storage, because we don't
+                * support altering or dropping columns in them, nor can they be part
+                * of inheritance trees.
                 */
                if (dopt->binary_upgrade &&
                        (tbinfo->relkind == RELKIND_RELATION ||
@@ -15917,16 +15875,16 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                                                          tbinfo->attalign[j]);
                                        appendStringLiteralAH(q, tbinfo->attnames[j], fout);
                                        appendPQExpBufferStr(q, "\n  AND attrelid = ");
-                                       appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
+                                       appendStringLiteralAH(q, qualrelname, fout);
                                        appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
 
                                        if (tbinfo->relkind == RELKIND_RELATION ||
                                                tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
                                                appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
-                                                                                 fmtId(tbinfo->dobj.name));
+                                                                                 qualrelname);
                                        else
                                                appendPQExpBuffer(q, "ALTER FOREIGN TABLE ONLY %s ",
-                                                                                 fmtId(tbinfo->dobj.name));
+                                                                                 qualrelname);
                                        appendPQExpBuffer(q, "DROP COLUMN %s;\n",
                                                                          fmtId(tbinfo->attnames[j]));
                                }
@@ -15938,21 +15896,27 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                                                                 "WHERE attname = ");
                                        appendStringLiteralAH(q, tbinfo->attnames[j], fout);
                                        appendPQExpBufferStr(q, "\n  AND attrelid = ");
-                                       appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
+                                       appendStringLiteralAH(q, qualrelname, fout);
                                        appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
                                }
                        }
 
+                       /*
+                        * Add inherited CHECK constraints, if any.
+                        *
+                        * For partitions, they were already dumped, and conislocal
+                        * doesn't need fixing.
+                        */
                        for (k = 0; k < tbinfo->ncheck; k++)
                        {
                                ConstraintInfo *constr = &(tbinfo->checkexprs[k]);
 
-                               if (constr->separate || constr->conislocal)
+                               if (constr->separate || constr->conislocal || tbinfo->ispartition)
                                        continue;
 
                                appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inherited constraint.\n");
                                appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
-                                                                 fmtId(tbinfo->dobj.name));
+                                                                 qualrelname);
                                appendPQExpBuffer(q, " ADD CONSTRAINT %s ",
                                                                  fmtId(constr->dobj.name));
                                appendPQExpBuffer(q, "%s;\n", constr->condef);
@@ -15961,44 +15925,20 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                                                         "WHERE contype = 'c' AND conname = ");
                                appendStringLiteralAH(q, constr->dobj.name, fout);
                                appendPQExpBufferStr(q, "\n  AND conrelid = ");
-                               appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
+                               appendStringLiteralAH(q, qualrelname, fout);
                                appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
                        }
 
-                       if (numParents > 0)
+                       if (numParents > 0 && !tbinfo->ispartition)
                        {
-                               appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inheritance and partitioning this way.\n");
+                               appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inheritance this way.\n");
                                for (k = 0; k < numParents; k++)
                                {
                                        TableInfo  *parentRel = parents[k];
-                                       PQExpBuffer parentname = createPQExpBuffer();
-
-                                       /* Schema-qualify the parent table, if necessary */
-                                       if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
-                                               appendPQExpBuffer(parentname, "%s.",
-                                                                                 fmtId(parentRel->dobj.namespace->dobj.name));
-
-                                       appendPQExpBuffer(parentname, "%s",
-                                                                         fmtId(parentRel->dobj.name));
 
-                                       /* In the partitioning case, we alter the parent */
-                                       if (tbinfo->ispartition)
-                                               appendPQExpBuffer(q,
-                                                                                 "ALTER TABLE ONLY %s ATTACH PARTITION ",
-                                                                                 parentname->data);
-                                       else
-                                               appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT ",
-                                                                                 fmtId(tbinfo->dobj.name));
-
-                                       /* Partition needs specifying the bounds */
-                                       if (tbinfo->ispartition)
-                                               appendPQExpBuffer(q, "%s %s;\n",
-                                                                                 fmtId(tbinfo->dobj.name),
-                                                                                 tbinfo->partbound);
-                                       else
-                                               appendPQExpBuffer(q, "%s;\n", parentname->data);
-
-                                       destroyPQExpBuffer(parentname);
+                                       appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT %s;\n",
+                                                                         qualrelname,
+                                                                         fmtQualifiedDumpable(parentRel));
                                }
                        }
 
@@ -16006,21 +15946,57 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                        {
                                appendPQExpBufferStr(q, "\n-- For binary upgrade, set up typed tables this way.\n");
                                appendPQExpBuffer(q, "ALTER TABLE ONLY %s OF %s;\n",
-                                                                 fmtId(tbinfo->dobj.name),
+                                                                 qualrelname,
                                                                  tbinfo->reloftype);
                        }
+               }
 
+               /*
+                * For partitioned tables, emit the ATTACH PARTITION clause.  Note
+                * that we always want to create partitions this way instead of using
+                * CREATE TABLE .. PARTITION OF, mainly to preserve a possible column
+                * layout discrepancy with the parent, but also to ensure it gets the
+                * correct tablespace setting if it differs from the parent's.
+                */
+               if (tbinfo->ispartition)
+               {
+                       /* With partitions there can only be one parent */
+                       if (tbinfo->numParents != 1)
+                               fatal("invalid number of parents %d for table \"%s\"",
+                                         tbinfo->numParents, tbinfo->dobj.name);
+
+                       /* Perform ALTER TABLE on the parent */
+                       appendPQExpBuffer(q,
+                                                         "ALTER TABLE ONLY %s ATTACH PARTITION %s %s;\n",
+                                                         fmtQualifiedDumpable(parents[0]),
+                                                         qualrelname, tbinfo->partbound);
+               }
+
+               /*
+                * In binary_upgrade mode, arrange to restore the old relfrozenxid and
+                * relminmxid of all vacuumable relations.  (While vacuum.c processes
+                * TOAST tables semi-independently, here we see them only as children
+                * of other relations; so this "if" lacks RELKIND_TOASTVALUE, and the
+                * child toast table is handled below.)
+                */
+               if (dopt->binary_upgrade &&
+                       (tbinfo->relkind == RELKIND_RELATION ||
+                        tbinfo->relkind == RELKIND_MATVIEW))
+               {
                        appendPQExpBufferStr(q, "\n-- For binary upgrade, set heap's relfrozenxid and relminmxid\n");
                        appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
                                                          "SET relfrozenxid = '%u', relminmxid = '%u'\n"
                                                          "WHERE oid = ",
                                                          tbinfo->frozenxid, tbinfo->minmxid);
-                       appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
+                       appendStringLiteralAH(q, qualrelname, fout);
                        appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
 
                        if (tbinfo->toast_oid)
                        {
-                               /* We preserve the toast oids, so we can use it during restore */
+                               /*
+                                * The toast table will have the same OID at restore, so we
+                                * can safely target it by OID.
+                                */
                                appendPQExpBufferStr(q, "\n-- For binary upgrade, set toast's relfrozenxid and relminmxid\n");
                                appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
                                                                  "SET relfrozenxid = '%u', relminmxid = '%u'\n"
@@ -16034,7 +16010,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                 * In binary_upgrade mode, restore matviews' populated status by
                 * poking pg_class directly.  This is pretty ugly, but we can't use
                 * REFRESH MATERIALIZED VIEW since it's possible that some underlying
-                * matview is not populated even though this matview is.
+                * matview is not populated even though this matview is; in any case,
+                * we want to transfer the matview's heap storage, not run REFRESH.
                 */
                if (dopt->binary_upgrade && tbinfo->relkind == RELKIND_MATVIEW &&
                        tbinfo->relispopulated)
@@ -16043,7 +16020,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                        appendPQExpBufferStr(q, "UPDATE pg_catalog.pg_class\n"
                                                                 "SET relispopulated = 't'\n"
                                                                 "WHERE oid = ");
-                       appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
+                       appendStringLiteralAH(q, qualrelname, fout);
                        appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
                }
 
@@ -16066,7 +16043,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                tbinfo->notnull[j] && !tbinfo->inhNotNull[j])
                        {
                                appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
-                                                                 fmtId(tbinfo->dobj.name));
+                                                                 qualrelname);
                                appendPQExpBuffer(q, "ALTER COLUMN %s SET NOT NULL;\n",
                                                                  fmtId(tbinfo->attnames[j]));
                        }
@@ -16079,7 +16056,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                        if (tbinfo->attstattarget[j] >= 0)
                        {
                                appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
-                                                                 fmtId(tbinfo->dobj.name));
+                                                                 qualrelname);
                                appendPQExpBuffer(q, "ALTER COLUMN %s ",
                                                                  fmtId(tbinfo->attnames[j]));
                                appendPQExpBuffer(q, "SET STATISTICS %d;\n",
@@ -16116,7 +16093,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                                if (storage != NULL)
                                {
                                        appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
-                                                                         fmtId(tbinfo->dobj.name));
+                                                                         qualrelname);
                                        appendPQExpBuffer(q, "ALTER COLUMN %s ",
                                                                          fmtId(tbinfo->attnames[j]));
                                        appendPQExpBuffer(q, "SET STORAGE %s;\n",
@@ -16127,10 +16104,10 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                        /*
                         * Dump per-column attributes.
                         */
-                       if (tbinfo->attoptions[j] && tbinfo->attoptions[j][0] != '\0')
+                       if (tbinfo->attoptions[j][0] != '\0')
                        {
                                appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
-                                                                 fmtId(tbinfo->dobj.name));
+                                                                 qualrelname);
                                appendPQExpBuffer(q, "ALTER COLUMN %s ",
                                                                  fmtId(tbinfo->attnames[j]));
                                appendPQExpBuffer(q, "SET (%s);\n",
@@ -16141,17 +16118,21 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                         * Dump per-column fdw options.
                         */
                        if (tbinfo->relkind == RELKIND_FOREIGN_TABLE &&
-                               tbinfo->attfdwoptions[j] &&
                                tbinfo->attfdwoptions[j][0] != '\0')
                        {
                                appendPQExpBuffer(q, "ALTER FOREIGN TABLE %s ",
-                                                                 fmtId(tbinfo->dobj.name));
+                                                                 qualrelname);
                                appendPQExpBuffer(q, "ALTER COLUMN %s ",
                                                                  fmtId(tbinfo->attnames[j]));
                                appendPQExpBuffer(q, "OPTIONS (\n    %s\n);\n",
                                                                  tbinfo->attfdwoptions[j]);
                        }
                }
+
+               if (ftoptions)
+                       free(ftoptions);
+               if (srvname)
+                       free(srvname);
        }
 
        /*
@@ -16169,40 +16150,45 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                else if (tbinfo->relreplident == REPLICA_IDENTITY_NOTHING)
                {
                        appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY NOTHING;\n",
-                                                         fmtId(tbinfo->dobj.name));
+                                                         qualrelname);
                }
                else if (tbinfo->relreplident == REPLICA_IDENTITY_FULL)
                {
                        appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY FULL;\n",
-                                                         fmtId(tbinfo->dobj.name));
+                                                         qualrelname);
                }
        }
 
-       if (tbinfo->relkind == RELKIND_FOREIGN_TABLE && tbinfo->hasoids)
-               appendPQExpBuffer(q, "\nALTER TABLE ONLY %s SET WITH OIDS;\n",
-                                                 fmtId(tbinfo->dobj.name));
-
        if (tbinfo->forcerowsec)
                appendPQExpBuffer(q, "\nALTER TABLE ONLY %s FORCE ROW LEVEL SECURITY;\n",
-                                                 fmtId(tbinfo->dobj.name));
+                                                 qualrelname);
 
        if (dopt->binary_upgrade)
-               binary_upgrade_extension_member(q, &tbinfo->dobj, labelq->data);
+               binary_upgrade_extension_member(q, &tbinfo->dobj,
+                                                                               reltypename, qrelname,
+                                                                               tbinfo->dobj.namespace->dobj.name);
 
        if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
-               ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
-                                        tbinfo->dobj.name,
-                                        tbinfo->dobj.namespace->dobj.name,
-                                        (tbinfo->relkind == RELKIND_VIEW) ? NULL : tbinfo->reltablespace,
-                                        tbinfo->rolname,
-                                        (strcmp(reltypename, "TABLE") == 0) ? tbinfo->hasoids : false,
-                                        reltypename,
-                                        tbinfo->postponed_def ?
-                                        SECTION_POST_DATA : SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+       {
+               char       *tableam = NULL;
 
+               if (tbinfo->relkind == RELKIND_RELATION ||
+                       tbinfo->relkind == RELKIND_MATVIEW)
+                       tableam = tbinfo->amname;
+
+               ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
+                                        ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+                                                                 .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                 .tablespace = (tbinfo->relkind == RELKIND_VIEW) ?
+                                                                 NULL : tbinfo->reltablespace,
+                                                                 .tableam = tableam,
+                                                                 .owner = tbinfo->rolname,
+                                                                 .description = reltypename,
+                                                                 .section = tbinfo->postponed_def ?
+                                                                 SECTION_POST_DATA : SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
+       }
 
        /* Dump Table Comments */
        if (tbinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -16226,7 +16212,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
+       free(qrelname);
+       free(qualrelname);
 }
 
 /*
@@ -16240,6 +16227,7 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
        int                     adnum = adinfo->adnum;
        PQExpBuffer q;
        PQExpBuffer delq;
+       char       *qualrelname;
        char       *tag;
 
        /* Skip if table definition not to be dumped */
@@ -16253,19 +16241,16 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
 
+       qualrelname = pg_strdup(fmtQualifiedDumpable(tbinfo));
+
        appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
-                                         fmtId(tbinfo->dobj.name));
+                                         qualrelname);
        appendPQExpBuffer(q, "ALTER COLUMN %s SET DEFAULT %s;\n",
                                          fmtId(tbinfo->attnames[adnum - 1]),
                                          adinfo->adef_expr);
 
-       /*
-        * DROP must be fully qualified in case same name appears in pg_catalog
-        */
-       appendPQExpBuffer(delq, "ALTER TABLE %s.",
-                                         fmtId(tbinfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delq, "%s ",
-                                         fmtId(tbinfo->dobj.name));
+       appendPQExpBuffer(delq, "ALTER TABLE %s ",
+                                         qualrelname);
        appendPQExpBuffer(delq, "ALTER COLUMN %s DROP DEFAULT;\n",
                                          fmtId(tbinfo->attnames[adnum - 1]));
 
@@ -16273,18 +16258,18 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
 
        if (adinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, adinfo->dobj.catId, adinfo->dobj.dumpId,
-                                        tag,
-                                        tbinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        tbinfo->rolname,
-                                        false, "DEFAULT", SECTION_PRE_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tag,
+                                                                 .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tbinfo->rolname,
+                                                                 .description = "DEFAULT",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        free(tag);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       free(qualrelname);
 }
 
 /*
@@ -16303,8 +16288,6 @@ getAttrName(int attrnum, TableInfo *tblInfo)
        {
                case SelfItemPointerAttributeNumber:
                        return "ctid";
-               case ObjectIdAttributeNumber:
-                       return "oid";
                case MinTransactionIdAttributeNumber:
                        return "xmin";
                case MinCommandIdAttributeNumber:
@@ -16316,8 +16299,8 @@ getAttrName(int attrnum, TableInfo *tblInfo)
                case TableOidAttributeNumber:
                        return "tableoid";
        }
-       exit_horribly(NULL, "invalid column number %d for table \"%s\"\n",
-                                 attrnum, tblInfo->dobj.name);
+       fatal("invalid column number %d for table \"%s\"",
+                 attrnum, tblInfo->dobj.name);
        return NULL;                            /* keep compiler quiet */
 }
 
@@ -16333,17 +16316,15 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
        bool            is_constraint = (indxinfo->indexconstraint != 0);
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
+       char       *qindxname;
 
        if (dopt->dataOnly)
                return;
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
 
-       appendPQExpBuffer(labelq, "INDEX %s",
-                                         fmtId(indxinfo->dobj.name));
+       qindxname = pg_strdup(fmtId(indxinfo->dobj.name));
 
        /*
         * If there's an associated constraint, don't dump the index per se, but
@@ -16354,6 +16335,13 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
         */
        if (!is_constraint)
        {
+               char       *indstatcols = indxinfo->indstatcols;
+               char       *indstatvals = indxinfo->indstatvals;
+               char      **indstatcolsarray = NULL;
+               char      **indstatvalsarray = NULL;
+               int                     nstatcols;
+               int                     nstatvals;
+
                if (dopt->binary_upgrade)
                        binary_upgrade_set_pg_class_oids(fout, q,
                                                                                         indxinfo->dobj.catId.oid, true);
@@ -16361,48 +16349,81 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
                /* Plain secondary index */
                appendPQExpBuffer(q, "%s;\n", indxinfo->indexdef);
 
+               /*
+                * Append ALTER TABLE commands as needed to set properties that we
+                * only have ALTER TABLE syntax for.  Keep this in sync with the
+                * similar code in dumpConstraint!
+                */
+
                /* If the index is clustered, we need to record that. */
                if (indxinfo->indisclustered)
                {
                        appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
-                                                         fmtId(tbinfo->dobj.name));
+                                                         fmtQualifiedDumpable(tbinfo));
+                       /* index name is not qualified in this syntax */
                        appendPQExpBuffer(q, " ON %s;\n",
-                                                         fmtId(indxinfo->dobj.name));
+                                                         qindxname);
+               }
+
+               /*
+                * If the index has any statistics on some of its columns, generate
+                * the associated ALTER INDEX queries.
+                */
+               if (parsePGArray(indstatcols, &indstatcolsarray, &nstatcols) &&
+                       parsePGArray(indstatvals, &indstatvalsarray, &nstatvals) &&
+                       nstatcols == nstatvals)
+               {
+                       int                     j;
+
+                       for (j = 0; j < nstatcols; j++)
+                       {
+                               appendPQExpBuffer(q, "ALTER INDEX %s ",
+                                                                 fmtQualifiedDumpable(indxinfo));
+
+                               /*
+                                * Note that this is a column number, so no quotes should be
+                                * used.
+                                */
+                               appendPQExpBuffer(q, "ALTER COLUMN %s ",
+                                                                 indstatcolsarray[j]);
+                               appendPQExpBuffer(q, "SET STATISTICS %s;\n",
+                                                                 indstatvalsarray[j]);
+                       }
                }
 
                /* If the index defines identity, we need to record that. */
                if (indxinfo->indisreplident)
                {
                        appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY USING",
-                                                         fmtId(tbinfo->dobj.name));
+                                                         fmtQualifiedDumpable(tbinfo));
+                       /* index name is not qualified in this syntax */
                        appendPQExpBuffer(q, " INDEX %s;\n",
-                                                         fmtId(indxinfo->dobj.name));
+                                                         qindxname);
                }
 
-               /*
-                * DROP must be fully qualified in case same name appears in
-                * pg_catalog
-                */
-               appendPQExpBuffer(delq, "DROP INDEX %s.",
-                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
-               appendPQExpBuffer(delq, "%s;\n",
-                                                 fmtId(indxinfo->dobj.name));
+               appendPQExpBuffer(delq, "DROP INDEX %s;\n",
+                                                 fmtQualifiedDumpable(indxinfo));
 
                if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                        ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
-                                                indxinfo->dobj.name,
-                                                tbinfo->dobj.namespace->dobj.name,
-                                                indxinfo->tablespace,
-                                                tbinfo->rolname, false,
-                                                "INDEX", SECTION_POST_DATA,
-                                                q->data, delq->data, NULL,
-                                                NULL, 0,
-                                                NULL, NULL);
+                                                ARCHIVE_OPTS(.tag = indxinfo->dobj.name,
+                                                                         .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                         .tablespace = indxinfo->tablespace,
+                                                                         .owner = tbinfo->rolname,
+                                                                         .description = "INDEX",
+                                                                         .section = SECTION_POST_DATA,
+                                                                         .createStmt = q->data,
+                                                                         .dropStmt = delq->data));
+
+               if (indstatcolsarray)
+                       free(indstatcolsarray);
+               if (indstatvalsarray)
+                       free(indstatvalsarray);
        }
 
        /* Dump Index Comments */
        if (indxinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "INDEX", qindxname,
                                        tbinfo->dobj.namespace->dobj.name,
                                        tbinfo->rolname,
                                        indxinfo->dobj.catId, 0,
@@ -16411,7 +16432,7 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
+       free(qindxname);
 }
 
 /*
@@ -16428,23 +16449,17 @@ dumpIndexAttach(Archive *fout, IndexAttachInfo *attachinfo)
        {
                PQExpBuffer q = createPQExpBuffer();
 
-               appendPQExpBuffer(q, "\nALTER INDEX %s ",
-                                                 fmtQualifiedId(fout->remoteVersion,
-                                                                                attachinfo->parentIdx->dobj.namespace->dobj.name,
-                                                                                attachinfo->parentIdx->dobj.name));
+               appendPQExpBuffer(q, "ALTER INDEX %s ",
+                                                 fmtQualifiedDumpable(attachinfo->parentIdx));
                appendPQExpBuffer(q, "ATTACH PARTITION %s;\n",
-                                                 fmtQualifiedId(fout->remoteVersion,
-                                                                                attachinfo->partitionIdx->dobj.namespace->dobj.name,
-                                                                                attachinfo->partitionIdx->dobj.name));
+                                                 fmtQualifiedDumpable(attachinfo->partitionIdx));
 
                ArchiveEntry(fout, attachinfo->dobj.catId, attachinfo->dobj.dumpId,
-                                        attachinfo->dobj.name,
-                                        NULL, NULL,
-                                        "",
-                                        false, "INDEX ATTACH", SECTION_POST_DATA,
-                                        q->data, "", NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = attachinfo->dobj.name,
+                                                                 .namespace = attachinfo->dobj.namespace->dobj.name,
+                                                                 .description = "INDEX ATTACH",
+                                                                 .section = SECTION_POST_DATA,
+                                                                 .createStmt = q->data));
 
                destroyPQExpBuffer(q);
        }
@@ -16460,8 +16475,8 @@ dumpStatisticsExt(Archive *fout, StatsExtInfo *statsextinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer labelq;
        PQExpBuffer query;
+       char       *qstatsextname;
        PGresult   *res;
        char       *stxdef;
 
@@ -16471,11 +16486,9 @@ dumpStatisticsExt(Archive *fout, StatsExtInfo *statsextinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       labelq = createPQExpBuffer();
        query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema so references are qualified */
-       selectSourceSchema(fout, statsextinfo->dobj.namespace->dobj.name);
+       qstatsextname = pg_strdup(fmtId(statsextinfo->dobj.name));
 
        appendPQExpBuffer(query, "SELECT "
                                          "pg_catalog.pg_get_statisticsobjdef('%u'::pg_catalog.oid)",
@@ -16485,32 +16498,26 @@ dumpStatisticsExt(Archive *fout, StatsExtInfo *statsextinfo)
 
        stxdef = PQgetvalue(res, 0, 0);
 
-       appendPQExpBuffer(labelq, "STATISTICS %s",
-                                         fmtId(statsextinfo->dobj.name));
-
        /* Result of pg_get_statisticsobjdef is complete except for semicolon */
        appendPQExpBuffer(q, "%s;\n", stxdef);
 
-       appendPQExpBuffer(delq, "DROP STATISTICS %s.",
-                                         fmtId(statsextinfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delq, "%s;\n",
-                                         fmtId(statsextinfo->dobj.name));
+       appendPQExpBuffer(delq, "DROP STATISTICS %s;\n",
+                                         fmtQualifiedDumpable(statsextinfo));
 
        if (statsextinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, statsextinfo->dobj.catId,
                                         statsextinfo->dobj.dumpId,
-                                        statsextinfo->dobj.name,
-                                        statsextinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        statsextinfo->rolname, false,
-                                        "STATISTICS", SECTION_POST_DATA,
-                                        q->data, delq->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = statsextinfo->dobj.name,
+                                                                 .namespace = statsextinfo->dobj.namespace->dobj.name,
+                                                                 .owner = statsextinfo->rolname,
+                                                                 .description = "STATISTICS",
+                                                                 .section = SECTION_POST_DATA,
+                                                                 .createStmt = q->data,
+                                                                 .dropStmt = delq->data));
 
        /* Dump Statistics Comments */
        if (statsextinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "STATISTICS", qstatsextname,
                                        statsextinfo->dobj.namespace->dobj.name,
                                        statsextinfo->rolname,
                                        statsextinfo->dobj.catId, 0,
@@ -16519,8 +16526,8 @@ dumpStatisticsExt(Archive *fout, StatsExtInfo *statsextinfo)
        PQclear(res);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
+       free(qstatsextname);
 }
 
 /*
@@ -16554,15 +16561,15 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                indxinfo = (IndxInfo *) findObjectByDumpId(coninfo->conindex);
 
                if (indxinfo == NULL)
-                       exit_horribly(NULL, "missing index for constraint \"%s\"\n",
-                                                 coninfo->dobj.name);
+                       fatal("missing index for constraint \"%s\"",
+                                 coninfo->dobj.name);
 
                if (dopt->binary_upgrade)
                        binary_upgrade_set_pg_class_oids(fout, q,
                                                                                         indxinfo->dobj.catId.oid, true);
 
                appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
-                                                 fmtId(tbinfo->dobj.name));
+                                                 fmtQualifiedDumpable(tbinfo));
                appendPQExpBuffer(q, "    ADD CONSTRAINT %s ",
                                                  fmtId(coninfo->dobj.name));
 
@@ -16575,7 +16582,7 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                {
                        appendPQExpBuffer(q, "%s (",
                                                          coninfo->contype == 'p' ? "PRIMARY KEY" : "UNIQUE");
-                       for (k = 0; k < indxinfo->indnkeys; k++)
+                       for (k = 0; k < indxinfo->indnkeyattrs; k++)
                        {
                                int                     indkey = (int) indxinfo->indkeys[k];
                                const char *attname;
@@ -16589,6 +16596,23 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                                                                  fmtId(attname));
                        }
 
+                       if (indxinfo->indnkeyattrs < indxinfo->indnattrs)
+                               appendPQExpBufferStr(q, ") INCLUDE (");
+
+                       for (k = indxinfo->indnkeyattrs; k < indxinfo->indnattrs; k++)
+                       {
+                               int                     indkey = (int) indxinfo->indkeys[k];
+                               const char *attname;
+
+                               if (indkey == InvalidAttrNumber)
+                                       break;
+                               attname = getAttrName(indkey, tbinfo);
+
+                               appendPQExpBuffer(q, "%s%s",
+                                                                 (k == indxinfo->indnkeyattrs) ? "" : ", ",
+                                                                 fmtId(attname));
+                       }
+
                        appendPQExpBufferChar(q, ')');
 
                        if (nonemptyReloptions(indxinfo->indreloptions))
@@ -16608,23 +16632,34 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                        appendPQExpBufferStr(q, ";\n");
                }
 
+               /*
+                * Append ALTER TABLE commands as needed to set properties that we
+                * only have ALTER TABLE syntax for.  Keep this in sync with the
+                * similar code in dumpIndex!
+                */
+
                /* If the index is clustered, we need to record that. */
                if (indxinfo->indisclustered)
                {
                        appendPQExpBuffer(q, "\nALTER TABLE %s CLUSTER",
-                                                         fmtId(tbinfo->dobj.name));
+                                                         fmtQualifiedDumpable(tbinfo));
+                       /* index name is not qualified in this syntax */
                        appendPQExpBuffer(q, " ON %s;\n",
                                                          fmtId(indxinfo->dobj.name));
                }
 
-               /*
-                * DROP must be fully qualified in case same name appears in
-                * pg_catalog
-                */
-               appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.",
-                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
-               appendPQExpBuffer(delq, "%s ",
-                                                 fmtId(tbinfo->dobj.name));
+               /* If the index defines identity, we need to record that. */
+               if (indxinfo->indisreplident)
+               {
+                       appendPQExpBuffer(q, "\nALTER TABLE ONLY %s REPLICA IDENTITY USING",
+                                                         fmtQualifiedDumpable(tbinfo));
+                       /* index name is not qualified in this syntax */
+                       appendPQExpBuffer(q, " INDEX %s;\n",
+                                                         fmtId(indxinfo->dobj.name));
+               }
+
+               appendPQExpBuffer(delq, "ALTER TABLE ONLY %s ",
+                                                 fmtQualifiedDumpable(tbinfo));
                appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
                                                  fmtId(coninfo->dobj.name));
 
@@ -16632,35 +16667,39 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
                if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                        ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-                                                tag,
-                                                tbinfo->dobj.namespace->dobj.name,
-                                                indxinfo->tablespace,
-                                                tbinfo->rolname, false,
-                                                "CONSTRAINT", SECTION_POST_DATA,
-                                                q->data, delq->data, NULL,
-                                                NULL, 0,
-                                                NULL, NULL);
+                                                ARCHIVE_OPTS(.tag = tag,
+                                                                         .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                         .tablespace = indxinfo->tablespace,
+                                                                         .owner = tbinfo->rolname,
+                                                                         .description = "CONSTRAINT",
+                                                                         .section = SECTION_POST_DATA,
+                                                                         .createStmt = q->data,
+                                                                         .dropStmt = delq->data));
        }
        else if (coninfo->contype == 'f')
        {
+               char       *only;
+
+               /*
+                * Foreign keys on partitioned tables are always declared as
+                * inheriting to partitions; for all other cases, emit them as
+                * applying ONLY directly to the named table, because that's how they
+                * work for regular inherited tables.
+                */
+               only = tbinfo->relkind == RELKIND_PARTITIONED_TABLE ? "" : "ONLY ";
+
                /*
                 * XXX Potentially wrap in a 'SET CONSTRAINTS OFF' block so that the
                 * current table data is not processed
                 */
-               appendPQExpBuffer(q, "ALTER TABLE ONLY %s\n",
-                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(q, "ALTER TABLE %s%s\n",
+                                                 only, fmtQualifiedDumpable(tbinfo));
                appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
                                                  fmtId(coninfo->dobj.name),
                                                  coninfo->condef);
 
-               /*
-                * DROP must be fully qualified in case same name appears in
-                * pg_catalog
-                */
-               appendPQExpBuffer(delq, "ALTER TABLE ONLY %s.",
-                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
-               appendPQExpBuffer(delq, "%s ",
-                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(delq, "ALTER TABLE %s%s ",
+                                                 only, fmtQualifiedDumpable(tbinfo));
                appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
                                                  fmtId(coninfo->dobj.name));
 
@@ -16668,14 +16707,13 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
                if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                        ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-                                                tag,
-                                                tbinfo->dobj.namespace->dobj.name,
-                                                NULL,
-                                                tbinfo->rolname, false,
-                                                "FK CONSTRAINT", SECTION_POST_DATA,
-                                                q->data, delq->data, NULL,
-                                                NULL, 0,
-                                                NULL, NULL);
+                                                ARCHIVE_OPTS(.tag = tag,
+                                                                         .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                         .owner = tbinfo->rolname,
+                                                                         .description = "FK CONSTRAINT",
+                                                                         .section = SECTION_POST_DATA,
+                                                                         .createStmt = q->data,
+                                                                         .dropStmt = delq->data));
        }
        else if (coninfo->contype == 'c' && tbinfo)
        {
@@ -16686,19 +16724,13 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                {
                        /* not ONLY since we want it to propagate to children */
                        appendPQExpBuffer(q, "ALTER TABLE %s\n",
-                                                         fmtId(tbinfo->dobj.name));
+                                                         fmtQualifiedDumpable(tbinfo));
                        appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
                                                          fmtId(coninfo->dobj.name),
                                                          coninfo->condef);
 
-                       /*
-                        * DROP must be fully qualified in case same name appears in
-                        * pg_catalog
-                        */
-                       appendPQExpBuffer(delq, "ALTER TABLE %s.",
-                                                         fmtId(tbinfo->dobj.namespace->dobj.name));
-                       appendPQExpBuffer(delq, "%s ",
-                                                         fmtId(tbinfo->dobj.name));
+                       appendPQExpBuffer(delq, "ALTER TABLE %s ",
+                                                         fmtQualifiedDumpable(tbinfo));
                        appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
                                                          fmtId(coninfo->dobj.name));
 
@@ -16706,14 +16738,13 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
                        if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                                ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-                                                        tag,
-                                                        tbinfo->dobj.namespace->dobj.name,
-                                                        NULL,
-                                                        tbinfo->rolname, false,
-                                                        "CHECK CONSTRAINT", SECTION_POST_DATA,
-                                                        q->data, delq->data, NULL,
-                                                        NULL, 0,
-                                                        NULL, NULL);
+                                                        ARCHIVE_OPTS(.tag = tag,
+                                                                                 .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                                 .owner = tbinfo->rolname,
+                                                                                 .description = "CHECK CONSTRAINT",
+                                                                                 .section = SECTION_POST_DATA,
+                                                                                 .createStmt = q->data,
+                                                                                 .dropStmt = delq->data));
                }
        }
        else if (coninfo->contype == 'c' && tbinfo == NULL)
@@ -16725,19 +16756,13 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
                if (coninfo->separate)
                {
                        appendPQExpBuffer(q, "ALTER DOMAIN %s\n",
-                                                         fmtId(tyinfo->dobj.name));
+                                                         fmtQualifiedDumpable(tyinfo));
                        appendPQExpBuffer(q, "    ADD CONSTRAINT %s %s;\n",
                                                          fmtId(coninfo->dobj.name),
                                                          coninfo->condef);
 
-                       /*
-                        * DROP must be fully qualified in case same name appears in
-                        * pg_catalog
-                        */
-                       appendPQExpBuffer(delq, "ALTER DOMAIN %s.",
-                                                         fmtId(tyinfo->dobj.namespace->dobj.name));
-                       appendPQExpBuffer(delq, "%s ",
-                                                         fmtId(tyinfo->dobj.name));
+                       appendPQExpBuffer(delq, "ALTER DOMAIN %s ",
+                                                         fmtQualifiedDumpable(tyinfo));
                        appendPQExpBuffer(delq, "DROP CONSTRAINT %s;\n",
                                                          fmtId(coninfo->dobj.name));
 
@@ -16745,20 +16770,19 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
                        if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                                ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-                                                        tag,
-                                                        tyinfo->dobj.namespace->dobj.name,
-                                                        NULL,
-                                                        tyinfo->rolname, false,
-                                                        "CHECK CONSTRAINT", SECTION_POST_DATA,
-                                                        q->data, delq->data, NULL,
-                                                        NULL, 0,
-                                                        NULL, NULL);
+                                                        ARCHIVE_OPTS(.tag = tag,
+                                                                                 .namespace = tyinfo->dobj.namespace->dobj.name,
+                                                                                 .owner = tyinfo->rolname,
+                                                                                 .description = "CHECK CONSTRAINT",
+                                                                                 .section = SECTION_POST_DATA,
+                                                                                 .createStmt = q->data,
+                                                                                 .dropStmt = delq->data));
                }
        }
        else
        {
-               exit_horribly(NULL, "unrecognized constraint type: %c\n",
-                                         coninfo->contype);
+               fatal("unrecognized constraint type: %c",
+                         coninfo->contype);
        }
 
        /* Dump Constraint Comments --- only works for table constraints */
@@ -16782,21 +16806,23 @@ static void
 dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo)
 {
        TableInfo  *tbinfo = coninfo->contable;
-       PQExpBuffer labelq = createPQExpBuffer();
+       PQExpBuffer conprefix = createPQExpBuffer();
+       char       *qtabname;
+
+       qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
 
-       appendPQExpBuffer(labelq, "CONSTRAINT %s ",
+       appendPQExpBuffer(conprefix, "CONSTRAINT %s ON",
                                          fmtId(coninfo->dobj.name));
-       appendPQExpBuffer(labelq, "ON %s",
-                                         fmtId(tbinfo->dobj.name));
 
        if (coninfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, conprefix->data, qtabname,
                                        tbinfo->dobj.namespace->dobj.name,
                                        tbinfo->rolname,
                                        coninfo->dobj.catId, 0,
                                        coninfo->separate ? coninfo->dobj.dumpId : tbinfo->dobj.dumpId);
 
-       destroyPQExpBuffer(labelq);
+       destroyPQExpBuffer(conprefix);
+       free(qtabname);
 }
 
 /*
@@ -16805,23 +16831,19 @@ dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo)
  * find the last built in oid
  *
  * For 7.1 through 8.0, we do this by retrieving datlastsysoid from the
- * pg_database entry for the current database.
+ * pg_database entry for the current database.  (Note: current_database()
+ * requires 7.3; pg_dump requires 8.0 now.)
  */
 static Oid
-findLastBuiltinOid_V71(Archive *fout, const char *dbname)
+findLastBuiltinOid_V71(Archive *fout)
 {
        PGresult   *res;
        Oid                     last_oid;
-       PQExpBuffer query = createPQExpBuffer();
-
-       resetPQExpBuffer(query);
-       appendPQExpBufferStr(query, "SELECT datlastsysoid from pg_database where datname = ");
-       appendStringLiteralAH(query, dbname, fout);
 
-       res = ExecuteSqlQueryForSingleRow(fout, query->data);
+       res = ExecuteSqlQueryForSingleRow(fout,
+                                                                         "SELECT datlastsysoid FROM pg_database WHERE datname = current_database()");
        last_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "datlastsysoid")));
        PQclear(res);
-       destroyPQExpBuffer(query);
 
        return last_oid;
 }
@@ -16849,62 +16871,52 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
                                bufx[32];
        PQExpBuffer query = createPQExpBuffer();
        PQExpBuffer delqry = createPQExpBuffer();
-       PQExpBuffer labelq = createPQExpBuffer();
+       char       *qseqname;
+
+       qseqname = pg_strdup(fmtId(tbinfo->dobj.name));
 
        if (fout->remoteVersion >= 100000)
        {
-               /* Make sure we are in proper schema */
-               selectSourceSchema(fout, "pg_catalog");
-
                appendPQExpBuffer(query,
                                                  "SELECT format_type(seqtypid, NULL), "
                                                  "seqstart, seqincrement, "
                                                  "seqmax, seqmin, "
                                                  "seqcache, seqcycle "
-                                                 "FROM pg_class c "
-                                                 "JOIN pg_sequence s ON (s.seqrelid = c.oid) "
-                                                 "WHERE c.oid = '%u'::oid",
+                                                 "FROM pg_catalog.pg_sequence "
+                                                 "WHERE seqrelid = '%u'::oid",
                                                  tbinfo->dobj.catId.oid);
        }
        else if (fout->remoteVersion >= 80400)
        {
                /*
-                * Before PostgreSQL 10, sequence metadata is in the sequence itself,
-                * so switch to the sequence's schema instead of pg_catalog.
+                * Before PostgreSQL 10, sequence metadata is in the sequence itself.
                 *
                 * Note: it might seem that 'bigint' potentially needs to be
                 * schema-qualified, but actually that's a keyword.
                 */
-
-               /* Make sure we are in proper schema */
-               selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
-
                appendPQExpBuffer(query,
                                                  "SELECT 'bigint' AS sequence_type, "
                                                  "start_value, increment_by, max_value, min_value, "
                                                  "cache_value, is_cycled FROM %s",
-                                                 fmtId(tbinfo->dobj.name));
+                                                 fmtQualifiedDumpable(tbinfo));
        }
        else
        {
-               /* Make sure we are in proper schema */
-               selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
-
                appendPQExpBuffer(query,
                                                  "SELECT 'bigint' AS sequence_type, "
                                                  "0 AS start_value, increment_by, max_value, min_value, "
                                                  "cache_value, is_cycled FROM %s",
-                                                 fmtId(tbinfo->dobj.name));
+                                                 fmtQualifiedDumpable(tbinfo));
        }
 
        res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
        if (PQntuples(res) != 1)
        {
-               write_msg(NULL, ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)\n",
-                                                                "query to get data of sequence \"%s\" returned %d rows (expected 1)\n",
-                                                                PQntuples(res)),
-                                 tbinfo->dobj.name, PQntuples(res));
+               pg_log_error(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)",
+                                                         "query to get data of sequence \"%s\" returned %d rows (expected 1)",
+                                                         PQntuples(res)),
+                                        tbinfo->dobj.name, PQntuples(res));
                exit_nicely(1);
        }
 
@@ -16935,7 +16947,7 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
        }
        else
        {
-               exit_horribly(NULL, "unrecognized sequence type: %s\n", seqtype);
+               fatal("unrecognized sequence type: %s", seqtype);
                default_minv = default_maxv = 0;        /* keep compiler quiet */
        }
 
@@ -16953,14 +16965,12 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
                maxv = NULL;
 
        /*
-        * DROP must be fully qualified in case same name appears in pg_catalog
+        * Identity sequences are not to be dropped separately.
         */
        if (!tbinfo->is_identity_sequence)
        {
-               appendPQExpBuffer(delqry, "DROP SEQUENCE %s.",
-                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
-               appendPQExpBuffer(delqry, "%s;\n",
-                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(delqry, "DROP SEQUENCE %s;\n",
+                                                 fmtQualifiedDumpable(tbinfo));
        }
 
        resetPQExpBuffer(query);
@@ -16979,22 +16989,22 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 
                appendPQExpBuffer(query,
                                                  "ALTER TABLE %s ",
-                                                 fmtId(owning_tab->dobj.name));
+                                                 fmtQualifiedDumpable(owning_tab));
                appendPQExpBuffer(query,
                                                  "ALTER COLUMN %s ADD GENERATED ",
                                                  fmtId(owning_tab->attnames[tbinfo->owning_col - 1]));
                if (owning_tab->attidentity[tbinfo->owning_col - 1] == ATTRIBUTE_IDENTITY_ALWAYS)
-                       appendPQExpBuffer(query, "ALWAYS");
+                       appendPQExpBufferStr(query, "ALWAYS");
                else if (owning_tab->attidentity[tbinfo->owning_col - 1] == ATTRIBUTE_IDENTITY_BY_DEFAULT)
-                       appendPQExpBuffer(query, "BY DEFAULT");
+                       appendPQExpBufferStr(query, "BY DEFAULT");
                appendPQExpBuffer(query, " AS IDENTITY (\n    SEQUENCE NAME %s\n",
-                                                 fmtId(tbinfo->dobj.name));
+                                                 fmtQualifiedDumpable(tbinfo));
        }
        else
        {
                appendPQExpBuffer(query,
                                                  "CREATE SEQUENCE %s\n",
-                                                 fmtId(tbinfo->dobj.name));
+                                                 fmtQualifiedDumpable(tbinfo));
 
                if (strcmp(seqtype, "bigint") != 0)
                        appendPQExpBuffer(query, "    AS %s\n", seqtype);
@@ -17024,24 +17034,22 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
        else
                appendPQExpBufferStr(query, ";\n");
 
-       appendPQExpBuffer(labelq, "SEQUENCE %s", fmtId(tbinfo->dobj.name));
-
        /* binary_upgrade:      no need to clear TOAST table oid */
 
        if (dopt->binary_upgrade)
                binary_upgrade_extension_member(query, &tbinfo->dobj,
-                                                                               labelq->data);
+                                                                               "SEQUENCE", qseqname,
+                                                                               tbinfo->dobj.namespace->dobj.name);
 
        if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
-                                        tbinfo->dobj.name,
-                                        tbinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        tbinfo->rolname,
-                                        false, "SEQUENCE", SECTION_PRE_DATA,
-                                        query->data, delqry->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+                                                                 .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tbinfo->rolname,
+                                                                 .description = "SEQUENCE",
+                                                                 .section = SECTION_PRE_DATA,
+                                                                 .createStmt = query->data,
+                                                                 .dropStmt = delqry->data));
 
        /*
         * If the sequence is owned by a table column, emit the ALTER for it as a
@@ -17060,40 +17068,40 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
                TableInfo  *owning_tab = findTableByOid(tbinfo->owning_tab);
 
                if (owning_tab == NULL)
-                       exit_horribly(NULL, "failed sanity check, parent table with OID %u of sequence with OID %u not found\n",
-                                                 tbinfo->owning_tab, tbinfo->dobj.catId.oid);
+                       fatal("failed sanity check, parent table with OID %u of sequence with OID %u not found",
+                                 tbinfo->owning_tab, tbinfo->dobj.catId.oid);
 
                if (owning_tab->dobj.dump & DUMP_COMPONENT_DEFINITION)
                {
                        resetPQExpBuffer(query);
                        appendPQExpBuffer(query, "ALTER SEQUENCE %s",
-                                                         fmtId(tbinfo->dobj.name));
+                                                         fmtQualifiedDumpable(tbinfo));
                        appendPQExpBuffer(query, " OWNED BY %s",
-                                                         fmtId(owning_tab->dobj.name));
+                                                         fmtQualifiedDumpable(owning_tab));
                        appendPQExpBuffer(query, ".%s;\n",
                                                          fmtId(owning_tab->attnames[tbinfo->owning_col - 1]));
 
                        if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                                ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                                        tbinfo->dobj.name,
-                                                        tbinfo->dobj.namespace->dobj.name,
-                                                        NULL,
-                                                        tbinfo->rolname,
-                                                        false, "SEQUENCE OWNED BY", SECTION_PRE_DATA,
-                                                        query->data, "", NULL,
-                                                        &(tbinfo->dobj.dumpId), 1,
-                                                        NULL, NULL);
+                                                        ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+                                                                                 .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                                 .owner = tbinfo->rolname,
+                                                                                 .description = "SEQUENCE OWNED BY",
+                                                                                 .section = SECTION_PRE_DATA,
+                                                                                 .createStmt = query->data,
+                                                                                 .deps = &(tbinfo->dobj.dumpId),
+                                                                                 .nDeps = 1));
                }
        }
 
        /* Dump Sequence Comments and Security Labels */
        if (tbinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "SEQUENCE", qseqname,
                                        tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                                        tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
 
        if (tbinfo->dobj.dump & DUMP_COMPONENT_SECLABEL)
-               dumpSecLabel(fout, labelq->data,
+               dumpSecLabel(fout, "SEQUENCE", qseqname,
                                         tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                                         tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
 
@@ -17101,7 +17109,7 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(delqry);
-       destroyPQExpBuffer(labelq);
+       free(qseqname);
 }
 
 /*
@@ -17117,21 +17125,18 @@ dumpSequenceData(Archive *fout, TableDataInfo *tdinfo)
        bool            called;
        PQExpBuffer query = createPQExpBuffer();
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
-
        appendPQExpBuffer(query,
                                          "SELECT last_value, is_called FROM %s",
-                                         fmtId(tbinfo->dobj.name));
+                                         fmtQualifiedDumpable(tbinfo));
 
        res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
        if (PQntuples(res) != 1)
        {
-               write_msg(NULL, ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)\n",
-                                                                "query to get data of sequence \"%s\" returned %d rows (expected 1)\n",
-                                                                PQntuples(res)),
-                                 tbinfo->dobj.name, PQntuples(res));
+               pg_log_error(ngettext("query to get data of sequence \"%s\" returned %d row (expected 1)",
+                                                         "query to get data of sequence \"%s\" returned %d rows (expected 1)",
+                                                         PQntuples(res)),
+                                        tbinfo->dobj.name, PQntuples(res));
                exit_nicely(1);
        }
 
@@ -17140,20 +17145,20 @@ dumpSequenceData(Archive *fout, TableDataInfo *tdinfo)
 
        resetPQExpBuffer(query);
        appendPQExpBufferStr(query, "SELECT pg_catalog.setval(");
-       appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout);
+       appendStringLiteralAH(query, fmtQualifiedDumpable(tbinfo), fout);
        appendPQExpBuffer(query, ", %s, %s);\n",
                                          last, (called ? "true" : "false"));
 
        if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA)
                ArchiveEntry(fout, nilCatalogId, createDumpId(),
-                                        tbinfo->dobj.name,
-                                        tbinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        tbinfo->rolname,
-                                        false, "SEQUENCE SET", SECTION_DATA,
-                                        query->data, "", NULL,
-                                        &(tbinfo->dobj.dumpId), 1,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+                                                                 .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tbinfo->rolname,
+                                                                 .description = "SEQUENCE SET",
+                                                                 .section = SECTION_DATA,
+                                                                 .createStmt = query->data,
+                                                                 .deps = &(tbinfo->dobj.dumpId),
+                                                                 .nDeps = 1));
 
        PQclear(res);
 
@@ -17171,7 +17176,8 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
        TableInfo  *tbinfo = tginfo->tgtable;
        PQExpBuffer query;
        PQExpBuffer delqry;
-       PQExpBuffer labelq;
+       PQExpBuffer trigprefix;
+       char       *qtabname;
        char       *tgargs;
        size_t          lentgargs;
        const char *p;
@@ -17187,17 +17193,14 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
 
        query = createPQExpBuffer();
        delqry = createPQExpBuffer();
-       labelq = createPQExpBuffer();
+       trigprefix = createPQExpBuffer();
+
+       qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
 
-       /*
-        * DROP must be fully qualified in case same name appears in pg_catalog
-        */
        appendPQExpBuffer(delqry, "DROP TRIGGER %s ",
                                          fmtId(tginfo->dobj.name));
-       appendPQExpBuffer(delqry, "ON %s.",
-                                         fmtId(tbinfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(delqry, "%s;\n",
-                                         fmtId(tbinfo->dobj.name));
+       appendPQExpBuffer(delqry, "ON %s;\n",
+                                         fmtQualifiedDumpable(tbinfo));
 
        if (tginfo->tgdef)
        {
@@ -17226,7 +17229,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
                        appendPQExpBufferStr(query, "INSTEAD OF");
                else
                {
-                       write_msg(NULL, "unexpected tgtype value: %d\n", tginfo->tgtype);
+                       pg_log_error("unexpected tgtype value: %d", tginfo->tgtype);
                        exit_nicely(1);
                }
 
@@ -17261,7 +17264,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
                        findx++;
                }
                appendPQExpBuffer(query, " ON %s\n",
-                                                 fmtId(tbinfo->dobj.name));
+                                                 fmtQualifiedDumpable(tbinfo));
 
                if (tginfo->tgisconstraint)
                {
@@ -17286,7 +17289,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
                        appendPQExpBufferStr(query, "    FOR EACH STATEMENT\n    ");
 
                /* regproc output is already sufficiently quoted */
-               appendPQExpBuffer(query, "EXECUTE PROCEDURE %s(",
+               appendPQExpBuffer(query, "EXECUTE FUNCTION %s(",
                                                  tginfo->tgfname);
 
                tgargs = (char *) PQunescapeBytea((unsigned char *) tginfo->tgargs,
@@ -17300,10 +17303,10 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
                        if (p + tlen >= tgargs + lentgargs)
                        {
                                /* hm, not found before end of bytea value... */
-                               write_msg(NULL, "invalid argument string (%s) for trigger \"%s\" on table \"%s\"\n",
-                                                 tginfo->tgargs,
-                                                 tginfo->dobj.name,
-                                                 tbinfo->dobj.name);
+                               pg_log_error("invalid argument string (%s) for trigger \"%s\" on table \"%s\"",
+                                                        tginfo->tgargs,
+                                                        tginfo->dobj.name,
+                                                        tbinfo->dobj.name);
                                exit_nicely(1);
                        }
 
@@ -17319,7 +17322,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
        if (tginfo->tgenabled != 't' && tginfo->tgenabled != 'O')
        {
                appendPQExpBuffer(query, "\nALTER TABLE %s ",
-                                                 fmtId(tbinfo->dobj.name));
+                                                 fmtQualifiedDumpable(tbinfo));
                switch (tginfo->tgenabled)
                {
                        case 'D':
@@ -17340,33 +17343,31 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
                                                  fmtId(tginfo->dobj.name));
        }
 
-       appendPQExpBuffer(labelq, "TRIGGER %s ",
+       appendPQExpBuffer(trigprefix, "TRIGGER %s ON",
                                          fmtId(tginfo->dobj.name));
-       appendPQExpBuffer(labelq, "ON %s",
-                                         fmtId(tbinfo->dobj.name));
 
        tag = psprintf("%s %s", tbinfo->dobj.name, tginfo->dobj.name);
 
        if (tginfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId,
-                                        tag,
-                                        tbinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        tbinfo->rolname, false,
-                                        "TRIGGER", SECTION_POST_DATA,
-                                        query->data, delqry->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tag,
+                                                                 .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tbinfo->rolname,
+                                                                 .description = "TRIGGER",
+                                                                 .section = SECTION_POST_DATA,
+                                                                 .createStmt = query->data,
+                                                                 .dropStmt = delqry->data));
 
        if (tginfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, trigprefix->data, qtabname,
                                        tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                                        tginfo->dobj.catId, 0, tginfo->dobj.dumpId);
 
        free(tag);
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(delqry);
-       destroyPQExpBuffer(labelq);
+       destroyPQExpBuffer(trigprefix);
+       free(qtabname);
 }
 
 /*
@@ -17379,7 +17380,7 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo)
        DumpOptions *dopt = fout->dopt;
        PQExpBuffer query;
        PQExpBuffer delqry;
-       PQExpBuffer labelq;
+       char       *qevtname;
 
        /* Skip if not to be dumped */
        if (!evtinfo->dobj.dump || dopt->dataOnly)
@@ -17387,10 +17388,11 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo)
 
        query = createPQExpBuffer();
        delqry = createPQExpBuffer();
-       labelq = createPQExpBuffer();
+
+       qevtname = pg_strdup(fmtId(evtinfo->dobj.name));
 
        appendPQExpBufferStr(query, "CREATE EVENT TRIGGER ");
-       appendPQExpBufferStr(query, fmtId(evtinfo->dobj.name));
+       appendPQExpBufferStr(query, qevtname);
        appendPQExpBufferStr(query, " ON ");
        appendPQExpBufferStr(query, fmtId(evtinfo->evtevent));
 
@@ -17401,14 +17403,14 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo)
                appendPQExpBufferChar(query, ')');
        }
 
-       appendPQExpBufferStr(query, "\n   EXECUTE PROCEDURE ");
+       appendPQExpBufferStr(query, "\n   EXECUTE FUNCTION ");
        appendPQExpBufferStr(query, evtinfo->evtfname);
        appendPQExpBufferStr(query, "();\n");
 
        if (evtinfo->evtenabled != 'O')
        {
                appendPQExpBuffer(query, "\nALTER EVENT TRIGGER %s ",
-                                                 fmtId(evtinfo->dobj.name));
+                                                 qevtname);
                switch (evtinfo->evtenabled)
                {
                        case 'D':
@@ -17428,28 +17430,29 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo)
        }
 
        appendPQExpBuffer(delqry, "DROP EVENT TRIGGER %s;\n",
-                                         fmtId(evtinfo->dobj.name));
+                                         qevtname);
 
-       appendPQExpBuffer(labelq, "EVENT TRIGGER %s",
-                                         fmtId(evtinfo->dobj.name));
+       if (dopt->binary_upgrade)
+               binary_upgrade_extension_member(query, &evtinfo->dobj,
+                                                                               "EVENT TRIGGER", qevtname, NULL);
 
        if (evtinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, evtinfo->dobj.catId, evtinfo->dobj.dumpId,
-                                        evtinfo->dobj.name, NULL, NULL,
-                                        evtinfo->evtowner, false,
-                                        "EVENT TRIGGER", SECTION_POST_DATA,
-                                        query->data, delqry->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = evtinfo->dobj.name,
+                                                                 .owner = evtinfo->evtowner,
+                                                                 .description = "EVENT TRIGGER",
+                                                                 .section = SECTION_POST_DATA,
+                                                                 .createStmt = query->data,
+                                                                 .dropStmt = delqry->data));
 
        if (evtinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, "EVENT TRIGGER", qevtname,
                                        NULL, evtinfo->evtowner,
                                        evtinfo->dobj.catId, 0, evtinfo->dobj.dumpId);
 
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(delqry);
-       destroyPQExpBuffer(labelq);
+       free(qevtname);
 }
 
 /*
@@ -17465,7 +17468,8 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
        PQExpBuffer query;
        PQExpBuffer cmd;
        PQExpBuffer delcmd;
-       PQExpBuffer labelq;
+       PQExpBuffer ruleprefix;
+       char       *qtabname;
        PGresult   *res;
        char       *tag;
 
@@ -17486,15 +17490,12 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
         */
        is_view = (rinfo->ev_type == '1' && rinfo->is_instead);
 
-       /*
-        * Make sure we are in proper schema.
-        */
-       selectSourceSchema(fout, tbinfo->dobj.namespace->dobj.name);
-
        query = createPQExpBuffer();
        cmd = createPQExpBuffer();
        delcmd = createPQExpBuffer();
-       labelq = createPQExpBuffer();
+       ruleprefix = createPQExpBuffer();
+
+       qtabname = pg_strdup(fmtId(tbinfo->dobj.name));
 
        if (is_view)
        {
@@ -17505,7 +17506,7 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
                 * Otherwise this should look largely like the regular view dump code.
                 */
                appendPQExpBuffer(cmd, "CREATE OR REPLACE VIEW %s",
-                                                 fmtId(tbinfo->dobj.name));
+                                                 fmtQualifiedDumpable(tbinfo));
                if (nonemptyReloptions(tbinfo->reloptions))
                {
                        appendPQExpBufferStr(cmd, " WITH (");
@@ -17531,8 +17532,8 @@ 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\n",
-                                         rinfo->dobj.name, tbinfo->dobj.name);
+                       pg_log_error("query to get rule \"%s\" for table \"%s\" failed: wrong number of rows returned",
+                                                rinfo->dobj.name, tbinfo->dobj.name);
                        exit_nicely(1);
                }
 
@@ -17547,7 +17548,7 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
         */
        if (rinfo->ev_enabled != 'O')
        {
-               appendPQExpBuffer(cmd, "ALTER TABLE %s ", fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(cmd, "ALTER TABLE %s ", fmtQualifiedDumpable(tbinfo));
                switch (rinfo->ev_enabled)
                {
                        case 'A':
@@ -17565,9 +17566,6 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
                }
        }
 
-       /*
-        * DROP must be fully qualified in case same name appears in pg_catalog
-        */
        if (is_view)
        {
                /*
@@ -17577,9 +17575,8 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
                 */
                PQExpBuffer result;
 
-               appendPQExpBuffer(delcmd, "CREATE OR REPLACE VIEW %s.",
-                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
-               appendPQExpBufferStr(delcmd, fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(delcmd, "CREATE OR REPLACE VIEW %s",
+                                                 fmtQualifiedDumpable(tbinfo));
                result = createDummyViewAsClause(fout, tbinfo);
                appendPQExpBuffer(delcmd, " AS\n%s;\n", result->data);
                destroyPQExpBuffer(result);
@@ -17588,33 +17585,28 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
        {
                appendPQExpBuffer(delcmd, "DROP RULE %s ",
                                                  fmtId(rinfo->dobj.name));
-               appendPQExpBuffer(delcmd, "ON %s.",
-                                                 fmtId(tbinfo->dobj.namespace->dobj.name));
-               appendPQExpBuffer(delcmd, "%s;\n",
-                                                 fmtId(tbinfo->dobj.name));
+               appendPQExpBuffer(delcmd, "ON %s;\n",
+                                                 fmtQualifiedDumpable(tbinfo));
        }
 
-       appendPQExpBuffer(labelq, "RULE %s",
+       appendPQExpBuffer(ruleprefix, "RULE %s ON",
                                          fmtId(rinfo->dobj.name));
-       appendPQExpBuffer(labelq, " ON %s",
-                                         fmtId(tbinfo->dobj.name));
 
        tag = psprintf("%s %s", tbinfo->dobj.name, rinfo->dobj.name);
 
        if (rinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
                ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId,
-                                        tag,
-                                        tbinfo->dobj.namespace->dobj.name,
-                                        NULL,
-                                        tbinfo->rolname, false,
-                                        "RULE", SECTION_POST_DATA,
-                                        cmd->data, delcmd->data, NULL,
-                                        NULL, 0,
-                                        NULL, NULL);
+                                        ARCHIVE_OPTS(.tag = tag,
+                                                                 .namespace = tbinfo->dobj.namespace->dobj.name,
+                                                                 .owner = tbinfo->rolname,
+                                                                 .description = "RULE",
+                                                                 .section = SECTION_POST_DATA,
+                                                                 .createStmt = cmd->data,
+                                                                 .dropStmt = delcmd->data));
 
        /* Dump rule comments */
        if (rinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-               dumpComment(fout, labelq->data,
+               dumpComment(fout, ruleprefix->data, qtabname,
                                        tbinfo->dobj.namespace->dobj.name,
                                        tbinfo->rolname,
                                        rinfo->dobj.catId, 0, rinfo->dobj.dumpId);
@@ -17623,7 +17615,8 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(cmd);
        destroyPQExpBuffer(delcmd);
-       destroyPQExpBuffer(labelq);
+       destroyPQExpBuffer(ruleprefix);
+       free(qtabname);
 }
 
 /*
@@ -17655,9 +17648,6 @@ getExtensionMembership(Archive *fout, ExtensionInfo extinfo[],
        if (numExtensions == 0)
                return;
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        query = createPQExpBuffer();
 
        /* refclassid constraint is redundant but may speed the search */
@@ -17704,7 +17694,7 @@ getExtensionMembership(Archive *fout, ExtensionInfo extinfo[],
                if (ext == NULL)
                {
                        /* shouldn't happen */
-                       fprintf(stderr, "could not find referenced extension %u\n", extId);
+                       pg_log_warning("could not find referenced extension %u", extId);
                        continue;
                }
 
@@ -17828,12 +17818,7 @@ processExtensionTables(Archive *fout, ExtensionInfo extinfo[],
 
                                if (dumpobj)
                                {
-                                       /*
-                                        * Note: config tables are dumped without OIDs regardless
-                                        * of the --oids setting.  This is because row filtering
-                                        * conditions aren't compatible with dumping OIDs.
-                                        */
-                                       makeTableDataInfo(dopt, configtbl, false);
+                                       makeTableDataInfo(dopt, configtbl);
                                        if (configtbl->dataObj != NULL)
                                        {
                                                if (strlen(extconditionarray[j]) > 0)
@@ -17857,9 +17842,6 @@ processExtensionTables(Archive *fout, ExtensionInfo extinfo[],
         * recreated after the data has been loaded.
         */
 
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
-
        query = createPQExpBuffer();
 
        printfPQExpBuffer(query,
@@ -17924,23 +17906,57 @@ getDependencies(Archive *fout)
        DumpableObject *dobj,
                           *refdobj;
 
-       if (g_verbose)
-               write_msg(NULL, "reading dependency data\n");
-
-       /* Make sure we are in proper schema */
-       selectSourceSchema(fout, "pg_catalog");
+       pg_log_info("reading dependency data");
 
        query = createPQExpBuffer();
 
        /*
+        * Messy query to collect the dependency data we need.  Note that we
+        * ignore the sub-object column, so that dependencies of or on a column
+        * look the same as dependencies of or on a whole table.
+        *
         * PIN dependencies aren't interesting, and EXTENSION dependencies were
         * already processed by getExtensionMembership.
         */
        appendPQExpBufferStr(query, "SELECT "
                                                 "classid, objid, refclassid, refobjid, deptype "
                                                 "FROM pg_depend "
-                                                "WHERE deptype != 'p' AND deptype != 'e' "
-                                                "ORDER BY 1,2");
+                                                "WHERE deptype != 'p' AND deptype != 'e'\n");
+
+       /*
+        * Since we don't treat pg_amop entries as separate DumpableObjects, we
+        * have to translate their dependencies into dependencies of their parent
+        * opfamily.  Ignore internal dependencies though, as those will point to
+        * their parent opclass, which we needn't consider here (and if we did,
+        * it'd just result in circular dependencies).  Also, "loose" opfamily
+        * entries will have dependencies on their parent opfamily, which we
+        * should drop since they'd likewise become useless self-dependencies.
+        * (But be sure to keep deps on *other* opfamilies; see amopsortfamily.)
+        *
+        * Skip this for pre-8.3 source servers: pg_opfamily doesn't exist there,
+        * and the (known) cases where it would matter to have these dependencies
+        * can't arise anyway.
+        */
+       if (fout->remoteVersion >= 80300)
+       {
+               appendPQExpBufferStr(query, "UNION ALL\n"
+                                                        "SELECT 'pg_opfamily'::regclass AS classid, amopfamily AS objid, refclassid, refobjid, deptype "
+                                                        "FROM pg_depend d, pg_amop o "
+                                                        "WHERE deptype NOT IN ('p', 'e', 'i') AND "
+                                                        "classid = 'pg_amop'::regclass AND objid = o.oid "
+                                                        "AND NOT (refclassid = 'pg_opfamily'::regclass AND amopfamily = refobjid)\n");
+
+               /* Likewise for pg_amproc entries */
+               appendPQExpBufferStr(query, "UNION ALL\n"
+                                                        "SELECT 'pg_opfamily'::regclass AS classid, amprocfamily AS objid, refclassid, refobjid, deptype "
+                                                        "FROM pg_depend d, pg_amproc p "
+                                                        "WHERE deptype NOT IN ('p', 'e', 'i') AND "
+                                                        "classid = 'pg_amproc'::regclass AND objid = p.oid "
+                                                        "AND NOT (refclassid = 'pg_opfamily'::regclass AND amprocfamily = refobjid)\n");
+       }
+
+       /* Sort the output for efficiency below */
+       appendPQExpBufferStr(query, "ORDER BY 1,2");
 
        res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
 
@@ -17983,8 +17999,8 @@ getDependencies(Archive *fout)
                if (dobj == NULL)
                {
 #ifdef NOT_USED
-                       fprintf(stderr, "no referencing object %u %u\n",
-                                       objId.tableoid, objId.oid);
+                       pg_log_warning("no referencing object %u %u",
+                                                  objId.tableoid, objId.oid);
 #endif
                        continue;
                }
@@ -17994,8 +18010,8 @@ getDependencies(Archive *fout)
                if (refdobj == NULL)
                {
 #ifdef NOT_USED
-                       fprintf(stderr, "no referenced object %u %u\n",
-                                       refobjId.tableoid, refobjId.oid);
+                       pg_log_warning("no referenced object %u %u",
+                                                  refobjId.tableoid, refobjId.oid);
 #endif
                        continue;
                }
@@ -18258,46 +18274,14 @@ findDumpableDependencies(ArchiveHandle *AH, DumpableObject *dobj,
 }
 
 
-/*
- * selectSourceSchema - make the specified schema the active search path
- * in the source database.
- *
- * NB: pg_catalog is explicitly searched after the specified schema;
- * so user names are only qualified if they are cross-schema references,
- * and system names are only qualified if they conflict with a user name
- * in the current schema.
- *
- * Whenever the selected schema is not pg_catalog, be careful to qualify
- * references to system catalogs and types in our emitted commands!
- *
- * This function is called only from selectSourceSchemaOnAH and
- * selectSourceSchema.
- */
-static void
-selectSourceSchema(Archive *fout, const char *schemaName)
-{
-       PQExpBuffer query;
-
-       /* This is checked by the callers already */
-       Assert(schemaName != NULL && *schemaName != '\0');
-
-       query = createPQExpBuffer();
-       appendPQExpBuffer(query, "SET search_path = %s",
-                                         fmtId(schemaName));
-       if (strcmp(schemaName, "pg_catalog") != 0)
-               appendPQExpBufferStr(query, ", pg_catalog");
-
-       ExecuteSqlStatement(fout, query->data);
-
-       destroyPQExpBuffer(query);
-}
-
 /*
  * getFormattedTypeName - retrieve a nicely-formatted type name for the
- * given type name.
+ * given type OID.
+ *
+ * This does not guarantee to schema-qualify the output, so it should not
+ * be used to create the target object name for CREATE or ALTER commands.
  *
- * NB: the result may depend on the currently-selected search_path; this is
- * why we don't try to cache the names.
+ * TODO: there might be some value in caching the results.
  */
 static char *
 getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts)
@@ -18345,6 +18329,7 @@ fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer)
        int                     numatts = ti->numatts;
        char      **attnames = ti->attnames;
        bool       *attisdropped = ti->attisdropped;
+       char       *attgenerated = ti->attgenerated;
        bool            needComma;
        int                     i;
 
@@ -18354,6 +18339,8 @@ fmtCopyColumnList(const TableInfo *ti, PQExpBuffer buffer)
        {
                if (attisdropped[i])
                        continue;
+               if (attgenerated[i])
+                       continue;
                if (needComma)
                        appendPQExpBufferStr(buffer, ", ");
                appendPQExpBufferStr(buffer, fmtId(attnames[i]));
@@ -18391,5 +18378,5 @@ appendReloptionsArrayAH(PQExpBuffer buffer, const char *reloptions,
        res = appendReloptionsArray(buffer, reloptions, prefix, fout->encoding,
                                                                fout->std_strings);
        if (!res)
-               write_msg(NULL, "WARNING: could not parse reloptions array\n");
+               pg_log_warning("could not parse reloptions array");
 }