OSDN Git Service

Fix pg_upgrade to handle extensions.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 10 Feb 2011 00:17:33 +0000 (19:17 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 10 Feb 2011 00:18:08 +0000 (19:18 -0500)
This follows my proposal of yesterday, namely that we try to recreate the
previous state of the extension exactly, instead of allowing CREATE
EXTENSION to run a SQL script that might create some entirely-incompatible
on-disk state.  In --binary-upgrade mode, pg_dump won't issue CREATE
EXTENSION at all, but instead uses a kluge function provided by
pg_upgrade_support to recreate the pg_extension row (and extension-level
pg_depend entries) without creating any member objects.  The member objects
are then restored in the same way as if they weren't members, in particular
using pg_upgrade's normal hacks to preserve OIDs that need to be preserved.
Then, for each member object, ALTER EXTENSION ADD is issued to recreate the
pg_depend entry that marks it as an extension member.

In passing, fix breakage in pg_upgrade's enum-type support: somebody didn't
fix it when the noise word VALUE got added to ALTER TYPE ADD.  Also,
rationalize parsetree representation of COMMENT ON DOMAIN and fix
get_object_address() to allow OBJECT_DOMAIN.

contrib/pg_upgrade/function.c
contrib/pg_upgrade_support/pg_upgrade_support.c
src/backend/catalog/objectaddress.c
src/backend/commands/comment.c
src/backend/commands/extension.c
src/backend/parser/gram.y
src/bin/pg_dump/common.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/include/commands/extension.h

index d7c790c..c01ff04 100644 (file)
@@ -36,52 +36,58 @@ install_support_functions_in_new_db(const char *db_name)
 
        PQclear(executeQueryOrDie(conn,
                                                          "CREATE OR REPLACE FUNCTION "
-                                "              binary_upgrade.set_next_pg_type_oid(OID) "
+                                                         "binary_upgrade.set_next_pg_type_oid(OID) "
                                                          "RETURNS VOID "
                                                          "AS '$libdir/pg_upgrade_support' "
                                                          "LANGUAGE C STRICT;"));
        PQclear(executeQueryOrDie(conn,
                                                          "CREATE OR REPLACE FUNCTION "
-                  "            binary_upgrade.set_next_array_pg_type_oid(OID) "
+                                                         "binary_upgrade.set_next_array_pg_type_oid(OID) "
                                                          "RETURNS VOID "
                                                          "AS '$libdir/pg_upgrade_support' "
                                                          "LANGUAGE C STRICT;"));
        PQclear(executeQueryOrDie(conn,
                                                          "CREATE OR REPLACE FUNCTION "
-                  "            binary_upgrade.set_next_toast_pg_type_oid(OID) "
+                                                         "binary_upgrade.set_next_toast_pg_type_oid(OID) "
                                                          "RETURNS VOID "
                                                          "AS '$libdir/pg_upgrade_support' "
                                                          "LANGUAGE C STRICT;"));
        PQclear(executeQueryOrDie(conn,
                                                          "CREATE OR REPLACE FUNCTION "
-                       "               binary_upgrade.set_next_heap_pg_class_oid(OID) "
+                                                         "binary_upgrade.set_next_heap_pg_class_oid(OID) "
                                                          "RETURNS VOID "
                                                          "AS '$libdir/pg_upgrade_support' "
                                                          "LANGUAGE C STRICT;"));
        PQclear(executeQueryOrDie(conn,
                                                          "CREATE OR REPLACE FUNCTION "
-                  "            binary_upgrade.set_next_index_pg_class_oid(OID) "
+                                                         "binary_upgrade.set_next_index_pg_class_oid(OID) "
                                                          "RETURNS VOID "
                                                          "AS '$libdir/pg_upgrade_support' "
                                                          "LANGUAGE C STRICT;"));
        PQclear(executeQueryOrDie(conn,
                                                          "CREATE OR REPLACE FUNCTION "
-                  "            binary_upgrade.set_next_toast_pg_class_oid(OID) "
+                                                         "binary_upgrade.set_next_toast_pg_class_oid(OID) "
                                                          "RETURNS VOID "
                                                          "AS '$libdir/pg_upgrade_support' "
                                                          "LANGUAGE C STRICT;"));
        PQclear(executeQueryOrDie(conn,
                                                          "CREATE OR REPLACE FUNCTION "
-                "              binary_upgrade.set_next_pg_enum_oid(OID) "
+                                                         "binary_upgrade.set_next_pg_enum_oid(OID) "
                                                          "RETURNS VOID "
                                                          "AS '$libdir/pg_upgrade_support' "
                                                          "LANGUAGE C STRICT;"));
        PQclear(executeQueryOrDie(conn,
                                                          "CREATE OR REPLACE FUNCTION "
-                "              binary_upgrade.set_next_pg_authid_oid(OID) "
+                                                         "binary_upgrade.set_next_pg_authid_oid(OID) "
                                                          "RETURNS VOID "
                                                          "AS '$libdir/pg_upgrade_support' "
                                                          "LANGUAGE C STRICT;"));
+       PQclear(executeQueryOrDie(conn,
+                                                         "CREATE OR REPLACE FUNCTION "
+                                                         "binary_upgrade.create_empty_extension(text, text, bool, text, oid[], text[], text[]) "
+                                                         "RETURNS VOID "
+                                                         "AS '$libdir/pg_upgrade_support' "
+                                                         "LANGUAGE C;"));
        PQfinish(conn);
 }
 
@@ -139,8 +145,8 @@ get_loadable_libraries(void)
                                                                                "SELECT DISTINCT probin "
                                                                                "FROM   pg_catalog.pg_proc "
                                                                                "WHERE  prolang = 13 /* C */ AND "
-                                                                        "              probin IS NOT NULL AND "
-                                                                               "               oid >= %u;",
+                                                                               "probin IS NOT NULL AND "
+                                                                               "oid >= %u;",
                                                                                FirstNormalObjectId);
                totaltups += PQntuples(ress[dbnum]);
 
index b499ff8..8b0e474 100644 (file)
@@ -1,8 +1,9 @@
 /*
- *     pg_upgrade_sysoids.c
+ *     pg_upgrade_support.c
  *
  *     server-side functions to set backend global variables
- *     to control oid and relfilenode assignment
+ *     to control oid and relfilenode assignment, and do other special
+ *     hacks needed for pg_upgrade.
  *
  *     Copyright (c) 2010-2011, PostgreSQL Global Development Group
  *     contrib/pg_upgrade_support/pg_upgrade_support.c
 
 #include "fmgr.h"
 #include "catalog/dependency.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_class.h"
+#include "catalog/pg_type.h"
+#include "commands/extension.h"
+#include "miscadmin.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
 
 /* THIS IS USED ONLY FOR PG >= 9.0 */
 
@@ -42,6 +49,8 @@ Datum         set_next_toast_pg_class_oid(PG_FUNCTION_ARGS);
 Datum          set_next_pg_enum_oid(PG_FUNCTION_ARGS);
 Datum          set_next_pg_authid_oid(PG_FUNCTION_ARGS);
 
+Datum          create_empty_extension(PG_FUNCTION_ARGS);
+
 PG_FUNCTION_INFO_V1(set_next_pg_type_oid);
 PG_FUNCTION_INFO_V1(set_next_array_pg_type_oid);
 PG_FUNCTION_INFO_V1(set_next_toast_pg_type_oid);
@@ -53,6 +62,8 @@ PG_FUNCTION_INFO_V1(set_next_toast_pg_class_oid);
 PG_FUNCTION_INFO_V1(set_next_pg_enum_oid);
 PG_FUNCTION_INFO_V1(set_next_pg_authid_oid);
 
+PG_FUNCTION_INFO_V1(create_empty_extension);
+
 
 Datum
 set_next_pg_type_oid(PG_FUNCTION_ARGS)
@@ -133,3 +144,61 @@ set_next_pg_authid_oid(PG_FUNCTION_ARGS)
        PG_RETURN_VOID();
 }
 
+Datum
+create_empty_extension(PG_FUNCTION_ARGS)
+{
+       text       *extName = PG_GETARG_TEXT_PP(0);
+       text       *schemaName = PG_GETARG_TEXT_PP(1);
+       bool            relocatable = PG_GETARG_BOOL(2);
+       char       *extVersion;
+       Datum           extConfig;
+       Datum           extCondition;
+       List       *requiredExtensions;
+
+       if (PG_ARGISNULL(3))
+               extVersion = NULL;
+       else
+               extVersion = text_to_cstring(PG_GETARG_TEXT_PP(3));
+
+       if (PG_ARGISNULL(4))
+               extConfig = PointerGetDatum(NULL);
+       else
+               extConfig = PG_GETARG_DATUM(4);
+
+       if (PG_ARGISNULL(5))
+               extCondition = PointerGetDatum(NULL);
+       else
+               extCondition = PG_GETARG_DATUM(5);
+
+       requiredExtensions = NIL;
+       if (!PG_ARGISNULL(6))
+       {
+               ArrayType  *textArray = PG_GETARG_ARRAYTYPE_P(6);
+               Datum      *textDatums;
+               int                     ndatums;
+               int                     i;
+
+               deconstruct_array(textArray,
+                                                 TEXTOID, -1, false, 'i',
+                                                 &textDatums, NULL, &ndatums);
+               for (i = 0; i < ndatums; i++)
+               {
+                       text   *txtname = DatumGetTextPP(textDatums[i]);
+                       char   *extName = text_to_cstring(txtname);
+                       Oid             extOid = get_extension_oid(extName, false);
+
+                       requiredExtensions = lappend_oid(requiredExtensions, extOid);
+               }
+       }
+
+       InsertExtensionTuple(text_to_cstring(extName),
+                                                GetUserId(),
+                                                get_namespace_oid(text_to_cstring(schemaName), false),
+                                                relocatable,
+                                                extVersion,
+                                                extConfig,
+                                                extCondition,
+                                                requiredExtensions);
+
+       PG_RETURN_VOID();
+}
index 82989ac..505bc35 100644 (file)
@@ -139,6 +139,7 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
                        address = get_object_address_unqualified(objtype, objname);
                        break;
                case OBJECT_TYPE:
+               case OBJECT_DOMAIN:
                        address.classId = TypeRelationId;
                        address.objectId =
                                typenameTypeId(NULL, makeTypeNameFromNameList(objname));
index bbb3f34..faef256 100644 (file)
@@ -105,6 +105,7 @@ CommentObject(CommentStmt *stmt)
                                                           strVal(linitial(stmt->objname)));
                        break;
                case OBJECT_TYPE:
+               case OBJECT_DOMAIN:
                        if (!pg_type_ownercheck(address.objectId, GetUserId()))
                                aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
                                                           format_type_be(address.objectId));
index 41667fb..1da76ac 100644 (file)
@@ -648,13 +648,7 @@ CreateExtension(CreateExtensionStmt *stmt)
        ExtensionControlFile *control;
        List       *requiredExtensions;
        List       *requiredSchemas;
-       Relation        rel;
-       Datum           values[Natts_pg_extension];
-       bool            nulls[Natts_pg_extension];
-       HeapTuple       tuple;
        Oid                     extensionOid;
-       ObjectAddress myself;
-       ObjectAddress nsp;
        ListCell   *lc;
 
        /* Must be super user */
@@ -801,7 +795,58 @@ CreateExtension(CreateExtensionStmt *stmt)
        }
 
        /*
-        * Insert new tuple into pg_extension.
+        * Insert new tuple into pg_extension, and create dependency entries.
+        */
+       extensionOid = InsertExtensionTuple(control->name, extowner,
+                                                                               schemaOid, control->relocatable,
+                                                                               control->version,
+                                                                               PointerGetDatum(NULL),
+                                                                               PointerGetDatum(NULL),
+                                                                               requiredExtensions);
+
+       /*
+        * Apply any comment on extension
+        */
+       if (control->comment != NULL)
+               CreateComments(extensionOid, ExtensionRelationId, 0, control->comment);
+
+       /*
+        * Finally, execute the extension script to create the member objects
+        */
+       execute_extension_script(extensionOid, control, requiredSchemas,
+                                                        schemaName, schemaOid);
+}
+
+/*
+ * InsertExtensionTuple
+ *
+ * Insert the new pg_extension row, and create extension's dependency entries.
+ * Return the OID assigned to the new row.
+ *
+ * This is exported for the benefit of pg_upgrade, which has to create a
+ * pg_extension entry (and the extension-level dependencies) without
+ * actually running the extension's script.
+ *
+ * extConfig and extCondition should be arrays or PointerGetDatum(NULL).
+ * We declare them as plain Datum to avoid needing array.h in extension.h.
+ */
+Oid
+InsertExtensionTuple(const char *extName, Oid extOwner,
+                                        Oid schemaOid, bool relocatable, const char *extVersion,
+                                        Datum extConfig, Datum extCondition,
+                                        List *requiredExtensions)
+{
+       Oid                     extensionOid;
+       Relation        rel;
+       Datum           values[Natts_pg_extension];
+       bool            nulls[Natts_pg_extension];
+       HeapTuple       tuple;
+       ObjectAddress myself;
+       ObjectAddress nsp;
+       ListCell   *lc;
+
+       /*
+        * Build and insert the pg_extension tuple
         */
        rel = heap_open(ExtensionRelationId, RowExclusiveLock);
 
@@ -809,19 +854,26 @@ CreateExtension(CreateExtensionStmt *stmt)
        memset(nulls, 0, sizeof(nulls));
 
        values[Anum_pg_extension_extname - 1] =
-               DirectFunctionCall1(namein, CStringGetDatum(control->name));
-       values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extowner);
+               DirectFunctionCall1(namein, CStringGetDatum(extName));
+       values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
        values[Anum_pg_extension_extnamespace - 1] = ObjectIdGetDatum(schemaOid);
-       values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(control->relocatable);
+       values[Anum_pg_extension_extrelocatable - 1] = BoolGetDatum(relocatable);
 
-       if (control->version == NULL)
+       if (extVersion == NULL)
                nulls[Anum_pg_extension_extversion - 1] = true;
        else
                values[Anum_pg_extension_extversion - 1] =
-                       CStringGetTextDatum(control->version);
+                       CStringGetTextDatum(extVersion);
+
+       if (extConfig == PointerGetDatum(NULL))
+               nulls[Anum_pg_extension_extconfig - 1] = true;
+       else
+               values[Anum_pg_extension_extconfig - 1] = extConfig;
 
-       nulls[Anum_pg_extension_extconfig - 1] = true;
-       nulls[Anum_pg_extension_extcondition - 1] = true;
+       if (extCondition == PointerGetDatum(NULL))
+               nulls[Anum_pg_extension_extcondition - 1] = true;
+       else
+               values[Anum_pg_extension_extcondition - 1] = extCondition;
 
        tuple = heap_form_tuple(rel->rd_att, values, nulls);
 
@@ -832,15 +884,9 @@ CreateExtension(CreateExtensionStmt *stmt)
        heap_close(rel, RowExclusiveLock);
 
        /*
-        * Apply any comment on extension
-        */
-       if (control->comment != NULL)
-               CreateComments(extensionOid, ExtensionRelationId, 0, control->comment);
-
-       /*
         * Record dependencies on owner, schema, and prerequisite extensions
         */
-       recordDependencyOnOwner(ExtensionRelationId, extensionOid, extowner);
+       recordDependencyOnOwner(ExtensionRelationId, extensionOid, extOwner);
 
        myself.classId = ExtensionRelationId;
        myself.objectId = extensionOid;
@@ -864,11 +910,7 @@ CreateExtension(CreateExtensionStmt *stmt)
                recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
        }
 
-       /*
-        * Finally, execute the extension script to create the member objects
-        */
-       execute_extension_script(extensionOid, control, requiredSchemas,
-                                                        schemaName, schemaOid);
+       return extensionOid;
 }
 
 
index a61f3dc..8c63027 100644 (file)
@@ -4790,7 +4790,7 @@ comment_type:
                        | INDEX                                                         { $$ = OBJECT_INDEX; }
                        | SEQUENCE                                                      { $$ = OBJECT_SEQUENCE; }
                        | TABLE                                                         { $$ = OBJECT_TABLE; }
-                       | DOMAIN_P                                                      { $$ = OBJECT_TYPE; }
+                       | DOMAIN_P                                                      { $$ = OBJECT_DOMAIN; }
                        | TYPE_P                                                        { $$ = OBJECT_TYPE; }
                        | VIEW                                                          { $$ = OBJECT_VIEW; }
                        | CONVERSION_P                                          { $$ = OBJECT_CONVERSION; }
index 8c4270c..9c6508e 100644 (file)
@@ -463,6 +463,7 @@ AssignDumpId(DumpableObject *dobj)
        dobj->name = NULL;                      /* must be set later */
        dobj->namespace = NULL;         /* may be set later */
        dobj->dump = true;                      /* default assumption */
+       dobj->ext_member = false;       /* default assumption */
        dobj->dependencies = NULL;
        dobj->nDeps = 0;
        dobj->allocDeps = 0;
index 83850a8..5561c7a 100644 (file)
@@ -234,6 +234,9 @@ static bool binary_upgrade_set_type_oids_by_rel_oid(
                                                                 PQExpBuffer upgrade_buffer, Oid pg_rel_oid);
 static void binary_upgrade_set_pg_class_oids(PQExpBuffer upgrade_buffer,
                                                                Oid pg_class_oid, bool is_index);
+static void binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
+                                                                                       DumpableObject *dobj,
+                                                                                       const char *objlabel);
 static const char *getAttrName(int attrnum, TableInfo *tblInfo);
 static const char *fmtCopyColumnList(const TableInfo *ti);
 static void do_sql_command(PGconn *conn, const char *query);
@@ -1586,7 +1589,6 @@ makeTableDataInfo(TableInfo *tbinfo, bool oids)
        AssignDumpId(&tdinfo->dobj);
        tdinfo->dobj.name = tbinfo->dobj.name;
        tdinfo->dobj.namespace = tbinfo->dobj.namespace;
-       tdinfo->dobj.dump = true;
        tdinfo->tdtable = tbinfo;
        tdinfo->oids = oids;
        tdinfo->filtercond = NULL;                              /* might get set later */
@@ -2468,6 +2470,47 @@ binary_upgrade_set_pg_class_oids(PQExpBuffer upgrade_buffer, Oid pg_class_oid,
 }
 
 /*
+ * If the DumpableObject is a member of an extension, add a suitable
+ * ALTER EXTENSION ADD command to the creation commands in upgrade_buffer.
+ */
+static void
+binary_upgrade_extension_member(PQExpBuffer upgrade_buffer,
+                                                               DumpableObject *dobj,
+                                                               const char *objlabel)
+{
+       DumpableObject *extobj = NULL;
+       int                     i;
+
+       if (!dobj->ext_member)
+               return;
+
+       /*
+        * Find the parent extension.  We could avoid this search if we wanted
+        * to add a link field to DumpableObject, but the space costs of that
+        * would be considerable.  We assume that member objects could only have
+        * a direct dependency on their own extension, not any others.
+        */
+       for (i = 0; i < dobj->nDeps; i++)
+       {
+               extobj = findObjectByDumpId(dobj->dependencies[i]);
+               if (extobj && extobj->objType == DO_EXTENSION)
+                       break;
+               extobj = NULL;
+       }
+       if (extobj == NULL)
+       {
+               write_msg(NULL, "failed to find parent extension for %s", objlabel);
+               exit_nicely();
+       }
+
+       appendPQExpBuffer(upgrade_buffer,
+                                         "\n-- For binary upgrade, handle extension membership the hard way\n");
+       appendPQExpBuffer(upgrade_buffer, "ALTER EXTENSION %s ADD %s;\n",
+                                         fmtId(extobj->name),
+                                         objlabel);
+}
+
+/*
  * getNamespaces:
  *       read all namespaces in the system catalogs and return them in the
  * NamespaceInfo* structure
@@ -2633,6 +2676,8 @@ getExtensions(int *numExtensions)
        int                     i_oid;
        int                     i_extname;
        int                     i_nspname;
+       int                     i_extrelocatable;
+       int                     i_extversion;
        int                     i_extconfig;
        int                     i_extcondition;
 
@@ -2651,7 +2696,7 @@ getExtensions(int *numExtensions)
        selectSourceSchema("pg_catalog");
 
        appendPQExpBuffer(query, "SELECT x.tableoid, x.oid, "
-                                         "x.extname, n.nspname, x.extconfig, x.extcondition "
+                                         "x.extname, n.nspname, x.extrelocatable, x.extversion, x.extconfig, x.extcondition "
                                          "FROM pg_extension x "
                                          "JOIN pg_namespace n ON n.oid = x.extnamespace");
 
@@ -2666,6 +2711,8 @@ getExtensions(int *numExtensions)
        i_oid = PQfnumber(res, "oid");
        i_extname = PQfnumber(res, "extname");
        i_nspname = PQfnumber(res, "nspname");
+       i_extrelocatable = PQfnumber(res, "extrelocatable");
+       i_extversion = PQfnumber(res, "extversion");
        i_extconfig = PQfnumber(res, "extconfig");
        i_extcondition = PQfnumber(res, "extcondition");
 
@@ -2677,11 +2724,13 @@ getExtensions(int *numExtensions)
                AssignDumpId(&extinfo[i].dobj);
                extinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_extname));
                extinfo[i].namespace = strdup(PQgetvalue(res, i, i_nspname));
+               extinfo[i].relocatable = *(PQgetvalue(res, i, i_extrelocatable)) == 't';
+               if (PQgetisnull(res, i, i_extversion))
+                       extinfo[i].extversion = NULL;
+               else
+                       extinfo[i].extversion = strdup(PQgetvalue(res, i, i_extversion));
                extinfo[i].extconfig = strdup(PQgetvalue(res, i, i_extconfig));
                extinfo[i].extcondition = strdup(PQgetvalue(res, i, i_extcondition));
-
-               /* For the moment, all extensions are considered dumpable */
-               extinfo->dobj.dump = true;
        }
 
        PQclear(res);
@@ -5152,9 +5201,6 @@ getProcLangs(int *numProcLangs)
                else
                        planginfo[i].lanowner = strdup("");
 
-               /* Assume it should be dumped (getExtensionMembership may override) */
-               planginfo[i].dobj.dump = true;
-
                if (g_fout->remoteVersion < 70300)
                {
                        /*
@@ -5262,9 +5308,6 @@ getCasts(int *numCasts)
                castinfo[i].castcontext = *(PQgetvalue(res, i, i_castcontext));
                castinfo[i].castmethod = *(PQgetvalue(res, i, i_castmethod));
 
-               /* Assume it should be dumped (getExtensionMembership may override) */
-               castinfo[i].dobj.dump = true;
-
                /*
                 * Try to name cast as concatenation of typnames.  This is only used
                 * for purposes of sorting.  If we fail to find either type, the name
@@ -6803,6 +6846,7 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 {
        PQExpBuffer q;
        PQExpBuffer delq;
+       PQExpBuffer labelq;
        char       *qnspname;
 
        /* Skip if not to be dumped */
@@ -6815,6 +6859,7 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
+       labelq = createPQExpBuffer();
 
        qnspname = strdup(fmtId(nspinfo->dobj.name));
 
@@ -6822,6 +6867,11 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 
        appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
 
+       appendPQExpBuffer(labelq, "SCHEMA %s", qnspname);
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &nspinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
                                 nspinfo->dobj.name,
                                 NULL, NULL,
@@ -6832,12 +6882,10 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
                                 NULL, NULL);
 
        /* Dump Schema Comments and Security Labels */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "SCHEMA %s", qnspname);
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                NULL, nspinfo->rolname,
                                nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
-       dumpSecLabel(fout, q->data,
+       dumpSecLabel(fout, labelq->data,
                                 NULL, nspinfo->rolname,
                                 nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
 
@@ -6849,6 +6897,7 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -6860,6 +6909,7 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo)
 {
        PQExpBuffer q;
        PQExpBuffer delq;
+       PQExpBuffer labelq;
        char       *qextname;
 
        /* Skip if not to be dumped */
@@ -6868,13 +6918,69 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
+       labelq = createPQExpBuffer();
 
        qextname = strdup(fmtId(extinfo->dobj.name));
 
        appendPQExpBuffer(delq, "DROP EXTENSION %s;\n", qextname);
 
-       appendPQExpBuffer(q, "CREATE EXTENSION %s WITH SCHEMA %s;\n",
-                                         qextname, fmtId(extinfo->namespace));
+       if (!binary_upgrade)
+       {
+               appendPQExpBuffer(q, "CREATE EXTENSION %s WITH SCHEMA %s;\n",
+                                                 qextname, fmtId(extinfo->namespace));
+       }
+       else
+       {
+               int             i;
+               int             n;
+
+               appendPQExpBuffer(q, "-- For binary upgrade, create an empty extension and insert objects into it\n");
+               appendPQExpBuffer(q,
+                                                 "SELECT binary_upgrade.create_empty_extension(");
+               appendStringLiteralAH(q, extinfo->dobj.name, fout);
+               appendPQExpBuffer(q, ", ");
+               appendStringLiteralAH(q, extinfo->namespace, fout);
+               appendPQExpBuffer(q, ", ");
+               appendPQExpBuffer(q, "%s, ", extinfo->relocatable ? "true" : "false");
+               if (extinfo->extversion)
+                       appendStringLiteralAH(q, extinfo->extversion, fout);
+               else
+                       appendPQExpBuffer(q, "NULL");
+               appendPQExpBuffer(q, ", ");
+               /*
+                * Note that we're pushing extconfig (an OID array) back into
+                * pg_extension exactly as-is.  This is OK because pg_class OIDs
+                * are preserved in binary upgrade.
+                */
+               if (strlen(extinfo->extconfig) > 2)
+                       appendStringLiteralAH(q, extinfo->extconfig, fout);
+               else
+                       appendPQExpBuffer(q, "NULL");
+               appendPQExpBuffer(q, ", ");
+               if (strlen(extinfo->extcondition) > 2)
+                       appendStringLiteralAH(q, extinfo->extcondition, fout);
+               else
+                       appendPQExpBuffer(q, "NULL");
+               appendPQExpBuffer(q, ", ");
+               appendPQExpBuffer(q, "ARRAY[");
+               n = 0;
+               for (i = 0; i < extinfo->dobj.nDeps; i++)
+               {
+                       DumpableObject *extobj;
+
+                       extobj = findObjectByDumpId(extinfo->dobj.dependencies[i]);
+                       if (extobj && extobj->objType == DO_EXTENSION)
+                       {
+                               if (n++ > 0)
+                                       appendPQExpBuffer(q, ",");
+                               appendStringLiteralAH(q, extobj->name, fout);
+                       }
+               }
+               appendPQExpBuffer(q, "]::pg_catalog.text[]");
+               appendPQExpBuffer(q, ");\n");
+       }
+
+       appendPQExpBuffer(labelq, "EXTENSION %s", qextname);
 
        ArchiveEntry(fout, extinfo->dobj.catId, extinfo->dobj.dumpId,
                                 extinfo->dobj.name,
@@ -6886,12 +6992,10 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo)
                                 NULL, NULL);
 
        /* Dump Extension Comments and Security Labels */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "EXTENSION %s", qextname);
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                NULL, "",
                                extinfo->dobj.catId, 0, extinfo->dobj.dumpId);
-       dumpSecLabel(fout, q->data,
+       dumpSecLabel(fout, labelq->data,
                                 NULL, "",
                                 extinfo->dobj.catId, 0, extinfo->dobj.dumpId);
 
@@ -6899,6 +7003,7 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo)
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -6932,6 +7037,7 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
 {
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
+       PQExpBuffer labelq = createPQExpBuffer();
        PQExpBuffer query = createPQExpBuffer();
        PGresult   *res;
        int                     num,
@@ -7006,13 +7112,18 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
                                                          enum_oid);
                        appendPQExpBuffer(q, "ALTER TYPE %s.",
                                                          fmtId(tyinfo->dobj.namespace->dobj.name));
-                       appendPQExpBuffer(q, "%s ADD ",
+                       appendPQExpBuffer(q, "%s ADD VALUE ",
                                                          fmtId(tyinfo->dobj.name));
                        appendStringLiteralAH(q, label, fout);
                        appendPQExpBuffer(q, ";\n\n");
                }
        }
 
+       appendPQExpBuffer(labelq, "TYPE %s", fmtId(tyinfo->dobj.name));
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
                                 tyinfo->dobj.name,
                                 tyinfo->dobj.namespace->dobj.name,
@@ -7024,19 +7135,17 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
                                 NULL, NULL);
 
        /* Dump Type Comments and Security Labels */
-       resetPQExpBuffer(q);
-
-       appendPQExpBuffer(q, "TYPE %s", fmtId(tyinfo->dobj.name));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
-       dumpSecLabel(fout, q->data,
+       dumpSecLabel(fout, labelq->data,
                                 tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                 tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        PQclear(res);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
 }
 
@@ -7049,6 +7158,7 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
 {
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
+       PQExpBuffer labelq = createPQExpBuffer();
        PQExpBuffer query = createPQExpBuffer();
        PGresult   *res;
        int                     ntups;
@@ -7392,6 +7502,11 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
 
        appendPQExpBuffer(q, "\n);\n");
 
+       appendPQExpBuffer(labelq, "TYPE %s", fmtId(tyinfo->dobj.name));
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
                                 tyinfo->dobj.name,
                                 tyinfo->dobj.namespace->dobj.name,
@@ -7403,19 +7518,17 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
                                 NULL, NULL);
 
        /* Dump Type Comments and Security Labels */
-       resetPQExpBuffer(q);
-
-       appendPQExpBuffer(q, "TYPE %s", fmtId(tyinfo->dobj.name));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
-       dumpSecLabel(fout, q->data,
+       dumpSecLabel(fout, labelq->data,
                                 tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                 tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        PQclear(res);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
 }
 
@@ -7428,6 +7541,7 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
 {
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
+       PQExpBuffer labelq = createPQExpBuffer();
        PQExpBuffer query = createPQExpBuffer();
        PGresult   *res;
        int                     ntups;
@@ -7534,6 +7648,11 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
        appendPQExpBuffer(delq, "%s;\n",
                                          fmtId(tyinfo->dobj.name));
 
+       appendPQExpBuffer(labelq, "DOMAIN %s", fmtId(tyinfo->dobj.name));
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
                                 tyinfo->dobj.name,
                                 tyinfo->dobj.namespace->dobj.name,
@@ -7545,18 +7664,16 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
                                 NULL, NULL);
 
        /* Dump Domain Comments and Security Labels */
-       resetPQExpBuffer(q);
-
-       appendPQExpBuffer(q, "DOMAIN %s", fmtId(tyinfo->dobj.name));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
-       dumpSecLabel(fout, q->data,
+       dumpSecLabel(fout, labelq->data,
                                 tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                 tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
 }
 
@@ -7570,6 +7687,7 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
 {
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
+       PQExpBuffer labelq = createPQExpBuffer();
        PQExpBuffer query = createPQExpBuffer();
        PGresult   *res;
        int                     ntups;
@@ -7636,6 +7754,11 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
        appendPQExpBuffer(delq, "%s;\n",
                                          fmtId(tyinfo->dobj.name));
 
+       appendPQExpBuffer(labelq, "TYPE %s", fmtId(tyinfo->dobj.name));
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &tyinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
                                 tyinfo->dobj.name,
                                 tyinfo->dobj.namespace->dobj.name,
@@ -7648,19 +7771,17 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
 
 
        /* Dump Type Comments and Security Labels */
-       resetPQExpBuffer(q);
-
-       appendPQExpBuffer(q, "TYPE %s", fmtId(tyinfo->dobj.name));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
-       dumpSecLabel(fout, q->data,
+       dumpSecLabel(fout, labelq->data,
                                 tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                                 tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
 
        PQclear(res);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
 
        /* Dump any per-column comments */
@@ -7856,6 +7977,7 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 {
        PQExpBuffer defqry;
        PQExpBuffer delqry;
+       PQExpBuffer labelq;
        bool            useParams;
        char       *qlanname;
        char       *lanschema;
@@ -7907,6 +8029,7 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 
        defqry = createPQExpBuffer();
        delqry = createPQExpBuffer();
+       labelq = createPQExpBuffer();
 
        qlanname = strdup(fmtId(plang->dobj.name));
 
@@ -7967,6 +8090,11 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
        }
        appendPQExpBuffer(defqry, ";\n");
 
+       appendPQExpBuffer(labelq, "LANGUAGE %s", qlanname);
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(defqry, &plang->dobj, labelq->data);
+
        ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
                                 plang->dobj.name,
                                 lanschema, NULL, plang->lanowner,
@@ -7976,12 +8104,10 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
                                 NULL, NULL);
 
        /* Dump Proc Lang Comments and Security Labels */
-       resetPQExpBuffer(defqry);
-       appendPQExpBuffer(defqry, "LANGUAGE %s", qlanname);
-       dumpComment(fout, defqry->data,
+       dumpComment(fout, labelq->data,
                                NULL, "",
                                plang->dobj.catId, 0, plang->dobj.dumpId);
-       dumpSecLabel(fout, defqry->data,
+       dumpSecLabel(fout, labelq->data,
                                 NULL, "",
                                 plang->dobj.catId, 0, plang->dobj.dumpId);
 
@@ -7995,6 +8121,7 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 
        destroyPQExpBuffer(defqry);
        destroyPQExpBuffer(delqry);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -8130,6 +8257,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delqry;
+       PQExpBuffer labelq;
        PQExpBuffer asPart;
        PGresult   *res;
        char       *funcsig;            /* identity signature */
@@ -8169,6 +8297,7 @@ 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 */
@@ -8529,6 +8658,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 
        appendPQExpBuffer(q, "\n    %s;\n", asPart->data);
 
+       appendPQExpBuffer(labelq, "FUNCTION %s", funcsig);
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &finfo->dobj, labelq->data);
+
        ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
                                 funcsig_tag,
                                 finfo->dobj.namespace->dobj.name,
@@ -8540,12 +8674,10 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
                                 NULL, NULL);
 
        /* Dump Function Comments and Security Labels */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "FUNCTION %s", funcsig);
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                finfo->dobj.namespace->dobj.name, finfo->rolname,
                                finfo->dobj.catId, 0, finfo->dobj.dumpId);
-       dumpSecLabel(fout, q->data,
+       dumpSecLabel(fout, labelq->data,
                                 finfo->dobj.namespace->dobj.name, finfo->rolname,
                                 finfo->dobj.catId, 0, finfo->dobj.dumpId);
 
@@ -8559,6 +8691,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delqry);
+       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(asPart);
        free(funcsig);
        free(funcsig_tag);
@@ -8581,7 +8714,7 @@ dumpCast(Archive *fout, CastInfo *cast)
 {
        PQExpBuffer defqry;
        PQExpBuffer delqry;
-       PQExpBuffer castsig;
+       PQExpBuffer labelq;
        FuncInfo   *funcInfo = NULL;
        TypeInfo   *sourceInfo;
        TypeInfo   *targetInfo;
@@ -8645,7 +8778,7 @@ dumpCast(Archive *fout, CastInfo *cast)
 
        defqry = createPQExpBuffer();
        delqry = createPQExpBuffer();
-       castsig = createPQExpBuffer();
+       labelq = createPQExpBuffer();
 
        appendPQExpBuffer(delqry, "DROP CAST (%s AS %s);\n",
                                          getFormattedTypeName(cast->castsource, zeroAsNone),
@@ -8684,12 +8817,15 @@ dumpCast(Archive *fout, CastInfo *cast)
                appendPQExpBuffer(defqry, " AS IMPLICIT");
        appendPQExpBuffer(defqry, ";\n");
 
-       appendPQExpBuffer(castsig, "CAST (%s AS %s)",
+       appendPQExpBuffer(labelq, "CAST (%s AS %s)",
                                          getFormattedTypeName(cast->castsource, zeroAsNone),
                                          getFormattedTypeName(cast->casttarget, zeroAsNone));
 
+       if (binary_upgrade)
+               binary_upgrade_extension_member(defqry, &cast->dobj, labelq->data);
+
        ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId,
-                                castsig->data,
+                                labelq->data,
                                 "pg_catalog", NULL, "",
                                 false, "CAST", SECTION_PRE_DATA,
                                 defqry->data, delqry->data, NULL,
@@ -8697,17 +8833,13 @@ dumpCast(Archive *fout, CastInfo *cast)
                                 NULL, NULL);
 
        /* Dump Cast Comments */
-       resetPQExpBuffer(defqry);
-       appendPQExpBuffer(defqry, "CAST (%s AS %s)",
-                                         getFormattedTypeName(cast->castsource, zeroAsNone),
-                                         getFormattedTypeName(cast->casttarget, zeroAsNone));
-       dumpComment(fout, defqry->data,
+       dumpComment(fout, labelq->data,
                                NULL, "",
                                cast->dobj.catId, 0, cast->dobj.dumpId);
 
        destroyPQExpBuffer(defqry);
        destroyPQExpBuffer(delqry);
-       destroyPQExpBuffer(castsig);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -8720,6 +8852,7 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delq;
+       PQExpBuffer labelq;
        PQExpBuffer oprid;
        PQExpBuffer details;
        const char *name;
@@ -8760,6 +8893,7 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        query = createPQExpBuffer();
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
+       labelq = createPQExpBuffer();
        oprid = createPQExpBuffer();
        details = createPQExpBuffer();
 
@@ -8930,6 +9064,11 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        appendPQExpBuffer(q, "CREATE OPERATOR %s (\n%s\n);\n",
                                          oprinfo->dobj.name, details->data);
 
+       appendPQExpBuffer(labelq, "OPERATOR %s", oprid->data);
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &oprinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId,
                                 oprinfo->dobj.name,
                                 oprinfo->dobj.namespace->dobj.name,
@@ -8941,9 +9080,7 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
                                 NULL, NULL);
 
        /* Dump Operator Comments */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "OPERATOR %s", oprid->data);
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                oprinfo->dobj.namespace->dobj.name, oprinfo->rolname,
                                oprinfo->dobj.catId, 0, oprinfo->dobj.dumpId);
 
@@ -8952,6 +9089,7 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(oprid);
        destroyPQExpBuffer(details);
 }
@@ -9108,6 +9246,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delq;
+       PQExpBuffer labelq;
        PGresult   *res;
        int                     ntups;
        int                     i_opcintype;
@@ -9156,6 +9295,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(opcinfo->dobj.namespace->dobj.name);
@@ -9432,6 +9572,14 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
 
        appendPQExpBuffer(q, ";\n");
 
+       appendPQExpBuffer(labelq, "OPERATOR CLASS %s",
+                                         fmtId(opcinfo->dobj.name));
+       appendPQExpBuffer(labelq, " USING %s",
+                                         fmtId(amname));
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &opcinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId,
                                 opcinfo->dobj.name,
                                 opcinfo->dobj.namespace->dobj.name,
@@ -9443,12 +9591,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
                                 NULL, NULL);
 
        /* Dump Operator Class Comments */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "OPERATOR CLASS %s",
-                                         fmtId(opcinfo->dobj.name));
-       appendPQExpBuffer(q, " USING %s",
-                                         fmtId(amname));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                NULL, opcinfo->rolname,
                                opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId);
 
@@ -9456,6 +9599,7 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -9471,6 +9615,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delq;
+       PQExpBuffer labelq;
        PGresult   *res;
        PGresult   *res_ops;
        PGresult   *res_procs;
@@ -9514,6 +9659,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(opfinfo->dobj.namespace->dobj.name);
@@ -9622,6 +9768,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
                        destroyPQExpBuffer(query);
                        destroyPQExpBuffer(q);
                        destroyPQExpBuffer(delq);
+                       destroyPQExpBuffer(labelq);
                        return;
                }
 
@@ -9753,6 +9900,14 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
                appendPQExpBuffer(q, ";\n");
        }
 
+       appendPQExpBuffer(labelq, "OPERATOR FAMILY %s",
+                                         fmtId(opfinfo->dobj.name));
+       appendPQExpBuffer(labelq, " USING %s",
+                                         fmtId(amname));
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &opfinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId,
                                 opfinfo->dobj.name,
                                 opfinfo->dobj.namespace->dobj.name,
@@ -9764,12 +9919,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
                                 NULL, NULL);
 
        /* Dump Operator Family Comments */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "OPERATOR FAMILY %s",
-                                         fmtId(opfinfo->dobj.name));
-       appendPQExpBuffer(q, " USING %s",
-                                         fmtId(amname));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                NULL, opfinfo->rolname,
                                opfinfo->dobj.catId, 0, opfinfo->dobj.dumpId);
 
@@ -9779,6 +9929,7 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -9791,7 +9942,7 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delq;
-       PQExpBuffer details;
+       PQExpBuffer labelq;
        PGresult   *res;
        int                     ntups;
        int                     i_conname;
@@ -9812,7 +9963,7 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        query = createPQExpBuffer();
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
-       details = createPQExpBuffer();
+       labelq = createPQExpBuffer();
 
        /* Make sure we are in proper schema */
        selectSourceSchema(convinfo->dobj.namespace->dobj.name);
@@ -9869,6 +10020,11 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        /* regproc is automatically quoted in 7.3 and above */
        appendPQExpBuffer(q, " FROM %s;\n", conproc);
 
+       appendPQExpBuffer(labelq, "CONVERSION %s", fmtId(convinfo->dobj.name));
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &convinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId,
                                 convinfo->dobj.name,
                                 convinfo->dobj.namespace->dobj.name,
@@ -9880,9 +10036,7 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
                                 NULL, NULL);
 
        /* Dump Conversion Comments */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "CONVERSION %s", fmtId(convinfo->dobj.name));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                convinfo->dobj.namespace->dobj.name, convinfo->rolname,
                                convinfo->dobj.catId, 0, convinfo->dobj.dumpId);
 
@@ -9891,7 +10045,7 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
-       destroyPQExpBuffer(details);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -9944,6 +10098,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        PQExpBuffer query;
        PQExpBuffer q;
        PQExpBuffer delq;
+       PQExpBuffer labelq;
        PQExpBuffer details;
        char       *aggsig;
        char       *aggsig_tag;
@@ -9969,6 +10124,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        query = createPQExpBuffer();
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
+       labelq = createPQExpBuffer();
        details = createPQExpBuffer();
 
        /* Make sure we are in proper schema */
@@ -10113,6 +10269,11 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        appendPQExpBuffer(q, "CREATE AGGREGATE %s (\n%s\n);\n",
                                          aggsig, details->data);
 
+       appendPQExpBuffer(labelq, "AGGREGATE %s", aggsig);
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &agginfo->aggfn.dobj, labelq->data);
+
        ArchiveEntry(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
                                 aggsig_tag,
                                 agginfo->aggfn.dobj.namespace->dobj.name,
@@ -10124,12 +10285,10 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
                                 NULL, NULL);
 
        /* Dump Aggregate Comments */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "AGGREGATE %s", aggsig);
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                        agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname,
                                agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
-       dumpSecLabel(fout, q->data,
+       dumpSecLabel(fout, labelq->data,
                        agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname,
                                 agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
 
@@ -10158,6 +10317,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(details);
 }
 
@@ -10170,6 +10330,7 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
 {
        PQExpBuffer q;
        PQExpBuffer delq;
+       PQExpBuffer labelq;
 
        /* Skip if not to be dumped */
        if (!prsinfo->dobj.dump || dataOnly)
@@ -10177,6 +10338,7 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
+       labelq = createPQExpBuffer();
 
        /* Make sure we are in proper schema */
        selectSourceSchema(prsinfo->dobj.namespace->dobj.name);
@@ -10204,6 +10366,12 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
        appendPQExpBuffer(delq, ".%s;\n",
                                          fmtId(prsinfo->dobj.name));
 
+       appendPQExpBuffer(labelq, "TEXT SEARCH PARSER %s",
+                                         fmtId(prsinfo->dobj.name));
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &prsinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId,
                                 prsinfo->dobj.name,
                                 prsinfo->dobj.namespace->dobj.name,
@@ -10215,15 +10383,13 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
                                 NULL, NULL);
 
        /* Dump Parser Comments */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "TEXT SEARCH PARSER %s",
-                                         fmtId(prsinfo->dobj.name));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                NULL, "",
                                prsinfo->dobj.catId, 0, prsinfo->dobj.dumpId);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -10235,6 +10401,7 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
 {
        PQExpBuffer q;
        PQExpBuffer delq;
+       PQExpBuffer labelq;
        PQExpBuffer query;
        PGresult   *res;
        int                     ntups;
@@ -10247,6 +10414,7 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
+       labelq = createPQExpBuffer();
        query = createPQExpBuffer();
 
        /* Fetch name and namespace of the dictionary's template */
@@ -10296,6 +10464,12 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
        appendPQExpBuffer(delq, ".%s;\n",
                                          fmtId(dictinfo->dobj.name));
 
+       appendPQExpBuffer(labelq, "TEXT SEARCH DICTIONARY %s",
+                                         fmtId(dictinfo->dobj.name));
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &dictinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId,
                                 dictinfo->dobj.name,
                                 dictinfo->dobj.namespace->dobj.name,
@@ -10307,15 +10481,13 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
                                 NULL, NULL);
 
        /* Dump Dictionary Comments */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "TEXT SEARCH DICTIONARY %s",
-                                         fmtId(dictinfo->dobj.name));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                NULL, dictinfo->rolname,
                                dictinfo->dobj.catId, 0, dictinfo->dobj.dumpId);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
 }
 
@@ -10328,6 +10500,7 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
 {
        PQExpBuffer q;
        PQExpBuffer delq;
+       PQExpBuffer labelq;
 
        /* Skip if not to be dumped */
        if (!tmplinfo->dobj.dump || dataOnly)
@@ -10335,6 +10508,7 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
+       labelq = createPQExpBuffer();
 
        /* Make sure we are in proper schema */
        selectSourceSchema(tmplinfo->dobj.namespace->dobj.name);
@@ -10356,6 +10530,12 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
        appendPQExpBuffer(delq, ".%s;\n",
                                          fmtId(tmplinfo->dobj.name));
 
+       appendPQExpBuffer(labelq, "TEXT SEARCH TEMPLATE %s",
+                                         fmtId(tmplinfo->dobj.name));
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &tmplinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId,
                                 tmplinfo->dobj.name,
                                 tmplinfo->dobj.namespace->dobj.name,
@@ -10367,15 +10547,13 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
                                 NULL, NULL);
 
        /* Dump Template Comments */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "TEXT SEARCH TEMPLATE %s",
-                                         fmtId(tmplinfo->dobj.name));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                NULL, "",
                                tmplinfo->dobj.catId, 0, tmplinfo->dobj.dumpId);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -10387,6 +10565,7 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
 {
        PQExpBuffer q;
        PQExpBuffer delq;
+       PQExpBuffer labelq;
        PQExpBuffer query;
        PGresult   *res;
        char       *nspname;
@@ -10402,6 +10581,7 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
+       labelq = createPQExpBuffer();
        query = createPQExpBuffer();
 
        /* Fetch name and namespace of the config's parser */
@@ -10489,6 +10669,12 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
        appendPQExpBuffer(delq, ".%s;\n",
                                          fmtId(cfginfo->dobj.name));
 
+       appendPQExpBuffer(labelq, "TEXT SEARCH CONFIGURATION %s",
+                                         fmtId(cfginfo->dobj.name));
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &cfginfo->dobj, labelq->data);
+
        ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId,
                                 cfginfo->dobj.name,
                                 cfginfo->dobj.namespace->dobj.name,
@@ -10500,15 +10686,13 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
                                 NULL, NULL);
 
        /* Dump Configuration Comments */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "TEXT SEARCH CONFIGURATION %s",
-                                         fmtId(cfginfo->dobj.name));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                NULL, cfginfo->rolname,
                                cfginfo->dobj.catId, 0, cfginfo->dobj.dumpId);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
        destroyPQExpBuffer(query);
 }
 
@@ -10521,7 +10705,8 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
 {
        PQExpBuffer q;
        PQExpBuffer delq;
-       char       *namecopy;
+       PQExpBuffer labelq;
+       char       *qfdwname;
 
        /* Skip if not to be dumped */
        if (!fdwinfo->dobj.dump || dataOnly)
@@ -10529,9 +10714,12 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
+       labelq = createPQExpBuffer();
+
+       qfdwname = strdup(fmtId(fdwinfo->dobj.name));
 
        appendPQExpBuffer(q, "CREATE FOREIGN DATA WRAPPER %s",
-                                         fmtId(fdwinfo->dobj.name));
+                                         qfdwname);
 
        if (fdwinfo->fdwvalidator && strcmp(fdwinfo->fdwvalidator, "-") != 0)
                appendPQExpBuffer(q, " VALIDATOR %s",
@@ -10543,7 +10731,13 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
        appendPQExpBuffer(q, ";\n");
 
        appendPQExpBuffer(delq, "DROP FOREIGN DATA WRAPPER %s;\n",
-                                         fmtId(fdwinfo->dobj.name));
+                                         qfdwname);
+
+       appendPQExpBuffer(labelq, "FOREIGN DATA WRAPPER %s",
+                                         qfdwname);
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &fdwinfo->dobj, labelq->data);
 
        ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
                                 fdwinfo->dobj.name,
@@ -10556,16 +10750,17 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
                                 NULL, NULL);
 
        /* Handle the ACL */
-       namecopy = strdup(fmtId(fdwinfo->dobj.name));
        dumpACL(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
                        "FOREIGN DATA WRAPPER",
-                       namecopy, NULL, fdwinfo->dobj.name,
+                       qfdwname, NULL, fdwinfo->dobj.name,
                        NULL, fdwinfo->rolname,
                        fdwinfo->fdwacl);
-       free(namecopy);
+
+       free(qfdwname);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -10577,10 +10772,11 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
 {
        PQExpBuffer q;
        PQExpBuffer delq;
+       PQExpBuffer labelq;
        PQExpBuffer query;
        PGresult   *res;
        int                     ntups;
-       char       *namecopy;
+       char       *qsrvname;
        char       *fdwname;
 
        /* Skip if not to be dumped */
@@ -10589,8 +10785,11 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
+       labelq = createPQExpBuffer();
        query = createPQExpBuffer();
 
+       qsrvname = strdup(fmtId(srvinfo->dobj.name));
+
        /* look up the foreign-data wrapper */
        selectSourceSchema("pg_catalog");
        appendPQExpBuffer(query, "SELECT fdwname "
@@ -10610,7 +10809,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
        }
        fdwname = PQgetvalue(res, 0, 0);
 
-       appendPQExpBuffer(q, "CREATE SERVER %s", fmtId(srvinfo->dobj.name));
+       appendPQExpBuffer(q, "CREATE SERVER %s", qsrvname);
        if (srvinfo->srvtype && strlen(srvinfo->srvtype) > 0)
        {
                appendPQExpBuffer(q, " TYPE ");
@@ -10631,7 +10830,12 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
        appendPQExpBuffer(q, ";\n");
 
        appendPQExpBuffer(delq, "DROP SERVER %s;\n",
-                                         fmtId(srvinfo->dobj.name));
+                                         qsrvname);
+
+       appendPQExpBuffer(labelq, "SERVER %s", qsrvname);
+
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &srvinfo->dobj, labelq->data);
 
        ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
                                 srvinfo->dobj.name,
@@ -10644,13 +10848,11 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
                                 NULL, NULL);
 
        /* Handle the ACL */
-       namecopy = strdup(fmtId(srvinfo->dobj.name));
        dumpACL(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
                        "FOREIGN SERVER",
-                       namecopy, NULL, srvinfo->dobj.name,
+                       qsrvname, NULL, srvinfo->dobj.name,
                        NULL, srvinfo->rolname,
                        srvinfo->srvacl);
-       free(namecopy);
 
        /* Dump user mappings */
        dumpUserMappings(fout,
@@ -10658,8 +10860,11 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
                                         srvinfo->rolname,
                                         srvinfo->dobj.catId, srvinfo->dobj.dumpId);
 
+       free(qsrvname);
+
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -11254,6 +11459,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
        PQExpBuffer query = createPQExpBuffer();
        PQExpBuffer q = createPQExpBuffer();
        PQExpBuffer delq = createPQExpBuffer();
+       PQExpBuffer labelq = createPQExpBuffer();
        PGresult   *res;
        int                     numParents;
        TableInfo **parents;
@@ -11334,6 +11540,9 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                appendPQExpBuffer(q, "CREATE VIEW %s AS\n    %s\n",
                                                  fmtId(tbinfo->dobj.name), viewdef);
 
+               appendPQExpBuffer(labelq, "VIEW %s",
+                                                 fmtId(tbinfo->dobj.name));
+
                PQclear(res);
        }
        else
@@ -11379,6 +11588,9 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                appendPQExpBuffer(delq, "%s;\n",
                                                  fmtId(tbinfo->dobj.name));
 
+               appendPQExpBuffer(labelq, "%s %s", reltypename,
+                                                 fmtId(tbinfo->dobj.name));
+
                if (binary_upgrade)
                        binary_upgrade_set_pg_class_oids(q, tbinfo->dobj.catId.oid, false);
 
@@ -11716,6 +11928,9 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
                }
        }
 
+       if (binary_upgrade)
+               binary_upgrade_extension_member(q, &tbinfo->dobj, labelq->data);
+
        ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
                                 tbinfo->dobj.name,
                                 tbinfo->dobj.namespace->dobj.name,
@@ -11748,6 +11963,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -11847,12 +12063,17 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
        TableInfo  *tbinfo = indxinfo->indextable;
        PQExpBuffer q;
        PQExpBuffer delq;
+       PQExpBuffer labelq;
 
        if (dataOnly)
                return;
 
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
+       labelq = createPQExpBuffer();
+
+       appendPQExpBuffer(labelq, "INDEX %s",
+                                         fmtId(indxinfo->dobj.name));
 
        /*
         * If there's an associated constraint, don't dump the index per se, but
@@ -11897,16 +12118,14 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
        }
 
        /* Dump Index Comments */
-       resetPQExpBuffer(q);
-       appendPQExpBuffer(q, "INDEX %s",
-                                         fmtId(indxinfo->dobj.name));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                tbinfo->dobj.namespace->dobj.name,
                                tbinfo->rolname,
                                indxinfo->dobj.catId, 0, indxinfo->dobj.dumpId);
 
        destroyPQExpBuffer(q);
        destroyPQExpBuffer(delq);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -12150,19 +12369,19 @@ static void
 dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo)
 {
        TableInfo  *tbinfo = coninfo->contable;
-       PQExpBuffer q = createPQExpBuffer();
+       PQExpBuffer labelq = createPQExpBuffer();
 
-       appendPQExpBuffer(q, "CONSTRAINT %s ",
+       appendPQExpBuffer(labelq, "CONSTRAINT %s ",
                                          fmtId(coninfo->dobj.name));
-       appendPQExpBuffer(q, "ON %s",
+       appendPQExpBuffer(labelq, "ON %s",
                                          fmtId(tbinfo->dobj.name));
-       dumpComment(fout, q->data,
+       dumpComment(fout, labelq->data,
                                tbinfo->dobj.namespace->dobj.name,
                                tbinfo->rolname,
                                coninfo->dobj.catId, 0,
                         coninfo->separate ? coninfo->dobj.dumpId : tbinfo->dobj.dumpId);
 
-       destroyPQExpBuffer(q);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -12256,6 +12475,7 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
                                called;
        PQExpBuffer query = createPQExpBuffer();
        PQExpBuffer delqry = createPQExpBuffer();
+       PQExpBuffer labelq = createPQExpBuffer();
 
        /* Make sure we are in proper schema */
        selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
@@ -12343,8 +12563,6 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
         */
        if (!dataOnly)
        {
-               resetPQExpBuffer(delqry);
-
                /*
                 * DROP must be fully qualified in case same name appears in
                 * pg_catalog
@@ -12397,8 +12615,14 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 
                appendPQExpBuffer(query, ";\n");
 
+               appendPQExpBuffer(labelq, "SEQUENCE %s", fmtId(tbinfo->dobj.name));
+
                /* binary_upgrade:      no need to clear TOAST table oid */
 
+               if (binary_upgrade)
+                       binary_upgrade_extension_member(query, &tbinfo->dobj,
+                                                                                       labelq->data);
+
                ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
                                         tbinfo->dobj.name,
                                         tbinfo->dobj.namespace->dobj.name,
@@ -12448,12 +12672,10 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
                }
 
                /* Dump Sequence Comments and Security Labels */
-               resetPQExpBuffer(query);
-               appendPQExpBuffer(query, "SEQUENCE %s", fmtId(tbinfo->dobj.name));
-               dumpComment(fout, query->data,
+               dumpComment(fout, labelq->data,
                                        tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                                        tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
-               dumpSecLabel(fout, query->data,
+               dumpSecLabel(fout, labelq->data,
                                         tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                                         tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
        }
@@ -12481,6 +12703,7 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(delqry);
+       destroyPQExpBuffer(labelq);
 }
 
 static void
@@ -12489,6 +12712,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
        TableInfo  *tbinfo = tginfo->tgtable;
        PQExpBuffer query;
        PQExpBuffer delqry;
+       PQExpBuffer labelq;
        char       *tgargs;
        size_t          lentgargs;
        const char *p;
@@ -12499,6 +12723,7 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
 
        query = createPQExpBuffer();
        delqry = createPQExpBuffer();
+       labelq = createPQExpBuffer();
 
        /*
         * DROP must be fully qualified in case same name appears in pg_catalog
@@ -12659,6 +12884,11 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
                                                  fmtId(tginfo->dobj.name));
        }
 
+       appendPQExpBuffer(labelq, "TRIGGER %s ",
+                                         fmtId(tginfo->dobj.name));
+       appendPQExpBuffer(labelq, "ON %s",
+                                         fmtId(tbinfo->dobj.name));
+
        ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId,
                                 tginfo->dobj.name,
                                 tbinfo->dobj.namespace->dobj.name,
@@ -12669,18 +12899,13 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
                                 tginfo->dobj.dependencies, tginfo->dobj.nDeps,
                                 NULL, NULL);
 
-       resetPQExpBuffer(query);
-       appendPQExpBuffer(query, "TRIGGER %s ",
-                                         fmtId(tginfo->dobj.name));
-       appendPQExpBuffer(query, "ON %s",
-                                         fmtId(tbinfo->dobj.name));
-
-       dumpComment(fout, query->data,
+       dumpComment(fout, labelq->data,
                                tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                                tginfo->dobj.catId, 0, tginfo->dobj.dumpId);
 
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(delqry);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -12694,6 +12919,7 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
        PQExpBuffer query;
        PQExpBuffer cmd;
        PQExpBuffer delcmd;
+       PQExpBuffer labelq;
        PGresult   *res;
 
        /* Skip if not to be dumped */
@@ -12715,6 +12941,7 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
        query = createPQExpBuffer();
        cmd = createPQExpBuffer();
        delcmd = createPQExpBuffer();
+       labelq = createPQExpBuffer();
 
        if (g_fout->remoteVersion >= 70300)
        {
@@ -12779,6 +13006,11 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
        appendPQExpBuffer(delcmd, "%s;\n",
                                          fmtId(tbinfo->dobj.name));
 
+       appendPQExpBuffer(labelq, "RULE %s",
+                                         fmtId(rinfo->dobj.name));
+       appendPQExpBuffer(labelq, " ON %s",
+                                         fmtId(tbinfo->dobj.name));
+
        ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId,
                                 rinfo->dobj.name,
                                 tbinfo->dobj.namespace->dobj.name,
@@ -12790,12 +13022,7 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
                                 NULL, NULL);
 
        /* Dump rule comments */
-       resetPQExpBuffer(query);
-       appendPQExpBuffer(query, "RULE %s",
-                                         fmtId(rinfo->dobj.name));
-       appendPQExpBuffer(query, " ON %s",
-                                         fmtId(tbinfo->dobj.name));
-       dumpComment(fout, query->data,
+       dumpComment(fout, labelq->data,
                                tbinfo->dobj.namespace->dobj.name,
                                tbinfo->rolname,
                                rinfo->dobj.catId, 0, rinfo->dobj.dumpId);
@@ -12805,6 +13032,7 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
        destroyPQExpBuffer(query);
        destroyPQExpBuffer(cmd);
        destroyPQExpBuffer(delcmd);
+       destroyPQExpBuffer(labelq);
 }
 
 /*
@@ -12900,11 +13128,16 @@ getExtensionMembership(ExtensionInfo extinfo[], int numExtensions)
                /* Record dependency so that getDependencies needn't repeat this */
                addObjectDependency(dobj, refdobj->dumpId);
 
+               dobj->ext_member = true;
+
                /*
-                * Mark the member object as not to be dumped.  We still need the
-                * dependency link, to ensure that sorting is done correctly.
+                * Normally, mark the member object as not to be dumped.  But in
+                * binary upgrades, we still dump the members individually, since
+                * the idea is to exactly reproduce the database contents rather
+                * than replace the extension contents with something different.
                 */
-               dobj->dump = false;
+               if (!binary_upgrade)
+                       dobj->dump = false;
        }
 
        PQclear(res);
index 140d02d..69668e9 100644 (file)
@@ -128,6 +128,7 @@ typedef struct _dumpableObject
        char       *name;                       /* object name (should never be NULL) */
        struct _namespaceInfo *namespace;       /* containing namespace, or NULL */
        bool            dump;                   /* true if we want to dump this object */
+       bool            ext_member;             /* true if object is member of extension */
        DumpId     *dependencies;       /* dumpIds of objects this one depends on */
        int                     nDeps;                  /* number of valid dependencies */
        int                     allocDeps;              /* allocated size of dependencies[] */
@@ -144,6 +145,8 @@ typedef struct _extensionInfo
 {
        DumpableObject dobj;
        char       *namespace;          /* schema containing extension's objects */
+       bool            relocatable;
+       char       *extversion;
        char       *extconfig;          /* info about configuration tables */
        char       *extcondition;
 } ExtensionInfo;
index d0e9455..8c07c3a 100644 (file)
@@ -32,6 +32,11 @@ extern void CreateExtension(CreateExtensionStmt *stmt);
 extern void RemoveExtensions(DropStmt *stmt);
 extern void RemoveExtensionById(Oid extId);
 
+extern Oid     InsertExtensionTuple(const char *extName, Oid extOwner,
+                                        Oid schemaOid, bool relocatable, const char *extVersion,
+                                        Datum extConfig, Datum extCondition,
+                                        List *requiredExtensions);
+
 extern void ExecAlterExtensionAddStmt(AlterExtensionAddStmt *stmt);
 
 extern Oid     get_extension_oid(const char *extname, bool missing_ok);