Обсуждение: pg_dump and premature optimizations for objects not to be dumped

Поиск
Список
Период
Сортировка

pg_dump and premature optimizations for objects not to be dumped

От
Tom Lane
Дата:
I looked into Karsten Hilbert's report here
http://www.postgresql.org/message-id/20160108114529.GB22446@hermes.hilbert.loc
of being unable to run pg_upgrade on a database containing the pg_trgm
extension.  After some investigation, the problem is explained like this:

1. Karsten had installed pg_trgm into pg_catalog rather than some user
schema.

2. When getTypes() processes the gtrgm type created by pg_trgm, it
decides the type won't be dumped (cf selectDumpableType, which quite
properly rejects types in pg_catalog).  This causes it not to generate
a ShellTypeInfo subsidiary object.

3. Later, getExtensionMembership decides that we *should* dump gtrgm
and associated I/O routines, since we're in binary-upgrade mode.

4. Later still, repairTypeFuncLoop breaks the dependency loops between
gtrgm and its I/O routines, but it doesn't mark the shell type as dumpable
because there isn't one.

5. So we end up with no shell type being dumped, which does not work
in binary-upgrade mode because we can't create the shell type when
we see the first I/O function; we don't know what OID to give it.


The core of the problem, therefore, is the choice in getTypes to not
create a ShellTypeInfo if it thinks the type is not to be dumped.  That
was probably fine when it was written, but now that we can change our
minds about object dumpability later, it's clearly broken.  It's really
just unnecessary optimization anyway, since if we create the object and
don't use it, we've not wasted much but cycles.  I've verified that a
patch like this:

diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 56c0528..6acbf4a 100644
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
*************** getTypes(Archive *fout, int *numTypes)
*** 3664,3671 ****          * should copy the base type's catId, but then it might capture the          * pg_depend
entriesfor the type, which we don't want.          */
 
!         if (tyinfo[i].dobj.dump && (tyinfo[i].typtype == TYPTYPE_BASE ||
!                                     tyinfo[i].typtype == TYPTYPE_RANGE))         {             stinfo =
(ShellTypeInfo*) pg_malloc(sizeof(ShellTypeInfo));             stinfo->dobj.objType = DO_SHELL_TYPE;
 
--- 3664,3671 ----          * should copy the base type's catId, but then it might capture the          * pg_depend
entriesfor the type, which we don't want.          */
 
!         if (tyinfo[i].typtype == TYPTYPE_BASE ||
!             tyinfo[i].typtype == TYPTYPE_RANGE)         {             stinfo = (ShellTypeInfo *)
pg_malloc(sizeof(ShellTypeInfo));            stinfo->dobj.objType = DO_SHELL_TYPE;
 

fixes Karsten's symptom without obvious other problems.

However ... there are a whole bunch of *other* places where pg_dump
skips work on objects that are not to be dumped, and some of them
would add quite a bit more cost than this one.  An example is just
above this code, where we skip getDomainConstraints() for domains
we think aren't to be dumped.  A fix for that wouldn't be a one-liner
either, because if we do pull in the domain's constraints unconditionally,
we'd have to do something to cause the domain's own dumpability flag
(and updates thereof) to get propagated to them.

Even if we fix all these issues today, it's not hard to imagine new bugs
of similar ilk sneaking in.  Exacerbating this is that some of those
checks are fine because they occur after getExtensionMembership(), at
which point the dump-or-not decisions won't change.  But in most places
in pg_dump, it's not instantly obvious whether you're looking at a flag
that is still subject to change or not.

The thing that seems possibly most robust to me is to pull in the
extension membership data *first* and incorporate it into the initial
selectDumpableObject tests, thus getting us back to the pre-9.1 state
of affairs where the initial settings of the object dump flags could
be trusted.  This might be expensive though; and it would certainly add
a good chunk of work to the race-condition window where we've taken
pg_dump's transaction snapshot but not yet acquired lock on any of
the tables.

Thoughts?  Anybody have another idea about what to do about this?
        regards, tom lane



Re: pg_dump and premature optimizations for objects not to be dumped

От
Tom Lane
Дата:
I wrote:
> I looked into Karsten Hilbert's report here
> http://www.postgresql.org/message-id/20160108114529.GB22446@hermes.hilbert.loc
> of being unable to run pg_upgrade on a database containing the pg_trgm
> extension.  After some investigation, the problem is explained like this:
> ...
> The thing that seems possibly most robust to me is to pull in the
> extension membership data *first* and incorporate it into the initial
> selectDumpableObject tests, thus getting us back to the pre-9.1 state
> of affairs where the initial settings of the object dump flags could
> be trusted.  This might be expensive though; and it would certainly add
> a good chunk of work to the race-condition window where we've taken
> pg_dump's transaction snapshot but not yet acquired lock on any of
> the tables.

Attached is a draft patch that does things this way.  Some simple testing
suggests it's just about exactly the same speed as 9.5 pg_dump, which
means that the "expensive" objection is dismissible.  It's hard to tell
though whether the pre-table-lock race-condition window has gotten
meaningfully wider.

In addition to fixing Karsten's problem, this deals with the bugs I noted
earlier about event triggers and transforms being dumped unconditionally.

I was also able to get rid of some unsightly special cases for procedural
languages, FDWs, and foreign servers, in favor of setting their dump
flags according to standard rules up front.

If we were to put a test rejecting initdb-created objects (those with
OID < FirstNormalObjectId) into selectDumpableObject, it'd be possible
to get rid of selectDumpableDefaultACL, selectDumpableCast, and/or
selectDumpableProcLang, since those would then have various subsets
of the selectDumpableObject rules.  I'm not sure if this would be an
improvement or just confusing; any thoughts?

I'm not very sure what to do with this patch.  I think it should
definitely go into 9.5: it applies cleanly there and it will fix our two
new-in-9.5 bugs with event triggers and transforms.  I'm less enthused
about back-porting it further.  In principle, the extension membership
issues exist all the way back to 9.1, but we haven't had complaints before,
and there's a nonzero chance of changing corner-case behaviors.  (I think
any such changes would likely be for the better, but nonetheless they
would be changes.)  Back-porting it further than about 9.4 would also
be quite a lot of work :-(

Comments?

            regards, tom lane

diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 7869ee9..ded14f3 100644
*** a/src/bin/pg_dump/common.c
--- b/src/bin/pg_dump/common.c
*************** static int    numCatalogIds = 0;
*** 40,69 ****

  /*
   * These variables are static to avoid the notational cruft of having to pass
!  * them into findTableByOid() and friends.  For each of these arrays, we
!  * build a sorted-by-OID index array immediately after it's built, and then
!  * we use binary search in findTableByOid() and friends.  (qsort'ing the base
!  * arrays themselves would be simpler, but it doesn't work because pg_dump.c
!  * may have already established pointers between items.)
   */
- static TableInfo *tblinfo;
- static TypeInfo *typinfo;
- static FuncInfo *funinfo;
- static OprInfo *oprinfo;
- static NamespaceInfo *nspinfo;
- static int    numTables;
- static int    numTypes;
- static int    numFuncs;
- static int    numOperators;
- static int    numCollations;
- static int    numNamespaces;
  static DumpableObject **tblinfoindex;
  static DumpableObject **typinfoindex;
  static DumpableObject **funinfoindex;
  static DumpableObject **oprinfoindex;
  static DumpableObject **collinfoindex;
  static DumpableObject **nspinfoindex;


  static void flagInhTables(TableInfo *tbinfo, int numTables,
                InhInfo *inhinfo, int numInherits);
--- 40,69 ----

  /*
   * These variables are static to avoid the notational cruft of having to pass
!  * them into findTableByOid() and friends.  For each of these arrays, we build
!  * a sorted-by-OID index array immediately after the objects are fetched,
!  * and then we use binary search in findTableByOid() and friends.  (qsort'ing
!  * the object arrays themselves would be simpler, but it doesn't work because
!  * pg_dump.c may have already established pointers between items.)
   */
  static DumpableObject **tblinfoindex;
  static DumpableObject **typinfoindex;
  static DumpableObject **funinfoindex;
  static DumpableObject **oprinfoindex;
  static DumpableObject **collinfoindex;
  static DumpableObject **nspinfoindex;
+ static DumpableObject **extinfoindex;
+ static int    numTables;
+ static int    numTypes;
+ static int    numFuncs;
+ static int    numOperators;
+ static int    numCollations;
+ static int    numNamespaces;
+ static int    numExtensions;

+ /* This is an array of object identities, not actual DumpableObjects */
+ static ExtensionMemberId *extmembers;
+ static int    numextmembers;

  static void flagInhTables(TableInfo *tbinfo, int numTables,
                InhInfo *inhinfo, int numInherits);
*************** static void flagInhAttrs(DumpOptions *do
*** 71,76 ****
--- 71,77 ----
  static DumpableObject **buildIndexArray(void *objArray, int numObjs,
                  Size objSize);
  static int    DOCatalogIdCompare(const void *p1, const void *p2);
+ static int    ExtensionMemberIdCompare(const void *p1, const void *p2);
  static void findParentsByOid(TableInfo *self,
                   InhInfo *inhinfo, int numInherits);
  static int    strInArray(const char *pattern, char **arr, int arr_size);
*************** static int    strInArray(const char *patter
*** 83,92 ****
  TableInfo *
  getSchemaData(Archive *fout, DumpOptions *dopt, int *numTablesPtr)
  {
      ExtensionInfo *extinfo;
      InhInfo    *inhinfo;
-     CollInfo   *collinfo;
-     int            numExtensions;
      int            numAggregates;
      int            numInherits;
      int            numRules;
--- 84,97 ----
  TableInfo *
  getSchemaData(Archive *fout, DumpOptions *dopt, int *numTablesPtr)
  {
+     TableInfo  *tblinfo;
+     TypeInfo   *typinfo;
+     FuncInfo   *funinfo;
+     OprInfo    *oprinfo;
+     CollInfo   *collinfo;
+     NamespaceInfo *nspinfo;
      ExtensionInfo *extinfo;
      InhInfo    *inhinfo;
      int            numAggregates;
      int            numInherits;
      int            numRules;
*************** getSchemaData(Archive *fout, DumpOptions
*** 105,113 ****
      int            numDefaultACLs;
      int            numEventTriggers;

      if (g_verbose)
          write_msg(NULL, "reading schemas\n");
!     nspinfo = getNamespaces(fout, &numNamespaces);
      nspinfoindex = buildIndexArray(nspinfo, numNamespaces, sizeof(NamespaceInfo));

      /*
--- 110,132 ----
      int            numDefaultACLs;
      int            numEventTriggers;

+     /*
+      * We must read extensions and extension membership info first, because
+      * extension membership needs to be consultable during decisions about
+      * whether other objects are to be dumped.
+      */
+     if (g_verbose)
+         write_msg(NULL, "reading extensions\n");
+     extinfo = getExtensions(fout, dopt, &numExtensions);
+     extinfoindex = buildIndexArray(extinfo, numExtensions, sizeof(ExtensionInfo));
+
+     if (g_verbose)
+         write_msg(NULL, "identifying extension members\n");
+     getExtensionMembership(fout, dopt, extinfo, numExtensions);
+
      if (g_verbose)
          write_msg(NULL, "reading schemas\n");
!     nspinfo = getNamespaces(fout, dopt, &numNamespaces);
      nspinfoindex = buildIndexArray(nspinfo, numNamespaces, sizeof(NamespaceInfo));

      /*
*************** getSchemaData(Archive *fout, DumpOptions
*** 125,134 ****
      getOwnedSeqs(fout, tblinfo, numTables);

      if (g_verbose)
-         write_msg(NULL, "reading extensions\n");
-     extinfo = getExtensions(fout, dopt, &numExtensions);
-
-     if (g_verbose)
          write_msg(NULL, "reading user-defined functions\n");
      funinfo = getFuncs(fout, dopt, &numFuncs);
      funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo));
--- 144,149 ----
*************** getSchemaData(Archive *fout, DumpOptions
*** 136,148 ****
      /* this must be after getTables and getFuncs */
      if (g_verbose)
          write_msg(NULL, "reading user-defined types\n");
!     typinfo = getTypes(fout, &numTypes);
      typinfoindex = buildIndexArray(typinfo, numTypes, sizeof(TypeInfo));

      /* this must be after getFuncs, too */
      if (g_verbose)
          write_msg(NULL, "reading procedural languages\n");
!     getProcLangs(fout, &numProcLangs);

      if (g_verbose)
          write_msg(NULL, "reading user-defined aggregate functions\n");
--- 151,163 ----
      /* this must be after getTables and getFuncs */
      if (g_verbose)
          write_msg(NULL, "reading user-defined types\n");
!     typinfo = getTypes(fout, dopt, &numTypes);
      typinfoindex = buildIndexArray(typinfo, numTypes, sizeof(TypeInfo));

      /* this must be after getFuncs, too */
      if (g_verbose)
          write_msg(NULL, "reading procedural languages\n");
!     getProcLangs(fout, dopt, &numProcLangs);

      if (g_verbose)
          write_msg(NULL, "reading user-defined aggregate functions\n");
*************** getSchemaData(Archive *fout, DumpOptions
*** 150,189 ****

      if (g_verbose)
          write_msg(NULL, "reading user-defined operators\n");
!     oprinfo = getOperators(fout, &numOperators);
      oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo));

      if (g_verbose)
          write_msg(NULL, "reading user-defined operator classes\n");
!     getOpclasses(fout, &numOpclasses);

      if (g_verbose)
          write_msg(NULL, "reading user-defined operator families\n");
!     getOpfamilies(fout, &numOpfamilies);

      if (g_verbose)
          write_msg(NULL, "reading user-defined text search parsers\n");
!     getTSParsers(fout, &numTSParsers);

      if (g_verbose)
          write_msg(NULL, "reading user-defined text search templates\n");
!     getTSTemplates(fout, &numTSTemplates);

      if (g_verbose)
          write_msg(NULL, "reading user-defined text search dictionaries\n");
!     getTSDictionaries(fout, &numTSDicts);

      if (g_verbose)
          write_msg(NULL, "reading user-defined text search configurations\n");
!     getTSConfigurations(fout, &numTSConfigs);

      if (g_verbose)
          write_msg(NULL, "reading user-defined foreign-data wrappers\n");
!     getForeignDataWrappers(fout, &numForeignDataWrappers);

      if (g_verbose)
          write_msg(NULL, "reading user-defined foreign servers\n");
!     getForeignServers(fout, &numForeignServers);

      if (g_verbose)
          write_msg(NULL, "reading default privileges\n");
--- 165,204 ----

      if (g_verbose)
          write_msg(NULL, "reading user-defined operators\n");
!     oprinfo = getOperators(fout, dopt, &numOperators);
      oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo));

      if (g_verbose)
          write_msg(NULL, "reading user-defined operator classes\n");
!     getOpclasses(fout, dopt, &numOpclasses);

      if (g_verbose)
          write_msg(NULL, "reading user-defined operator families\n");
!     getOpfamilies(fout, dopt, &numOpfamilies);

      if (g_verbose)
          write_msg(NULL, "reading user-defined text search parsers\n");
!     getTSParsers(fout, dopt, &numTSParsers);

      if (g_verbose)
          write_msg(NULL, "reading user-defined text search templates\n");
!     getTSTemplates(fout, dopt, &numTSTemplates);

      if (g_verbose)
          write_msg(NULL, "reading user-defined text search dictionaries\n");
!     getTSDictionaries(fout, dopt, &numTSDicts);

      if (g_verbose)
          write_msg(NULL, "reading user-defined text search configurations\n");
!     getTSConfigurations(fout, dopt, &numTSConfigs);

      if (g_verbose)
          write_msg(NULL, "reading user-defined foreign-data wrappers\n");
!     getForeignDataWrappers(fout, dopt, &numForeignDataWrappers);

      if (g_verbose)
          write_msg(NULL, "reading user-defined foreign servers\n");
!     getForeignServers(fout, dopt, &numForeignServers);

      if (g_verbose)
          write_msg(NULL, "reading default privileges\n");
*************** getSchemaData(Archive *fout, DumpOptions
*** 191,202 ****

      if (g_verbose)
          write_msg(NULL, "reading user-defined collations\n");
!     collinfo = getCollations(fout, &numCollations);
      collinfoindex = buildIndexArray(collinfo, numCollations, sizeof(CollInfo));

      if (g_verbose)
          write_msg(NULL, "reading user-defined conversions\n");
!     getConversions(fout, &numConversions);

      if (g_verbose)
          write_msg(NULL, "reading type casts\n");
--- 206,217 ----

      if (g_verbose)
          write_msg(NULL, "reading user-defined collations\n");
!     collinfo = getCollations(fout, dopt, &numCollations);
      collinfoindex = buildIndexArray(collinfo, numCollations, sizeof(CollInfo));

      if (g_verbose)
          write_msg(NULL, "reading user-defined conversions\n");
!     getConversions(fout, dopt, &numConversions);

      if (g_verbose)
          write_msg(NULL, "reading type casts\n");
*************** getSchemaData(Archive *fout, DumpOptions
*** 204,210 ****

      if (g_verbose)
          write_msg(NULL, "reading transforms\n");
!     getTransforms(fout, &numTransforms);

      if (g_verbose)
          write_msg(NULL, "reading table inheritance information\n");
--- 219,225 ----

      if (g_verbose)
          write_msg(NULL, "reading transforms\n");
!     getTransforms(fout, dopt, &numTransforms);

      if (g_verbose)
          write_msg(NULL, "reading table inheritance information\n");
*************** getSchemaData(Archive *fout, DumpOptions
*** 212,227 ****

      if (g_verbose)
          write_msg(NULL, "reading event triggers\n");
!     getEventTriggers(fout, &numEventTriggers);

!     /*
!      * Identify extension member objects and mark them as not to be dumped.
!      * This must happen after reading all objects that can be direct members
!      * of extensions, but before we begin to process table subsidiary objects.
!      */
      if (g_verbose)
!         write_msg(NULL, "finding extension members\n");
!     getExtensionMembership(fout, dopt, extinfo, numExtensions);

      /* Link tables to parents, mark parents of target tables interesting */
      if (g_verbose)
--- 227,238 ----

      if (g_verbose)
          write_msg(NULL, "reading event triggers\n");
!     getEventTriggers(fout, dopt, &numEventTriggers);

!     /* Identify extension configuration tables that should be dumped */
      if (g_verbose)
!         write_msg(NULL, "finding extension tables\n");
!     processExtensionTables(fout, dopt, extinfo, numExtensions);

      /* Link tables to parents, mark parents of target tables interesting */
      if (g_verbose)
*************** findNamespaceByOid(Oid oid)
*** 764,769 ****
--- 775,867 ----
      return (NamespaceInfo *) findObjectByOid(oid, nspinfoindex, numNamespaces);
  }

+ /*
+  * findExtensionByOid
+  *      finds the entry (in extinfo) of the extension with the given oid
+  *      returns NULL if not found
+  */
+ ExtensionInfo *
+ findExtensionByOid(Oid oid)
+ {
+     return (ExtensionInfo *) findObjectByOid(oid, extinfoindex, numExtensions);
+ }
+
+
+ /*
+  * setExtensionMembership
+  *      accept and save data about which objects belong to extensions
+  */
+ void
+ setExtensionMembership(ExtensionMemberId *extmems, int nextmems)
+ {
+     /* Sort array in preparation for binary searches */
+     if (nextmems > 1)
+         qsort((void *) extmems, nextmems, sizeof(ExtensionMemberId),
+               ExtensionMemberIdCompare);
+     /* And save */
+     extmembers = extmems;
+     numextmembers = nextmems;
+ }
+
+ /*
+  * findOwningExtension
+  *      return owning extension for specified catalog ID, or NULL if none
+  */
+ ExtensionInfo *
+ findOwningExtension(CatalogId catalogId)
+ {
+     ExtensionMemberId *low;
+     ExtensionMemberId *high;
+
+     /*
+      * We could use bsearch() here, but the notational cruft of calling
+      * bsearch is nearly as bad as doing it ourselves; and the generalized
+      * bsearch function is noticeably slower as well.
+      */
+     if (numextmembers <= 0)
+         return NULL;
+     low = extmembers;
+     high = extmembers + (numextmembers - 1);
+     while (low <= high)
+     {
+         ExtensionMemberId *middle;
+         int            difference;
+
+         middle = low + (high - low) / 2;
+         /* comparison must match ExtensionMemberIdCompare, below */
+         difference = oidcmp(middle->catId.oid, catalogId.oid);
+         if (difference == 0)
+             difference = oidcmp(middle->catId.tableoid, catalogId.tableoid);
+         if (difference == 0)
+             return middle->ext;
+         else if (difference < 0)
+             low = middle + 1;
+         else
+             high = middle - 1;
+     }
+     return NULL;
+ }
+
+ /*
+  * qsort comparator for ExtensionMemberIds
+  */
+ static int
+ ExtensionMemberIdCompare(const void *p1, const void *p2)
+ {
+     const ExtensionMemberId *obj1 = (const ExtensionMemberId *) p1;
+     const ExtensionMemberId *obj2 = (const ExtensionMemberId *) p2;
+     int            cmpval;
+
+     /*
+      * Compare OID first since it's usually unique, whereas there will only be
+      * a few distinct values of tableoid.
+      */
+     cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid);
+     if (cmpval == 0)
+         cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid);
+     return cmpval;
+ }
+

  /*
   * findParentsByOid
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 56c0528..ba14fe1 100644
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
*************** expand_table_name_patterns(Archive *fout
*** 1250,1261 ****
  }

  /*
   * selectDumpableNamespace: policy-setting subroutine
   *        Mark a namespace as to be dumped or not
   */
  static void
! selectDumpableNamespace(NamespaceInfo *nsinfo)
  {
      /*
       * If specific tables are being dumped, do not dump any complete
       * namespaces. If specific namespaces are being dumped, dump just those
--- 1250,1302 ----
  }

  /*
+  * checkExtensionMembership
+  *        Determine whether object is an extension member, and if so,
+  *        record an appropriate dependency and set the object's dump flag.
+  *
+  * It's important to call this for each object that could be an extension
+  * member.  Generally, we integrate this with determining the object's
+  * to-be-dumped-ness, since extension membership overrides other rules for that.
+  *
+  * Returns true if object is an extension member, else false.
+  */
+ static bool
+ checkExtensionMembership(DumpableObject *dobj, DumpOptions *dopt)
+ {
+     ExtensionInfo *ext = findOwningExtension(dobj->catId);
+
+     if (ext == NULL)
+         return false;
+
+     dobj->ext_member = true;
+
+     /* Record dependency so that getDependencies needn't deal with that */
+     addObjectDependency(dobj, ext->dobj.dumpId);
+
+     /*
+      * 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.
+      */
+     if (!dopt->binary_upgrade)
+         dobj->dump = false;
+     else
+         dobj->dump = ext->dobj.dump;
+
+     return true;
+ }
+
+ /*
   * selectDumpableNamespace: policy-setting subroutine
   *        Mark a namespace as to be dumped or not
   */
  static void
! selectDumpableNamespace(NamespaceInfo *nsinfo, DumpOptions *dopt)
  {
+     if (checkExtensionMembership(&nsinfo->dobj, dopt))
+         return;                    /* extension membership overrides all else */
+
      /*
       * If specific tables are being dumped, do not dump any complete
       * namespaces. If specific namespaces are being dumped, dump just those
*************** selectDumpableNamespace(NamespaceInfo *n
*** 1286,1293 ****
   *        Mark a table as to be dumped or not
   */
  static void
! selectDumpableTable(TableInfo *tbinfo)
  {
      /*
       * If specific tables are being dumped, dump just those tables; else, dump
       * according to the parent namespace's dump flag.
--- 1327,1337 ----
   *        Mark a table as to be dumped or not
   */
  static void
! selectDumpableTable(TableInfo *tbinfo, DumpOptions *dopt)
  {
+     if (checkExtensionMembership(&tbinfo->dobj, dopt))
+         return;                    /* extension membership overrides all else */
+
      /*
       * If specific tables are being dumped, dump just those tables; else, dump
       * according to the parent namespace's dump flag.
*************** selectDumpableTable(TableInfo *tbinfo)
*** 1321,1327 ****
   * object (the table or base type).
   */
  static void
! selectDumpableType(TypeInfo *tyinfo)
  {
      /* skip complex types, except for standalone composite types */
      if (OidIsValid(tyinfo->typrelid) &&
--- 1365,1371 ----
   * object (the table or base type).
   */
  static void
! selectDumpableType(TypeInfo *tyinfo, DumpOptions *dopt)
  {
      /* skip complex types, except for standalone composite types */
      if (OidIsValid(tyinfo->typrelid) &&
*************** selectDumpableType(TypeInfo *tyinfo)
*** 1350,1355 ****
--- 1394,1402 ----
           */
      }

+     if (checkExtensionMembership(&tyinfo->dobj, dopt))
+         return;                    /* extension membership overrides all else */
+
      /* dump only types in dumpable namespaces */
      if (!tyinfo->dobj.namespace->dobj.dump)
          tyinfo->dobj.dump = false;
*************** selectDumpableType(TypeInfo *tyinfo)
*** 1366,1373 ****
   * and aclsSkip are checked separately.
   */
  static void
! selectDumpableDefaultACL(DumpOptions *dopt, DefaultACLInfo *dinfo)
  {
      if (dinfo->dobj.namespace)
          dinfo->dobj.dump = dinfo->dobj.namespace->dobj.dump;
      else
--- 1413,1422 ----
   * and aclsSkip are checked separately.
   */
  static void
! selectDumpableDefaultACL(DefaultACLInfo *dinfo, DumpOptions *dopt)
  {
+     /* Default ACLs can't be extension members */
+
      if (dinfo->dobj.namespace)
          dinfo->dobj.dump = dinfo->dobj.namespace->dobj.dump;
      else
*************** selectDumpableDefaultACL(DumpOptions *do
*** 1384,1391 ****
   * OID is in the range reserved for initdb.
   */
  static void
! selectDumpableCast(DumpOptions *dopt, CastInfo *cast)
  {
      if (cast->dobj.catId.oid < (Oid) FirstNormalObjectId)
          cast->dobj.dump = false;
      else
--- 1433,1443 ----
   * OID is in the range reserved for initdb.
   */
  static void
! selectDumpableCast(CastInfo *cast, DumpOptions *dopt)
  {
+     if (checkExtensionMembership(&cast->dobj, dopt))
+         return;                    /* extension membership overrides all else */
+
      if (cast->dobj.catId.oid < (Oid) FirstNormalObjectId)
          cast->dobj.dump = false;
      else
*************** selectDumpableCast(DumpOptions *dopt, Ca
*** 1393,1398 ****
--- 1445,1470 ----
  }

  /*
+  * selectDumpableProcLang: policy-setting subroutine
+  *        Mark a procedural language as to be dumped or not
+  *
+  * Procedural languages do not belong to any particular namespace.  To
+  * identify built-in languages, we must resort to checking whether the
+  * language's OID is in the range reserved for initdb.
+  */
+ static void
+ selectDumpableProcLang(ProcLangInfo *plang, DumpOptions *dopt)
+ {
+     if (checkExtensionMembership(&plang->dobj, dopt))
+         return;                    /* extension membership overrides all else */
+
+     if (plang->dobj.catId.oid < (Oid) FirstNormalObjectId)
+         plang->dobj.dump = false;
+     else
+         plang->dobj.dump = dopt->include_everything;
+ }
+
+ /*
   * selectDumpableExtension: policy-setting subroutine
   *        Mark an extension as to be dumped or not
   *
*************** selectDumpableCast(DumpOptions *dopt, Ca
*** 1403,1409 ****
   * such extensions by their having OIDs in the range reserved for initdb.
   */
  static void
! selectDumpableExtension(DumpOptions *dopt, ExtensionInfo *extinfo)
  {
      if (dopt->binary_upgrade && extinfo->dobj.catId.oid < (Oid) FirstNormalObjectId)
          extinfo->dobj.dump = false;
--- 1475,1481 ----
   * such extensions by their having OIDs in the range reserved for initdb.
   */
  static void
! selectDumpableExtension(ExtensionInfo *extinfo, DumpOptions *dopt)
  {
      if (dopt->binary_upgrade && extinfo->dobj.catId.oid < (Oid) FirstNormalObjectId)
          extinfo->dobj.dump = false;
*************** selectDumpableExtension(DumpOptions *dop
*** 1418,1433 ****
   * Use this only for object types without a special-case routine above.
   */
  static void
! selectDumpableObject(DumpableObject *dobj)
  {
      /*
!      * Default policy is to dump if parent namespace is dumpable, or always
!      * for non-namespace-associated items.
       */
      if (dobj->namespace)
          dobj->dump = dobj->namespace->dobj.dump;
      else
!         dobj->dump = true;
  }

  /*
--- 1490,1508 ----
   * Use this only for object types without a special-case routine above.
   */
  static void
! selectDumpableObject(DumpableObject *dobj, DumpOptions *dopt)
  {
+     if (checkExtensionMembership(dobj, dopt))
+         return;                    /* extension membership overrides all else */
+
      /*
!      * Default policy is to dump if parent namespace is dumpable, or for
!      * non-namespace-associated items, dump if we're dumping "everything".
       */
      if (dobj->namespace)
          dobj->dump = dobj->namespace->dobj.dump;
      else
!         dobj->dump = dopt->include_everything;
  }

  /*
*************** binary_upgrade_extension_member(PQExpBuf
*** 3248,3254 ****
   *    numNamespaces is set to the number of namespaces read in
   */
  NamespaceInfo *
! getNamespaces(Archive *fout, int *numNamespaces)
  {
      PGresult   *res;
      int            ntups;
--- 3323,3329 ----
   *    numNamespaces is set to the number of namespaces read in
   */
  NamespaceInfo *
! getNamespaces(Archive *fout, DumpOptions *dopt, int *numNamespaces)
  {
      PGresult   *res;
      int            ntups;
*************** getNamespaces(Archive *fout, int *numNam
*** 3277,3283 ****
          nsinfo[0].rolname = pg_strdup("");
          nsinfo[0].nspacl = pg_strdup("");

!         selectDumpableNamespace(&nsinfo[0]);

          nsinfo[1].dobj.objType = DO_NAMESPACE;
          nsinfo[1].dobj.catId.tableoid = 0;
--- 3352,3358 ----
          nsinfo[0].rolname = pg_strdup("");
          nsinfo[0].nspacl = pg_strdup("");

!         selectDumpableNamespace(&nsinfo[0], dopt);

          nsinfo[1].dobj.objType = DO_NAMESPACE;
          nsinfo[1].dobj.catId.tableoid = 0;
*************** getNamespaces(Archive *fout, int *numNam
*** 3287,3293 ****
          nsinfo[1].rolname = pg_strdup("");
          nsinfo[1].nspacl = pg_strdup("");

!         selectDumpableNamespace(&nsinfo[1]);

          *numNamespaces = 2;

--- 3362,3368 ----
          nsinfo[1].rolname = pg_strdup("");
          nsinfo[1].nspacl = pg_strdup("");

!         selectDumpableNamespace(&nsinfo[1], dopt);

          *numNamespaces = 2;

*************** getNamespaces(Archive *fout, int *numNam
*** 3331,3337 ****
          nsinfo[i].nspacl = pg_strdup(PQgetvalue(res, i, i_nspacl));

          /* Decide whether to dump this namespace */
!         selectDumpableNamespace(&nsinfo[i]);

          if (strlen(nsinfo[i].rolname) == 0)
              write_msg(NULL, "WARNING: owner of schema \"%s\" appears to be invalid\n",
--- 3406,3412 ----
          nsinfo[i].nspacl = pg_strdup(PQgetvalue(res, i, i_nspacl));

          /* Decide whether to dump this namespace */
!         selectDumpableNamespace(&nsinfo[i], dopt);

          if (strlen(nsinfo[i].rolname) == 0)
              write_msg(NULL, "WARNING: owner of schema \"%s\" appears to be invalid\n",
*************** getExtensions(Archive *fout, DumpOptions
*** 3454,3460 ****
          extinfo[i].extcondition = pg_strdup(PQgetvalue(res, i, i_extcondition));

          /* Decide whether we want to dump it */
!         selectDumpableExtension(dopt, &(extinfo[i]));
      }

      PQclear(res);
--- 3529,3535 ----
          extinfo[i].extcondition = pg_strdup(PQgetvalue(res, i, i_extcondition));

          /* Decide whether we want to dump it */
!         selectDumpableExtension(&(extinfo[i]), dopt);
      }

      PQclear(res);
*************** getExtensions(Archive *fout, DumpOptions
*** 3476,3482 ****
   * findFuncByOid().
   */
  TypeInfo *
! getTypes(Archive *fout, int *numTypes)
  {
      PGresult   *res;
      int            ntups;
--- 3551,3557 ----
   * findFuncByOid().
   */
  TypeInfo *
! getTypes(Archive *fout, DumpOptions *dopt, int *numTypes)
  {
      PGresult   *res;
      int            ntups;
*************** getTypes(Archive *fout, int *numTypes)
*** 3644,3650 ****
              tyinfo[i].isArray = false;

          /* Decide whether we want to dump it */
!         selectDumpableType(&tyinfo[i]);

          /*
           * If it's a domain, fetch info about its constraints, if any
--- 3719,3725 ----
              tyinfo[i].isArray = false;

          /* Decide whether we want to dump it */
!         selectDumpableType(&tyinfo[i], dopt);

          /*
           * If it's a domain, fetch info about its constraints, if any
*************** getTypes(Archive *fout, int *numTypes)
*** 3748,3754 ****
   *    numOprs is set to the number of operators read in
   */
  OprInfo *
! getOperators(Archive *fout, int *numOprs)
  {
      PGresult   *res;
      int            ntups;
--- 3823,3829 ----
   *    numOprs is set to the number of operators read in
   */
  OprInfo *
! getOperators(Archive *fout, DumpOptions *dopt, int *numOprs)
  {
      PGresult   *res;
      int            ntups;
*************** getOperators(Archive *fout, int *numOprs
*** 3835,3841 ****
          oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(oprinfo[i].dobj));

          if (strlen(oprinfo[i].rolname) == 0)
              write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
--- 3910,3916 ----
          oprinfo[i].oprcode = atooid(PQgetvalue(res, i, i_oprcode));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(oprinfo[i].dobj), dopt);

          if (strlen(oprinfo[i].rolname) == 0)
              write_msg(NULL, "WARNING: owner of operator \"%s\" appears to be invalid\n",
*************** getOperators(Archive *fout, int *numOprs
*** 3857,3863 ****
   *    numCollations is set to the number of collations read in
   */
  CollInfo *
! getCollations(Archive *fout, int *numCollations)
  {
      PGresult   *res;
      int            ntups;
--- 3932,3938 ----
   *    numCollations is set to the number of collations read in
   */
  CollInfo *
! getCollations(Archive *fout, DumpOptions *dopt, int *numCollations)
  {
      PGresult   *res;
      int            ntups;
*************** getCollations(Archive *fout, int *numCol
*** 3920,3926 ****
          collinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(collinfo[i].dobj));
      }

      PQclear(res);
--- 3995,4001 ----
          collinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(collinfo[i].dobj), dopt);
      }

      PQclear(res);
*************** getCollations(Archive *fout, int *numCol
*** 3938,3944 ****
   *    numConversions is set to the number of conversions read in
   */
  ConvInfo *
! getConversions(Archive *fout, int *numConversions)
  {
      PGresult   *res;
      int            ntups;
--- 4013,4019 ----
   *    numConversions is set to the number of conversions read in
   */
  ConvInfo *
! getConversions(Archive *fout, DumpOptions *dopt, int *numConversions)
  {
      PGresult   *res;
      int            ntups;
*************** getConversions(Archive *fout, int *numCo
*** 4001,4007 ****
          convinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(convinfo[i].dobj));
      }

      PQclear(res);
--- 4076,4082 ----
          convinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(convinfo[i].dobj), dopt);
      }

      PQclear(res);
*************** getConversions(Archive *fout, int *numCo
*** 4019,4025 ****
   *    numOpclasses is set to the number of opclasses read in
   */
  OpclassInfo *
! getOpclasses(Archive *fout, int *numOpclasses)
  {
      PGresult   *res;
      int            ntups;
--- 4094,4100 ----
   *    numOpclasses is set to the number of opclasses read in
   */
  OpclassInfo *
! getOpclasses(Archive *fout, DumpOptions *dopt, int *numOpclasses)
  {
      PGresult   *res;
      int            ntups;
*************** getOpclasses(Archive *fout, int *numOpcl
*** 4092,4098 ****
          opcinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(opcinfo[i].dobj));

          if (fout->remoteVersion >= 70300)
          {
--- 4167,4173 ----
          opcinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(opcinfo[i].dobj), dopt);

          if (fout->remoteVersion >= 70300)
          {
*************** getOpclasses(Archive *fout, int *numOpcl
*** 4117,4123 ****
   *    numOpfamilies is set to the number of opfamilies read in
   */
  OpfamilyInfo *
! getOpfamilies(Archive *fout, int *numOpfamilies)
  {
      PGresult   *res;
      int            ntups;
--- 4192,4198 ----
   *    numOpfamilies is set to the number of opfamilies read in
   */
  OpfamilyInfo *
! getOpfamilies(Archive *fout, DumpOptions *dopt, int *numOpfamilies)
  {
      PGresult   *res;
      int            ntups;
*************** getOpfamilies(Archive *fout, int *numOpf
*** 4180,4186 ****
          opfinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(opfinfo[i].dobj));

          if (fout->remoteVersion >= 70300)
          {
--- 4255,4261 ----
          opfinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(opfinfo[i].dobj), dopt);

          if (fout->remoteVersion >= 70300)
          {
*************** getAggregates(Archive *fout, DumpOptions
*** 4344,4350 ****
          }

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(agginfo[i].aggfn.dobj));
      }

      PQclear(res);
--- 4419,4425 ----
          }

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(agginfo[i].aggfn.dobj), dopt);
      }

      PQclear(res);
*************** getFuncs(Archive *fout, DumpOptions *dop
*** 4501,4507 ****
          }

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(finfo[i].dobj));

          if (strlen(finfo[i].rolname) == 0)
              write_msg(NULL,
--- 4576,4582 ----
          }

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(finfo[i].dobj), dopt);

          if (strlen(finfo[i].rolname) == 0)
              write_msg(NULL,
*************** getTables(Archive *fout, DumpOptions *do
*** 5163,5169 ****
          if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
              tblinfo[i].dobj.dump = false;
          else
!             selectDumpableTable(&tblinfo[i]);
          tblinfo[i].interesting = tblinfo[i].dobj.dump;

          tblinfo[i].postponed_def = false;        /* might get set during sort */
--- 5238,5244 ----
          if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
              tblinfo[i].dobj.dump = false;
          else
!             selectDumpableTable(&tblinfo[i], dopt);
          tblinfo[i].interesting = tblinfo[i].dobj.dump;

          tblinfo[i].postponed_def = false;        /* might get set during sort */
*************** getTriggers(Archive *fout, TableInfo tbl
*** 6241,6247 ****
   *      get information about event triggers
   */
  EventTriggerInfo *
! getEventTriggers(Archive *fout, int *numEventTriggers)
  {
      int            i;
      PQExpBuffer query;
--- 6316,6322 ----
   *      get information about event triggers
   */
  EventTriggerInfo *
! getEventTriggers(Archive *fout, DumpOptions *dopt, int *numEventTriggers)
  {
      int            i;
      PQExpBuffer query;
*************** getEventTriggers(Archive *fout, int *num
*** 6310,6315 ****
--- 6385,6393 ----
          evtinfo[i].evttags = pg_strdup(PQgetvalue(res, i, i_evttags));
          evtinfo[i].evtfname = pg_strdup(PQgetvalue(res, i, i_evtfname));
          evtinfo[i].evtenabled = *(PQgetvalue(res, i, i_evtenabled));
+
+         /* Decide whether we want to dump it */
+         selectDumpableObject(&(evtinfo[i].dobj), dopt);
      }

      PQclear(res);
*************** getEventTriggers(Archive *fout, int *num
*** 6329,6335 ****
   * findFuncByOid().
   */
  ProcLangInfo *
! getProcLangs(Archive *fout, int *numProcLangs)
  {
      PGresult   *res;
      int            ntups;
--- 6407,6413 ----
   * findFuncByOid().
   */
  ProcLangInfo *
! getProcLangs(Archive *fout, DumpOptions *dopt, int *numProcLangs)
  {
      PGresult   *res;
      int            ntups;
*************** getProcLangs(Archive *fout, int *numProc
*** 6464,6469 ****
--- 6542,6550 ----
          planginfo[i].lanacl = pg_strdup(PQgetvalue(res, i, i_lanacl));
          planginfo[i].lanowner = pg_strdup(PQgetvalue(res, i, i_lanowner));

+         /* Decide whether we want to dump it */
+         selectDumpableProcLang(&(planginfo[i]), dopt);
+
          if (fout->remoteVersion < 70300)
          {
              /*
*************** getCasts(Archive *fout, DumpOptions *dop
*** 6600,6606 ****
          }

          /* Decide whether we want to dump it */
!         selectDumpableCast(dopt, &(castinfo[i]));
      }

      PQclear(res);
--- 6681,6687 ----
          }

          /* Decide whether we want to dump it */
!         selectDumpableCast(&(castinfo[i]), dopt);
      }

      PQclear(res);
*************** get_language_name(Archive *fout, Oid lan
*** 6634,6640 ****
   * numTransforms is set to the number of transforms read in
   */
  TransformInfo *
! getTransforms(Archive *fout, int *numTransforms)
  {
      PGresult   *res;
      int            ntups;
--- 6715,6721 ----
   * numTransforms is set to the number of transforms read in
   */
  TransformInfo *
! getTransforms(Archive *fout, DumpOptions *dopt, int *numTransforms)
  {
      PGresult   *res;
      int            ntups;
*************** getTransforms(Archive *fout, int *numTra
*** 6708,6713 ****
--- 6789,6797 ----
                                typeInfo->dobj.name, lanname);
          transforminfo[i].dobj.name = namebuf.data;
          free(lanname);
+
+         /* Decide whether we want to dump it */
+         selectDumpableObject(&(transforminfo[i].dobj), dopt);
      }

      PQclear(res);
*************** shouldPrintColumn(DumpOptions *dopt, Tab
*** 7315,7321 ****
   *    numTSParsers is set to the number of parsers read in
   */
  TSParserInfo *
! getTSParsers(Archive *fout, int *numTSParsers)
  {
      PGresult   *res;
      int            ntups;
--- 7399,7405 ----
   *    numTSParsers is set to the number of parsers read in
   */
  TSParserInfo *
! getTSParsers(Archive *fout, DumpOptions *dopt, int *numTSParsers)
  {
      PGresult   *res;
      int            ntups;
*************** getTSParsers(Archive *fout, int *numTSPa
*** 7389,7395 ****
          prsinfo[i].prslextype = atooid(PQgetvalue(res, i, i_prslextype));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(prsinfo[i].dobj));
      }

      PQclear(res);
--- 7473,7479 ----
          prsinfo[i].prslextype = atooid(PQgetvalue(res, i, i_prslextype));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(prsinfo[i].dobj), dopt);
      }

      PQclear(res);
*************** getTSParsers(Archive *fout, int *numTSPa
*** 7407,7413 ****
   *    numTSDicts is set to the number of dictionaries read in
   */
  TSDictInfo *
! getTSDictionaries(Archive *fout, int *numTSDicts)
  {
      PGresult   *res;
      int            ntups;
--- 7491,7497 ----
   *    numTSDicts is set to the number of dictionaries read in
   */
  TSDictInfo *
! getTSDictionaries(Archive *fout, DumpOptions *dopt, int *numTSDicts)
  {
      PGresult   *res;
      int            ntups;
*************** getTSDictionaries(Archive *fout, int *nu
*** 7474,7480 ****
              dictinfo[i].dictinitoption = pg_strdup(PQgetvalue(res, i, i_dictinitoption));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(dictinfo[i].dobj));
      }

      PQclear(res);
--- 7558,7564 ----
              dictinfo[i].dictinitoption = pg_strdup(PQgetvalue(res, i, i_dictinitoption));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(dictinfo[i].dobj), dopt);
      }

      PQclear(res);
*************** getTSDictionaries(Archive *fout, int *nu
*** 7492,7498 ****
   *    numTSTemplates is set to the number of templates read in
   */
  TSTemplateInfo *
! getTSTemplates(Archive *fout, int *numTSTemplates)
  {
      PGresult   *res;
      int            ntups;
--- 7576,7582 ----
   *    numTSTemplates is set to the number of templates read in
   */
  TSTemplateInfo *
! getTSTemplates(Archive *fout, DumpOptions *dopt, int *numTSTemplates)
  {
      PGresult   *res;
      int            ntups;
*************** getTSTemplates(Archive *fout, int *numTS
*** 7551,7557 ****
          tmplinfo[i].tmpllexize = atooid(PQgetvalue(res, i, i_tmpllexize));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(tmplinfo[i].dobj));
      }

      PQclear(res);
--- 7635,7641 ----
          tmplinfo[i].tmpllexize = atooid(PQgetvalue(res, i, i_tmpllexize));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(tmplinfo[i].dobj), dopt);
      }

      PQclear(res);
*************** getTSTemplates(Archive *fout, int *numTS
*** 7569,7575 ****
   *    numTSConfigs is set to the number of configurations read in
   */
  TSConfigInfo *
! getTSConfigurations(Archive *fout, int *numTSConfigs)
  {
      PGresult   *res;
      int            ntups;
--- 7653,7659 ----
   *    numTSConfigs is set to the number of configurations read in
   */
  TSConfigInfo *
! getTSConfigurations(Archive *fout, DumpOptions *dopt, int *numTSConfigs)
  {
      PGresult   *res;
      int            ntups;
*************** getTSConfigurations(Archive *fout, int *
*** 7629,7635 ****
          cfginfo[i].cfgparser = atooid(PQgetvalue(res, i, i_cfgparser));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(cfginfo[i].dobj));
      }

      PQclear(res);
--- 7713,7719 ----
          cfginfo[i].cfgparser = atooid(PQgetvalue(res, i, i_cfgparser));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(cfginfo[i].dobj), dopt);
      }

      PQclear(res);
*************** getTSConfigurations(Archive *fout, int *
*** 7647,7653 ****
   *    numForeignDataWrappers is set to the number of fdws read in
   */
  FdwInfo *
! getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
  {
      PGresult   *res;
      int            ntups;
--- 7731,7737 ----
   *    numForeignDataWrappers is set to the number of fdws read in
   */
  FdwInfo *
! getForeignDataWrappers(Archive *fout, DumpOptions *dopt, int *numForeignDataWrappers)
  {
      PGresult   *res;
      int            ntups;
*************** getForeignDataWrappers(Archive *fout, in
*** 7737,7743 ****
          fdwinfo[i].fdwacl = pg_strdup(PQgetvalue(res, i, i_fdwacl));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(fdwinfo[i].dobj));
      }

      PQclear(res);
--- 7821,7827 ----
          fdwinfo[i].fdwacl = pg_strdup(PQgetvalue(res, i, i_fdwacl));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(fdwinfo[i].dobj), dopt);
      }

      PQclear(res);
*************** getForeignDataWrappers(Archive *fout, in
*** 7755,7761 ****
   *    numForeignServers is set to the number of servers read in
   */
  ForeignServerInfo *
! getForeignServers(Archive *fout, int *numForeignServers)
  {
      PGresult   *res;
      int            ntups;
--- 7839,7845 ----
   *    numForeignServers is set to the number of servers read in
   */
  ForeignServerInfo *
! getForeignServers(Archive *fout, DumpOptions *dopt, int *numForeignServers)
  {
      PGresult   *res;
      int            ntups;
*************** getForeignServers(Archive *fout, int *nu
*** 7829,7835 ****
          srvinfo[i].srvacl = pg_strdup(PQgetvalue(res, i, i_srvacl));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(srvinfo[i].dobj));
      }

      PQclear(res);
--- 7913,7919 ----
          srvinfo[i].srvacl = pg_strdup(PQgetvalue(res, i, i_srvacl));

          /* Decide whether we want to dump it */
!         selectDumpableObject(&(srvinfo[i].dobj), dopt);
      }

      PQclear(res);
*************** getDefaultACLs(Archive *fout, DumpOption
*** 7916,7922 ****
          daclinfo[i].defaclacl = pg_strdup(PQgetvalue(res, i, i_defaclacl));

          /* Decide whether we want to dump it */
!         selectDumpableDefaultACL(dopt, &(daclinfo[i]));
      }

      PQclear(res);
--- 8000,8006 ----
          daclinfo[i].defaclacl = pg_strdup(PQgetvalue(res, i, i_defaclacl));

          /* Decide whether we want to dump it */
!         selectDumpableDefaultACL(&(daclinfo[i]), dopt);
      }

      PQclear(res);
*************** dumpShellType(Archive *fout, DumpOptions
*** 9868,9899 ****
  }

  /*
-  * Determine whether we want to dump definitions for procedural languages.
-  * Since the languages themselves don't have schemas, we can't rely on
-  * the normal schema-based selection mechanism.  We choose to dump them
-  * whenever neither --schema nor --table was given.  (Before 8.1, we used
-  * the dump flag of the PL's call handler function, but in 8.1 this will
-  * probably always be false since call handlers are created in pg_catalog.)
-  *
-  * For some backwards compatibility with the older behavior, we forcibly
-  * dump a PL if its handler function (and validator if any) are in a
-  * dumpable namespace.  That case is not checked here.
-  *
-  * Also, if the PL belongs to an extension, we do not use this heuristic.
-  * That case isn't checked here either.
-  */
- static bool
- shouldDumpProcLangs(DumpOptions *dopt)
- {
-     if (!dopt->include_everything)
-         return false;
-     /* And they're schema not data */
-     if (dopt->dataOnly)
-         return false;
-     return true;
- }
-
- /*
   * dumpProcLang
   *          writes out to fout the queries to recreate a user-defined
   *          procedural language
--- 9952,9957 ----
*************** dumpProcLang(Archive *fout, DumpOptions
*** 9943,9967 ****

      /*
       * If the functions are dumpable then emit a traditional CREATE LANGUAGE
!      * with parameters.  Otherwise, dump only if shouldDumpProcLangs() says to
!      * dump it.
!      *
!      * However, for a language that belongs to an extension, we must not use
!      * the shouldDumpProcLangs heuristic, but just dump the language iff we're
!      * told to (via dobj.dump).  Generally the support functions will belong
!      * to the same extension and so have the same dump flags ... if they
!      * don't, this might not work terribly nicely.
       */
      useParams = (funcInfo != NULL &&
                   (inlineInfo != NULL || !OidIsValid(plang->laninline)) &&
                   (validatorInfo != NULL || !OidIsValid(plang->lanvalidator)));

-     if (!plang->dobj.ext_member)
-     {
-         if (!useParams && !shouldDumpProcLangs(dopt))
-             return;
-     }
-
      defqry = createPQExpBuffer();
      delqry = createPQExpBuffer();
      labelq = createPQExpBuffer();
--- 10001,10013 ----

      /*
       * If the functions are dumpable then emit a traditional CREATE LANGUAGE
!      * with parameters.  Otherwise, we'll write a parameterless command, which
!      * will rely on data from pg_pltemplate.
       */
      useParams = (funcInfo != NULL &&
                   (inlineInfo != NULL || !OidIsValid(plang->laninline)) &&
                   (validatorInfo != NULL || !OidIsValid(plang->lanvalidator)));

      defqry = createPQExpBuffer();
      delqry = createPQExpBuffer();
      labelq = createPQExpBuffer();
*************** dumpForeignDataWrapper(Archive *fout, Du
*** 13016,13029 ****
      if (!fdwinfo->dobj.dump || dopt->dataOnly)
          return;

-     /*
-      * FDWs that belong to an extension are dumped based on their "dump"
-      * field. Otherwise omit them if we are only dumping some specific object.
-      */
-     if (!fdwinfo->dobj.ext_member)
-         if (!dopt->include_everything)
-             return;
-
      q = createPQExpBuffer();
      delq = createPQExpBuffer();
      labelq = createPQExpBuffer();
--- 13062,13067 ----
*************** dumpForeignServer(Archive *fout, DumpOpt
*** 13098,13104 ****
      char       *fdwname;

      /* Skip if not to be dumped */
!     if (!srvinfo->dobj.dump || dopt->dataOnly || !dopt->include_everything)
          return;

      q = createPQExpBuffer();
--- 13136,13142 ----
      char       *fdwname;

      /* Skip if not to be dumped */
!     if (!srvinfo->dobj.dump || dopt->dataOnly)
          return;

      q = createPQExpBuffer();
*************** dumpRule(Archive *fout, DumpOptions *dop
*** 15634,15682 ****
  /*
   * getExtensionMembership --- obtain extension membership data
   *
!  * There are three main parts to this process:
!  *
!  * 1. Identify objects which are members of extensions
!  *
!  *      Generally speaking, this is to mark them as *not* being dumped, as most
!  *      extension objects are created by the single CREATE EXTENSION command.
!  *      The one exception is binary upgrades with pg_upgrade will still dump the
!  *      non-table objects.
!  *
!  * 2. Identify and create dump records for extension configuration tables.
!  *
!  *      Extensions can mark tables as "configuration", which means that the user
!  *      is able and expected to modify those tables after the extension has been
!  *      loaded.  For these tables, we dump out only the data- the structure is
!  *      expected to be handled at CREATE EXTENSION time, including any indexes or
!  *      foreign keys, which brings us to-
!  *
!  * 3. Record FK dependencies between configuration tables.
!  *
!  *      Due to the FKs being created at CREATE EXTENSION time and therefore before
!  *      the data is loaded, we have to work out what the best order for reloading
!  *      the data is, to avoid FK violations when the tables are restored.  This is
!  *      not perfect- we can't handle circular dependencies and if any exist they
!  *      will cause an invalid dump to be produced (though at least all of the data
!  *      is included for a user to manually restore).  This is currently documented
!  *      but perhaps we can provide a better solution in the future.
   */
  void
! getExtensionMembership(Archive *fout, DumpOptions *dopt, ExtensionInfo extinfo[],
!                        int numExtensions)
  {
      PQExpBuffer query;
      PGresult   *res;
      int            ntups,
                  i;
      int            i_classid,
                  i_objid,
!                 i_refclassid,
!                 i_refobjid,
!                 i_conrelid,
!                 i_confrelid;
!     DumpableObject *dobj,
!                *refdobj;

      /* Nothing to do if no extensions */
      if (numExtensions == 0)
--- 15672,15698 ----
  /*
   * getExtensionMembership --- obtain extension membership data
   *
!  * We need to identify objects that are extension members as soon as they're
!  * loaded, so that we can correctly determine whether they need to be dumped.
!  * Generally speaking, extension member objects will get marked as *not* to
!  * be dumped, as they will be recreated by the single CREATE EXTENSION
!  * command.  However, in binary upgrade mode we still need to dump the members
!  * individually.
   */
  void
! getExtensionMembership(Archive *fout, DumpOptions *dopt,
!                        ExtensionInfo extinfo[], int numExtensions)
  {
      PQExpBuffer query;
      PGresult   *res;
      int            ntups,
+                 nextmembers,
                  i;
      int            i_classid,
                  i_objid,
!                 i_refobjid;
!     ExtensionMemberId *extmembers;
!     ExtensionInfo *ext;

      /* Nothing to do if no extensions */
      if (numExtensions == 0)
*************** getExtensionMembership(Archive *fout, Du
*** 15689,15699 ****

      /* refclassid constraint is redundant but may speed the search */
      appendPQExpBufferStr(query, "SELECT "
!                          "classid, objid, refclassid, refobjid "
                           "FROM pg_depend "
                           "WHERE refclassid = 'pg_extension'::regclass "
                           "AND deptype = 'e' "
!                          "ORDER BY 3,4");

      res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);

--- 15705,15715 ----

      /* refclassid constraint is redundant but may speed the search */
      appendPQExpBufferStr(query, "SELECT "
!                          "classid, objid, refobjid "
                           "FROM pg_depend "
                           "WHERE refclassid = 'pg_extension'::regclass "
                           "AND deptype = 'e' "
!                          "ORDER BY 3");

      res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);

*************** getExtensionMembership(Archive *fout, Du
*** 15701,15776 ****

      i_classid = PQfnumber(res, "classid");
      i_objid = PQfnumber(res, "objid");
-     i_refclassid = PQfnumber(res, "refclassid");
      i_refobjid = PQfnumber(res, "refobjid");

      /*
       * Since we ordered the SELECT by referenced ID, we can expect that
       * multiple entries for the same extension will appear together; this
       * saves on searches.
       */
!     refdobj = NULL;

      for (i = 0; i < ntups; i++)
      {
          CatalogId    objId;
!         CatalogId    refobjId;

          objId.tableoid = atooid(PQgetvalue(res, i, i_classid));
          objId.oid = atooid(PQgetvalue(res, i, i_objid));
!         refobjId.tableoid = atooid(PQgetvalue(res, i, i_refclassid));
!         refobjId.oid = atooid(PQgetvalue(res, i, i_refobjid));

!         if (refdobj == NULL ||
!             refdobj->catId.tableoid != refobjId.tableoid ||
!             refdobj->catId.oid != refobjId.oid)
!             refdobj = findObjectByCatalogId(refobjId);

!         /*
!          * Failure to find objects mentioned in pg_depend is not unexpected,
!          * since for example we don't collect info about TOAST tables.
!          */
!         if (refdobj == NULL)
          {
! #ifdef NOT_USED
!             fprintf(stderr, "no referenced object %u %u\n",
!                     refobjId.tableoid, refobjId.oid);
! #endif
              continue;
          }

!         dobj = findObjectByCatalogId(objId);

!         if (dobj == NULL)
!         {
! #ifdef NOT_USED
!             fprintf(stderr, "no referencing object %u %u\n",
!                     objId.tableoid, objId.oid);
! #endif
!             continue;
!         }

!         /* Record dependency so that getDependencies needn't repeat this */
!         addObjectDependency(dobj, refdobj->dumpId);

!         dobj->ext_member = true;

!         /*
!          * 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.
!          */
!         if (!dopt->binary_upgrade)
!             dobj->dump = false;
!         else
!             dobj->dump = refdobj->dump;
!     }

!     PQclear(res);

      /*
!      * Now identify extension configuration tables and create TableDataInfo
       * objects for them, ensuring their data will be dumped even though the
       * tables themselves won't be.
       *
--- 15717,15809 ----

      i_classid = PQfnumber(res, "classid");
      i_objid = PQfnumber(res, "objid");
      i_refobjid = PQfnumber(res, "refobjid");

+     extmembers = (ExtensionMemberId *) pg_malloc(ntups * sizeof(ExtensionMemberId));
+     nextmembers = 0;
+
      /*
+      * Accumulate data into extmembers[].
+      *
       * Since we ordered the SELECT by referenced ID, we can expect that
       * multiple entries for the same extension will appear together; this
       * saves on searches.
       */
!     ext = NULL;

      for (i = 0; i < ntups; i++)
      {
          CatalogId    objId;
!         Oid            extId;

          objId.tableoid = atooid(PQgetvalue(res, i, i_classid));
          objId.oid = atooid(PQgetvalue(res, i, i_objid));
!         extId = atooid(PQgetvalue(res, i, i_refobjid));

!         if (ext == NULL ||
!             ext->dobj.catId.oid != extId)
!             ext = findExtensionByOid(extId);

!         if (ext == NULL)
          {
!             /* shouldn't happen */
!             fprintf(stderr, "could not find referenced extension %u\n", extId);
              continue;
          }

!         extmembers[nextmembers].catId = objId;
!         extmembers[nextmembers].ext = ext;
!         nextmembers++;
!     }

!     PQclear(res);

!     /* Remember the data for use later */
!     setExtensionMembership(extmembers, nextmembers);

!     destroyPQExpBuffer(query);
! }

! /*
!  * processExtensionTables --- deal with extension configuration tables
!  *
!  * There are two parts to this process:
!  *
!  * 1. Identify and create dump records for extension configuration tables.
!  *
!  *      Extensions can mark tables as "configuration", which means that the user
!  *      is able and expected to modify those tables after the extension has been
!  *      loaded.  For these tables, we dump out only the data- the structure is
!  *      expected to be handled at CREATE EXTENSION time, including any indexes or
!  *      foreign keys, which brings us to-
!  *
!  * 2. Record FK dependencies between configuration tables.
!  *
!  *      Due to the FKs being created at CREATE EXTENSION time and therefore before
!  *      the data is loaded, we have to work out what the best order for reloading
!  *      the data is, to avoid FK violations when the tables are restored.  This is
!  *      not perfect- we can't handle circular dependencies and if any exist they
!  *      will cause an invalid dump to be produced (though at least all of the data
!  *      is included for a user to manually restore).  This is currently documented
!  *      but perhaps we can provide a better solution in the future.
!  */
! void
! processExtensionTables(Archive *fout, DumpOptions *dopt,
!                        ExtensionInfo extinfo[], int numExtensions)
! {
!     PQExpBuffer query;
!     PGresult   *res;
!     int            ntups,
!                 i;
!     int            i_conrelid,
!                 i_confrelid;

!     /* Nothing to do if no extensions */
!     if (numExtensions == 0)
!         return;

      /*
!      * Identify extension configuration tables and create TableDataInfo
       * objects for them, ensuring their data will be dumped even though the
       * tables themselves won't be.
       *
*************** getExtensionMembership(Archive *fout, Du
*** 15858,15868 ****
      /*
       * Now that all the TableInfoData objects have been created for all the
       * extensions, check their FK dependencies and register them to try and
!      * dump the data out in an order which they can be restored in.
       *
       * Note that this is not a problem for user tables as their FKs are
       * recreated after the data has been loaded.
       */
      printfPQExpBuffer(query,
                        "SELECT conrelid, confrelid "
                        "FROM pg_constraint "
--- 15891,15907 ----
      /*
       * Now that all the TableInfoData objects have been created for all the
       * extensions, check their FK dependencies and register them to try and
!      * dump the data out in an order that they can be restored in.
       *
       * Note that this is not a problem for user tables as their FKs are
       * recreated after the data has been loaded.
       */
+
+     /* Make sure we are in proper schema */
+     selectSourceSchema(fout, "pg_catalog");
+
+     query = createPQExpBuffer();
+
      printfPQExpBuffer(query,
                        "SELECT conrelid, confrelid "
                        "FROM pg_constraint "
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index ba37c4c..6b0af59 100644
*** a/src/bin/pg_dump/pg_dump.h
--- b/src/bin/pg_dump/pg_dump.h
*************** typedef struct _policyInfo
*** 479,484 ****
--- 479,494 ----
      char       *polwithcheck;
  } PolicyInfo;

+ /*
+  * We build an array of these with an entry for each object that is an
+  * extension member according to pg_depend.
+  */
+ typedef struct _extensionMemberId
+ {
+     CatalogId    catId;            /* tableoid+oid of some member object */
+     ExtensionInfo *ext;            /* owning extension */
+ } ExtensionMemberId;
+
  /* global decls */
  extern bool force_quotes;        /* double-quotes for identifiers flag */
  extern bool g_verbose;            /* verbose flag */
*************** extern FuncInfo *findFuncByOid(Oid oid);
*** 511,516 ****
--- 521,530 ----
  extern OprInfo *findOprByOid(Oid oid);
  extern CollInfo *findCollationByOid(Oid oid);
  extern NamespaceInfo *findNamespaceByOid(Oid oid);
+ extern ExtensionInfo *findExtensionByOid(Oid oid);
+
+ extern void setExtensionMembership(ExtensionMemberId *extmems, int nextmems);
+ extern ExtensionInfo *findOwningExtension(CatalogId catalogId);

  extern void simple_oid_list_append(SimpleOidList *list, Oid val);
  extern bool simple_oid_list_member(SimpleOidList *list, Oid val);
*************** extern void sortDataAndIndexObjectsBySiz
*** 526,541 ****
  /*
   * version specific routines
   */
! extern NamespaceInfo *getNamespaces(Archive *fout, int *numNamespaces);
  extern ExtensionInfo *getExtensions(Archive *fout, DumpOptions *dopt, int *numExtensions);
! extern TypeInfo *getTypes(Archive *fout, int *numTypes);
  extern FuncInfo *getFuncs(Archive *fout, DumpOptions *dopt, int *numFuncs);
  extern AggInfo *getAggregates(Archive *fout, DumpOptions *dopt, int *numAggregates);
! extern OprInfo *getOperators(Archive *fout, int *numOperators);
! extern OpclassInfo *getOpclasses(Archive *fout, int *numOpclasses);
! extern OpfamilyInfo *getOpfamilies(Archive *fout, int *numOpfamilies);
! extern CollInfo *getCollations(Archive *fout, int *numCollations);
! extern ConvInfo *getConversions(Archive *fout, int *numConversions);
  extern TableInfo *getTables(Archive *fout, DumpOptions *dopt, int *numTables);
  extern void getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables);
  extern InhInfo *getInherits(Archive *fout, int *numInherits);
--- 540,555 ----
  /*
   * version specific routines
   */
! extern NamespaceInfo *getNamespaces(Archive *fout, DumpOptions *dopt, int *numNamespaces);
  extern ExtensionInfo *getExtensions(Archive *fout, DumpOptions *dopt, int *numExtensions);
! extern TypeInfo *getTypes(Archive *fout, DumpOptions *dopt, int *numTypes);
  extern FuncInfo *getFuncs(Archive *fout, DumpOptions *dopt, int *numFuncs);
  extern AggInfo *getAggregates(Archive *fout, DumpOptions *dopt, int *numAggregates);
! extern OprInfo *getOperators(Archive *fout, DumpOptions *dopt, int *numOperators);
! extern OpclassInfo *getOpclasses(Archive *fout, DumpOptions *dopt, int *numOpclasses);
! extern OpfamilyInfo *getOpfamilies(Archive *fout, DumpOptions *dopt, int *numOpfamilies);
! extern CollInfo *getCollations(Archive *fout, DumpOptions *dopt, int *numCollations);
! extern ConvInfo *getConversions(Archive *fout, DumpOptions *dopt, int *numConversions);
  extern TableInfo *getTables(Archive *fout, DumpOptions *dopt, int *numTables);
  extern void getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables);
  extern InhInfo *getInherits(Archive *fout, int *numInherits);
*************** extern void getIndexes(Archive *fout, Ta
*** 543,565 ****
  extern void getConstraints(Archive *fout, TableInfo tblinfo[], int numTables);
  extern RuleInfo *getRules(Archive *fout, int *numRules);
  extern void getTriggers(Archive *fout, TableInfo tblinfo[], int numTables);
! extern ProcLangInfo *getProcLangs(Archive *fout, int *numProcLangs);
  extern CastInfo *getCasts(Archive *fout, DumpOptions *dopt, int *numCasts);
! extern TransformInfo *getTransforms(Archive *fout, int *numTransforms);
  extern void getTableAttrs(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo, int numTables);
  extern bool shouldPrintColumn(DumpOptions *dopt, TableInfo *tbinfo, int colno);
! extern TSParserInfo *getTSParsers(Archive *fout, int *numTSParsers);
! extern TSDictInfo *getTSDictionaries(Archive *fout, int *numTSDicts);
! extern TSTemplateInfo *getTSTemplates(Archive *fout, int *numTSTemplates);
! extern TSConfigInfo *getTSConfigurations(Archive *fout, int *numTSConfigs);
! extern FdwInfo *getForeignDataWrappers(Archive *fout,
                         int *numForeignDataWrappers);
! extern ForeignServerInfo *getForeignServers(Archive *fout,
                    int *numForeignServers);
  extern DefaultACLInfo *getDefaultACLs(Archive *fout, DumpOptions *dopt, int *numDefaultACLs);
! extern void getExtensionMembership(Archive *fout, DumpOptions *dopt, ExtensionInfo extinfo[],
!                        int numExtensions);
! extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers);
  extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables);

  #endif   /* PG_DUMP_H */
--- 557,581 ----
  extern void getConstraints(Archive *fout, TableInfo tblinfo[], int numTables);
  extern RuleInfo *getRules(Archive *fout, int *numRules);
  extern void getTriggers(Archive *fout, TableInfo tblinfo[], int numTables);
! extern ProcLangInfo *getProcLangs(Archive *fout, DumpOptions *dopt, int *numProcLangs);
  extern CastInfo *getCasts(Archive *fout, DumpOptions *dopt, int *numCasts);
! extern TransformInfo *getTransforms(Archive *fout, DumpOptions *dopt, int *numTransforms);
  extern void getTableAttrs(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo, int numTables);
  extern bool shouldPrintColumn(DumpOptions *dopt, TableInfo *tbinfo, int colno);
! extern TSParserInfo *getTSParsers(Archive *fout, DumpOptions *dopt, int *numTSParsers);
! extern TSDictInfo *getTSDictionaries(Archive *fout, DumpOptions *dopt, int *numTSDicts);
! extern TSTemplateInfo *getTSTemplates(Archive *fout, DumpOptions *dopt, int *numTSTemplates);
! extern TSConfigInfo *getTSConfigurations(Archive *fout, DumpOptions *dopt, int *numTSConfigs);
! extern FdwInfo *getForeignDataWrappers(Archive *fout, DumpOptions *dopt,
                         int *numForeignDataWrappers);
! extern ForeignServerInfo *getForeignServers(Archive *fout, DumpOptions *dopt,
                    int *numForeignServers);
  extern DefaultACLInfo *getDefaultACLs(Archive *fout, DumpOptions *dopt, int *numDefaultACLs);
! extern void getExtensionMembership(Archive *fout, DumpOptions *dopt,
!                        ExtensionInfo extinfo[], int numExtensions);
! extern void processExtensionTables(Archive *fout, DumpOptions *dopt,
!                        ExtensionInfo extinfo[], int numExtensions);
! extern EventTriggerInfo *getEventTriggers(Archive *fout, DumpOptions *dopt, int *numEventTriggers);
  extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables);

  #endif   /* PG_DUMP_H */

Re: pg_dump and premature optimizations for objects not to be dumped

От
Tom Lane
Дата:
I wrote:
> Attached is a draft patch that does things this way.

BTW, the bulk of the changes in this patch are just there to pass down
the DumpOptions struct to where it's needed, following some pre-existing
work that passed that around as a separate pointer.  I wonder why things
were done that way, rather than adding a DumpOptions pointer in the
Archive struct?  The vast majority of the functions I had to touch already
had an Archive* parameter, and would not have needed to be touched if it
were done the other way.  I'm tempted to push a preliminary patch that
adds such a field and gets rid of DumpOptions as a separate parameter
to anything that also takes an Archive* pointer.
        regards, tom lane



Re: pg_dump and premature optimizations for objects not to be dumped

От
Tom Lane
Дата:
I wrote:
> BTW, the bulk of the changes in this patch are just there to pass down
> the DumpOptions struct to where it's needed, following some pre-existing
> work that passed that around as a separate pointer.  I wonder why things
> were done that way, rather than adding a DumpOptions pointer in the
> Archive struct?  The vast majority of the functions I had to touch already
> had an Archive* parameter, and would not have needed to be touched if it
> were done the other way.  I'm tempted to push a preliminary patch that
> adds such a field and gets rid of DumpOptions as a separate parameter
> to anything that also takes an Archive* pointer.

Specifically, something like the attached, which is bulky but mostly
mechanical.  This undoes a lot of API changes introduced by 0eea8047bf
to pass DumpOptions as a separate argument to assorted functions.
I think this is a good idea because (a) those changes were pretty random
and incomplete, as evidenced by the fact that I had to do a bunch more of
them in my upthread patch; (b) this significantly reduces the delta
between 9.5/HEAD and pre-9.5 code in pg_dump, which will no doubt ease
future back-patching.  So unless I hear objections, I plan to push this
pretty soon.

            regards, tom lane

diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 7869ee9..3b4e478 100644
*** a/src/bin/pg_dump/common.c
--- b/src/bin/pg_dump/common.c
*************** static int    strInArray(const char *patter
*** 81,87 ****
   *      Collect information about all potentially dumpable objects
   */
  TableInfo *
! getSchemaData(Archive *fout, DumpOptions *dopt, int *numTablesPtr)
  {
      ExtensionInfo *extinfo;
      InhInfo    *inhinfo;
--- 81,87 ----
   *      Collect information about all potentially dumpable objects
   */
  TableInfo *
! getSchemaData(Archive *fout, int *numTablesPtr)
  {
      ExtensionInfo *extinfo;
      InhInfo    *inhinfo;
*************** getSchemaData(Archive *fout, DumpOptions
*** 118,124 ****
       */
      if (g_verbose)
          write_msg(NULL, "reading user-defined tables\n");
!     tblinfo = getTables(fout, dopt, &numTables);
      tblinfoindex = buildIndexArray(tblinfo, numTables, sizeof(TableInfo));

      /* Do this after we've built tblinfoindex */
--- 118,124 ----
       */
      if (g_verbose)
          write_msg(NULL, "reading user-defined tables\n");
!     tblinfo = getTables(fout, &numTables);
      tblinfoindex = buildIndexArray(tblinfo, numTables, sizeof(TableInfo));

      /* Do this after we've built tblinfoindex */
*************** getSchemaData(Archive *fout, DumpOptions
*** 126,136 ****

      if (g_verbose)
          write_msg(NULL, "reading extensions\n");
!     extinfo = getExtensions(fout, dopt, &numExtensions);

      if (g_verbose)
          write_msg(NULL, "reading user-defined functions\n");
!     funinfo = getFuncs(fout, dopt, &numFuncs);
      funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo));

      /* this must be after getTables and getFuncs */
--- 126,136 ----

      if (g_verbose)
          write_msg(NULL, "reading extensions\n");
!     extinfo = getExtensions(fout, &numExtensions);

      if (g_verbose)
          write_msg(NULL, "reading user-defined functions\n");
!     funinfo = getFuncs(fout, &numFuncs);
      funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo));

      /* this must be after getTables and getFuncs */
*************** getSchemaData(Archive *fout, DumpOptions
*** 146,152 ****

      if (g_verbose)
          write_msg(NULL, "reading user-defined aggregate functions\n");
!     getAggregates(fout, dopt, &numAggregates);

      if (g_verbose)
          write_msg(NULL, "reading user-defined operators\n");
--- 146,152 ----

      if (g_verbose)
          write_msg(NULL, "reading user-defined aggregate functions\n");
!     getAggregates(fout, &numAggregates);

      if (g_verbose)
          write_msg(NULL, "reading user-defined operators\n");
*************** getSchemaData(Archive *fout, DumpOptions
*** 187,193 ****

      if (g_verbose)
          write_msg(NULL, "reading default privileges\n");
!     getDefaultACLs(fout, dopt, &numDefaultACLs);

      if (g_verbose)
          write_msg(NULL, "reading user-defined collations\n");
--- 187,193 ----

      if (g_verbose)
          write_msg(NULL, "reading default privileges\n");
!     getDefaultACLs(fout, &numDefaultACLs);

      if (g_verbose)
          write_msg(NULL, "reading user-defined collations\n");
*************** getSchemaData(Archive *fout, DumpOptions
*** 200,206 ****

      if (g_verbose)
          write_msg(NULL, "reading type casts\n");
!     getCasts(fout, dopt, &numCasts);

      if (g_verbose)
          write_msg(NULL, "reading transforms\n");
--- 200,206 ----

      if (g_verbose)
          write_msg(NULL, "reading type casts\n");
!     getCasts(fout, &numCasts);

      if (g_verbose)
          write_msg(NULL, "reading transforms\n");
*************** getSchemaData(Archive *fout, DumpOptions
*** 221,227 ****
       */
      if (g_verbose)
          write_msg(NULL, "finding extension members\n");
!     getExtensionMembership(fout, dopt, extinfo, numExtensions);

      /* Link tables to parents, mark parents of target tables interesting */
      if (g_verbose)
--- 221,227 ----
       */
      if (g_verbose)
          write_msg(NULL, "finding extension members\n");
!     getExtensionMembership(fout, extinfo, numExtensions);

      /* Link tables to parents, mark parents of target tables interesting */
      if (g_verbose)
*************** getSchemaData(Archive *fout, DumpOptions
*** 230,240 ****

      if (g_verbose)
          write_msg(NULL, "reading column info for interesting tables\n");
!     getTableAttrs(fout, dopt, tblinfo, numTables);

      if (g_verbose)
          write_msg(NULL, "flagging inherited columns in subtables\n");
!     flagInhAttrs(dopt, tblinfo, numTables);

      if (g_verbose)
          write_msg(NULL, "reading indexes\n");
--- 230,240 ----

      if (g_verbose)
          write_msg(NULL, "reading column info for interesting tables\n");
!     getTableAttrs(fout, tblinfo, numTables);

      if (g_verbose)
          write_msg(NULL, "flagging inherited columns in subtables\n");
!     flagInhAttrs(fout->dopt, tblinfo, numTables);

      if (g_verbose)
          write_msg(NULL, "reading indexes\n");
diff --git a/src/bin/pg_dump/parallel.c b/src/bin/pg_dump/parallel.c
index ce5e472..d8bd9a9 100644
*** a/src/bin/pg_dump/parallel.c
--- b/src/bin/pg_dump/parallel.c
*************** static int    piperead(int s, char *buf, in
*** 46,53 ****
  typedef struct
  {
      ArchiveHandle *AH;
-     RestoreOptions *ropt;
-     DumpOptions *dopt;
      int            worker;
      int            pipeRead;
      int            pipeWrite;
--- 46,51 ----
*************** static void WaitForTerminatingWorkers(Pa
*** 87,99 ****
  #ifndef WIN32
  static void sigTermHandler(int signum);
  #endif
! static void SetupWorker(ArchiveHandle *AH, int pipefd[2], int worker,
!             DumpOptions *dopt,
!             RestoreOptions *ropt);
  static bool HasEveryWorkerTerminated(ParallelState *pstate);

  static void lockTableNoWait(ArchiveHandle *AH, TocEntry *te);
! static void WaitForCommands(ArchiveHandle *AH, DumpOptions *dopt, int pipefd[2]);
  static char *getMessageFromMaster(int pipefd[2]);
  static void sendMessageToMaster(int pipefd[2], const char *str);
  static int    select_loop(int maxFd, fd_set *workerset);
--- 85,95 ----
  #ifndef WIN32
  static void sigTermHandler(int signum);
  #endif
! static void SetupWorker(ArchiveHandle *AH, int pipefd[2], int worker);
  static bool HasEveryWorkerTerminated(ParallelState *pstate);

  static void lockTableNoWait(ArchiveHandle *AH, TocEntry *te);
! static void WaitForCommands(ArchiveHandle *AH, int pipefd[2]);
  static char *getMessageFromMaster(int pipefd[2]);
  static void sendMessageToMaster(int pipefd[2], const char *str);
  static int    select_loop(int maxFd, fd_set *workerset);
*************** sigTermHandler(int signum)
*** 435,443 ****
   * worker process.
   */
  static void
! SetupWorker(ArchiveHandle *AH, int pipefd[2], int worker,
!             DumpOptions *dopt,
!             RestoreOptions *ropt)
  {
      /*
       * Call the setup worker function that's defined in the ArchiveHandle.
--- 431,437 ----
   * worker process.
   */
  static void
! SetupWorker(ArchiveHandle *AH, int pipefd[2], int worker)
  {
      /*
       * Call the setup worker function that's defined in the ArchiveHandle.
*************** SetupWorker(ArchiveHandle *AH, int pipef
*** 446,456 ****
       * properly when we shut down. This happens only that way when it is
       * brought down because of an error.
       */
!     (AH->SetupWorkerPtr) ((Archive *) AH, dopt, ropt);

      Assert(AH->connection != NULL);

!     WaitForCommands(AH, dopt, pipefd);

      closesocket(pipefd[PIPE_READ]);
      closesocket(pipefd[PIPE_WRITE]);
--- 440,450 ----
       * properly when we shut down. This happens only that way when it is
       * brought down because of an error.
       */
!     (AH->SetupWorkerPtr) ((Archive *) AH);

      Assert(AH->connection != NULL);

!     WaitForCommands(AH, pipefd);

      closesocket(pipefd[PIPE_READ]);
      closesocket(pipefd[PIPE_WRITE]);
*************** init_spawned_worker_win32(WorkerInfo *wi
*** 463,475 ****
      ArchiveHandle *AH;
      int            pipefd[2] = {wi->pipeRead, wi->pipeWrite};
      int            worker = wi->worker;
-     DumpOptions *dopt = wi->dopt;
-     RestoreOptions *ropt = wi->ropt;

      AH = CloneArchive(wi->AH);

      free(wi);
!     SetupWorker(AH, pipefd, worker, dopt, ropt);

      DeCloneArchive(AH);
      _endthreadex(0);
--- 457,467 ----
      ArchiveHandle *AH;
      int            pipefd[2] = {wi->pipeRead, wi->pipeWrite};
      int            worker = wi->worker;

      AH = CloneArchive(wi->AH);

      free(wi);
!     SetupWorker(AH, pipefd, worker);

      DeCloneArchive(AH);
      _endthreadex(0);
*************** init_spawned_worker_win32(WorkerInfo *wi
*** 483,489 ****
   * of threads while it does a fork() on Unix.
   */
  ParallelState *
! ParallelBackupStart(ArchiveHandle *AH, DumpOptions *dopt, RestoreOptions *ropt)
  {
      ParallelState *pstate;
      int            i;
--- 475,481 ----
   * of threads while it does a fork() on Unix.
   */
  ParallelState *
! ParallelBackupStart(ArchiveHandle *AH)
  {
      ParallelState *pstate;
      int            i;
*************** ParallelBackupStart(ArchiveHandle *AH, D
*** 545,552 ****
          /* Allocate a new structure for every worker */
          wi = (WorkerInfo *) pg_malloc(sizeof(WorkerInfo));

-         wi->ropt = ropt;
-         wi->dopt = dopt;
          wi->worker = i;
          wi->AH = AH;
          wi->pipeRead = pstate->parallelSlot[i].pipeRevRead = pipeMW[PIPE_READ];
--- 537,542 ----
*************** ParallelBackupStart(ArchiveHandle *AH, D
*** 601,607 ****
                  closesocket(pstate->parallelSlot[j].pipeWrite);
              }

!             SetupWorker(pstate->parallelSlot[i].args->AH, pipefd, i, dopt, ropt);

              exit(0);
          }
--- 591,597 ----
                  closesocket(pstate->parallelSlot[j].pipeWrite);
              }

!             SetupWorker(pstate->parallelSlot[i].args->AH, pipefd, i);

              exit(0);
          }
*************** lockTableNoWait(ArchiveHandle *AH, TocEn
*** 859,865 ****
   * exit.
   */
  static void
! WaitForCommands(ArchiveHandle *AH, DumpOptions *dopt, int pipefd[2])
  {
      char       *command;
      DumpId        dumpId;
--- 849,855 ----
   * exit.
   */
  static void
! WaitForCommands(ArchiveHandle *AH, int pipefd[2])
  {
      char       *command;
      DumpId        dumpId;
*************** WaitForCommands(ArchiveHandle *AH, DumpO
*** 899,905 ****
               * The message we return here has been pg_malloc()ed and we are
               * responsible for free()ing it.
               */
!             str = (AH->WorkerJobDumpPtr) (AH, dopt, te);
              Assert(AH->connection != NULL);
              sendMessageToMaster(pipefd, str);
              free(str);
--- 889,895 ----
               * The message we return here has been pg_malloc()ed and we are
               * responsible for free()ing it.
               */
!             str = (AH->WorkerJobDumpPtr) (AH, te);
              Assert(AH->connection != NULL);
              sendMessageToMaster(pipefd, str);
              free(str);
diff --git a/src/bin/pg_dump/parallel.h b/src/bin/pg_dump/parallel.h
index ecceb4e..591653b 100644
*** a/src/bin/pg_dump/parallel.h
--- b/src/bin/pg_dump/parallel.h
*************** extern int    ReapWorkerStatus(ParallelStat
*** 76,84 ****
  extern void EnsureIdleWorker(ArchiveHandle *AH, ParallelState *pstate);
  extern void EnsureWorkersFinished(ArchiveHandle *AH, ParallelState *pstate);

! extern ParallelState *ParallelBackupStart(ArchiveHandle *AH,
!                     DumpOptions *dopt,
!                     RestoreOptions *ropt);
  extern void DispatchJobForTocEntry(ArchiveHandle *AH,
                         ParallelState *pstate,
                         TocEntry *te, T_Action act);
--- 76,82 ----
  extern void EnsureIdleWorker(ArchiveHandle *AH, ParallelState *pstate);
  extern void EnsureWorkersFinished(ArchiveHandle *AH, ParallelState *pstate);

! extern ParallelState *ParallelBackupStart(ArchiveHandle *AH);
  extern void DispatchJobForTocEntry(ArchiveHandle *AH,
                         ParallelState *pstate,
                         TocEntry *te, T_Action act);
diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h
index 7126749..26061e7 100644
*** a/src/bin/pg_dump/pg_backup.h
--- b/src/bin/pg_dump/pg_backup.h
*************** typedef enum _teSection
*** 58,92 ****
      SECTION_POST_DATA            /* stuff to be processed after data */
  } teSection;

- /*
-  *    We may want to have some more user-readable data, but in the mean
-  *    time this gives us some abstraction and type checking.
-  */
- typedef struct Archive
- {
-     int            verbose;
-     char       *remoteVersionStr;        /* server's version string */
-     int            remoteVersion;    /* same in numeric form */
-
-     int            minRemoteVersion;        /* allowable range */
-     int            maxRemoteVersion;
-
-     int            numWorkers;        /* number of parallel processes */
-     char       *sync_snapshot_id;        /* sync snapshot id for parallel
-                                          * operation */
-
-     /* info needed for string escaping */
-     int            encoding;        /* libpq code for client_encoding */
-     bool        std_strings;    /* standard_conforming_strings */
-     char       *use_role;        /* Issue SET ROLE to this */
-
-     /* error handling */
-     bool        exit_on_error;    /* whether to exit on SQL errors... */
-     int            n_errors;        /* number of errors (if no die) */
-
-     /* The rest is private */
- } Archive;
-
  typedef struct _restoreOptions
  {
      int            createDB;        /* Issue commands to create the database */
--- 58,63 ----
*************** typedef struct _dumpOptions
*** 190,195 ****
--- 161,198 ----
      char       *outputSuperuser;
  } DumpOptions;

+ /*
+  *    We may want to have some more user-readable data, but in the mean
+  *    time this gives us some abstraction and type checking.
+  */
+ typedef struct Archive
+ {
+     DumpOptions *dopt;            /* options, if dumping */
+     RestoreOptions *ropt;        /* options, if restoring */
+
+     int            verbose;
+     char       *remoteVersionStr;        /* server's version string */
+     int            remoteVersion;    /* same in numeric form */
+
+     int            minRemoteVersion;        /* allowable range */
+     int            maxRemoteVersion;
+
+     int            numWorkers;        /* number of parallel processes */
+     char       *sync_snapshot_id;        /* sync snapshot id for parallel
+                                          * operation */
+
+     /* info needed for string escaping */
+     int            encoding;        /* libpq code for client_encoding */
+     bool        std_strings;    /* standard_conforming_strings */
+     char       *use_role;        /* Issue SET ROLE to this */
+
+     /* error handling */
+     bool        exit_on_error;    /* whether to exit on SQL errors... */
+     int            n_errors;        /* number of errors (if no die) */
+
+     /* The rest is private */
+ } Archive;
+

  /*
   * pg_dump uses two different mechanisms for identifying database objects:
*************** typedef struct
*** 215,223 ****

  typedef int DumpId;

! typedef int (*DataDumperPtr) (Archive *AH, DumpOptions *dopt, void *userArg);

! typedef void (*SetupWorkerPtr) (Archive *AH, DumpOptions *dopt, RestoreOptions *ropt);

  /*
   * Main archiver interface.
--- 218,226 ----

  typedef int DumpId;

! typedef int (*DataDumperPtr) (Archive *AH, void *userArg);

! typedef void (*SetupWorkerPtr) (Archive *AH);

  /*
   * Main archiver interface.
*************** extern void WriteData(Archive *AH, const
*** 250,258 ****
  extern int    StartBlob(Archive *AH, Oid oid);
  extern int    EndBlob(Archive *AH, Oid oid);

! extern void CloseArchive(Archive *AH, DumpOptions *dopt);

! extern void SetArchiveRestoreOptions(Archive *AH, RestoreOptions *ropt);

  extern void RestoreArchive(Archive *AH);

--- 253,263 ----
  extern int    StartBlob(Archive *AH, Oid oid);
  extern int    EndBlob(Archive *AH, Oid oid);

! extern void CloseArchive(Archive *AH);

! extern void SetArchiveOptions(Archive *AH, DumpOptions *dopt, RestoreOptions *ropt);
!
! extern void ProcessArchiveRestoreOptions(Archive *AH);

  extern void RestoreArchive(Archive *AH);

*************** extern Archive *CreateArchive(const char
*** 265,271 ****
                SetupWorkerPtr setupDumpWorker);

  /* The --list option */
! extern void PrintTOCSummary(Archive *AH, RestoreOptions *ropt);

  extern RestoreOptions *NewRestoreOptions(void);

--- 270,276 ----
                SetupWorkerPtr setupDumpWorker);

  /* The --list option */
! extern void PrintTOCSummary(Archive *AH);

  extern RestoreOptions *NewRestoreOptions(void);

*************** extern void InitDumpOptions(DumpOptions
*** 274,280 ****
  extern DumpOptions *dumpOptionsFromRestoreOptions(RestoreOptions *ropt);

  /* Rearrange and filter TOC entries */
! extern void SortTocFromFile(Archive *AHX, RestoreOptions *ropt);

  /* Convenience functions used only when writing DATA */
  extern void archputs(const char *s, Archive *AH);
--- 279,285 ----
  extern DumpOptions *dumpOptionsFromRestoreOptions(RestoreOptions *ropt);

  /* Rearrange and filter TOC entries */
! extern void SortTocFromFile(Archive *AHX);

  /* Convenience functions used only when writing DATA */
  extern void archputs(const char *s, Archive *AH);
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index c33df4d..33e500e 100644
*** a/src/bin/pg_dump/pg_backup_archiver.c
--- b/src/bin/pg_dump/pg_backup_archiver.c
*************** static ArchiveHandle *_allocAH(const cha
*** 57,63 ****
       const int compression, ArchiveMode mode, SetupWorkerPtr setupWorkerPtr);
  static void _getObjectDescription(PQExpBuffer buf, TocEntry *te,
                        ArchiveHandle *AH);
! static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData, bool acl_pass);
  static char *replace_line_endings(const char *str);
  static void _doSetFixedOutputState(ArchiveHandle *AH);
  static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
--- 57,63 ----
       const int compression, ArchiveMode mode, SetupWorkerPtr setupWorkerPtr);
  static void _getObjectDescription(PQExpBuffer buf, TocEntry *te,
                        ArchiveHandle *AH);
! static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData, bool acl_pass);
  static char *replace_line_endings(const char *str);
  static void _doSetFixedOutputState(ArchiveHandle *AH);
  static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
*************** static void processEncodingEntry(Archive
*** 71,78 ****
  static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te);
  static teReqs _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt);
  static bool _tocEntryIsACL(TocEntry *te);
! static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
! static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
  static void buildTocEntryArrays(ArchiveHandle *AH);
  static void _moveBefore(ArchiveHandle *AH, TocEntry *pos, TocEntry *te);
  static int    _discoverArchiveFormat(ArchiveHandle *AH);
--- 71,78 ----
  static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te);
  static teReqs _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt);
  static bool _tocEntryIsACL(TocEntry *te);
! static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te);
! static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te);
  static void buildTocEntryArrays(ArchiveHandle *AH);
  static void _moveBefore(ArchiveHandle *AH, TocEntry *pos, TocEntry *te);
  static int    _discoverArchiveFormat(ArchiveHandle *AH);
*************** static void SetOutput(ArchiveHandle *AH,
*** 84,91 ****
  static OutputContext SaveOutput(ArchiveHandle *AH);
  static void RestoreOutput(ArchiveHandle *AH, OutputContext savedContext);

! static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te,
!                   RestoreOptions *ropt, bool is_parallel);
  static void restore_toc_entries_prefork(ArchiveHandle *AH);
  static void restore_toc_entries_parallel(ArchiveHandle *AH, ParallelState *pstate,
                               TocEntry *pending_list);
--- 84,90 ----
  static OutputContext SaveOutput(ArchiveHandle *AH);
  static void RestoreOutput(ArchiveHandle *AH, OutputContext savedContext);

! static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel);
  static void restore_toc_entries_prefork(ArchiveHandle *AH);
  static void restore_toc_entries_parallel(ArchiveHandle *AH, ParallelState *pstate,
                               TocEntry *pending_list);
*************** dumpOptionsFromRestoreOptions(RestoreOpt
*** 184,190 ****
   * setup doesn't need to know anything much, so it's defined here.
   */
  static void
! setupRestoreWorker(Archive *AHX, DumpOptions *dopt, RestoreOptions *ropt)
  {
      ArchiveHandle *AH = (ArchiveHandle *) AHX;

--- 183,189 ----
   * setup doesn't need to know anything much, so it's defined here.
   */
  static void
! setupRestoreWorker(Archive *AHX)
  {
      ArchiveHandle *AH = (ArchiveHandle *) AHX;

*************** OpenArchive(const char *FileSpec, const
*** 216,227 ****

  /* Public */
  void
! CloseArchive(Archive *AHX, DumpOptions *dopt)
  {
      int            res = 0;
      ArchiveHandle *AH = (ArchiveHandle *) AHX;

!     (*AH->ClosePtr) (AH, dopt);

      /* Close the output */
      if (AH->gzOut)
--- 215,226 ----

  /* Public */
  void
! CloseArchive(Archive *AHX)
  {
      int            res = 0;
      ArchiveHandle *AH = (ArchiveHandle *) AHX;

!     (*AH->ClosePtr) (AH);

      /* Close the output */
      if (AH->gzOut)
*************** CloseArchive(Archive *AHX, DumpOptions *
*** 236,249 ****

  /* Public */
  void
! SetArchiveRestoreOptions(Archive *AHX, RestoreOptions *ropt)
  {
!     ArchiveHandle *AH = (ArchiveHandle *) AHX;
!     TocEntry   *te;
!     teSection    curSection;

      /* Save options for later access */
      AH->ropt = ropt;

      /* Decide which TOC entries will be dumped/restored, and mark them */
      curSection = SECTION_PRE_DATA;
--- 235,259 ----

  /* Public */
  void
! SetArchiveOptions(Archive *AH, DumpOptions *dopt, RestoreOptions *ropt)
  {
!     /* Caller can omit dump options, in which case we synthesize them */
!     if (dopt == NULL && ropt != NULL)
!         dopt = dumpOptionsFromRestoreOptions(ropt);

      /* Save options for later access */
+     AH->dopt = dopt;
      AH->ropt = ropt;
+ }
+
+ /* Public */
+ void
+ ProcessArchiveRestoreOptions(Archive *AHX)
+ {
+     ArchiveHandle *AH = (ArchiveHandle *) AHX;
+     RestoreOptions *ropt = AH->public.ropt;
+     TocEntry   *te;
+     teSection    curSection;

      /* Decide which TOC entries will be dumped/restored, and mark them */
      curSection = SECTION_PRE_DATA;
*************** void
*** 298,304 ****
  RestoreArchive(Archive *AHX)
  {
      ArchiveHandle *AH = (ArchiveHandle *) AHX;
!     RestoreOptions *ropt = AH->ropt;
      bool        parallel_mode;
      TocEntry   *te;
      OutputContext sav;
--- 308,314 ----
  RestoreArchive(Archive *AHX)
  {
      ArchiveHandle *AH = (ArchiveHandle *) AHX;
!     RestoreOptions *ropt = AH->public.ropt;
      bool        parallel_mode;
      TocEntry   *te;
      OutputContext sav;
*************** RestoreArchive(Archive *AHX)
*** 605,611 ****
          Assert(AH->connection == NULL);

          /* ParallelBackupStart() will actually fork the processes */
!         pstate = ParallelBackupStart(AH, NULL, ropt);
          restore_toc_entries_parallel(AH, pstate, &pending_list);
          ParallelBackupEnd(AH, pstate);

--- 615,621 ----
          Assert(AH->connection == NULL);

          /* ParallelBackupStart() will actually fork the processes */
!         pstate = ParallelBackupStart(AH);
          restore_toc_entries_parallel(AH, pstate, &pending_list);
          ParallelBackupEnd(AH, pstate);

*************** RestoreArchive(Archive *AHX)
*** 616,622 ****
      else
      {
          for (te = AH->toc->next; te != AH->toc; te = te->next)
!             (void) restore_toc_entry(AH, te, ropt, false);
      }

      /*
--- 626,632 ----
      else
      {
          for (te = AH->toc->next; te != AH->toc; te = te->next)
!             (void) restore_toc_entry(AH, te, false);
      }

      /*
*************** RestoreArchive(Archive *AHX)
*** 636,642 ****
              else
                  ahlog(AH, 1, "setting owner and privileges for %s \"%s\"\n",
                        te->desc, te->tag);
!             _printTocEntry(AH, te, ropt, false, true);
          }
      }

--- 646,652 ----
              else
                  ahlog(AH, 1, "setting owner and privileges for %s \"%s\"\n",
                        te->desc, te->tag);
!             _printTocEntry(AH, te, false, true);
          }
      }

*************** RestoreArchive(Archive *AHX)
*** 673,681 ****
   * the parallel parent has to make the corresponding status update.
   */
  static int
! restore_toc_entry(ArchiveHandle *AH, TocEntry *te,
!                   RestoreOptions *ropt, bool is_parallel)
  {
      int            status = WORKER_OK;
      teReqs        reqs;
      bool        defnDumped;
--- 683,691 ----
   * the parallel parent has to make the corresponding status update.
   */
  static int
! restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)
  {
+     RestoreOptions *ropt = AH->public.ropt;
      int            status = WORKER_OK;
      teReqs        reqs;
      bool        defnDumped;
*************** restore_toc_entry(ArchiveHandle *AH, Toc
*** 717,723 ****
              ahlog(AH, 1, "creating %s \"%s\"\n", te->desc, te->tag);


!         _printTocEntry(AH, te, ropt, false, false);
          defnDumped = true;

          if (strcmp(te->desc, "TABLE") == 0)
--- 727,733 ----
              ahlog(AH, 1, "creating %s \"%s\"\n", te->desc, te->tag);


!         _printTocEntry(AH, te, false, false);
          defnDumped = true;

          if (strcmp(te->desc, "TABLE") == 0)
*************** restore_toc_entry(ArchiveHandle *AH, Toc
*** 782,788 ****
               */
              if (AH->PrintTocDataPtr !=NULL)
              {
!                 _printTocEntry(AH, te, ropt, true, false);

                  if (strcmp(te->desc, "BLOBS") == 0 ||
                      strcmp(te->desc, "BLOB COMMENTS") == 0)
--- 792,798 ----
               */
              if (AH->PrintTocDataPtr !=NULL)
              {
!                 _printTocEntry(AH, te, true, false);

                  if (strcmp(te->desc, "BLOBS") == 0 ||
                      strcmp(te->desc, "BLOB COMMENTS") == 0)
*************** restore_toc_entry(ArchiveHandle *AH, Toc
*** 795,807 ****
                      if (strcmp(te->desc, "BLOB COMMENTS") == 0)
                          AH->outputKind = OUTPUT_OTHERDATA;

!                     (*AH->PrintTocDataPtr) (AH, te, ropt);

                      AH->outputKind = OUTPUT_SQLCMDS;
                  }
                  else
                  {
!                     _disableTriggersIfNecessary(AH, te, ropt);

                      /* Select owner and schema as necessary */
                      _becomeOwner(AH, te);
--- 805,817 ----
                      if (strcmp(te->desc, "BLOB COMMENTS") == 0)
                          AH->outputKind = OUTPUT_OTHERDATA;

!                     (*AH->PrintTocDataPtr) (AH, te);

                      AH->outputKind = OUTPUT_SQLCMDS;
                  }
                  else
                  {
!                     _disableTriggersIfNecessary(AH, te);

                      /* Select owner and schema as necessary */
                      _becomeOwner(AH, te);
*************** restore_toc_entry(ArchiveHandle *AH, Toc
*** 848,854 ****
                      else
                          AH->outputKind = OUTPUT_OTHERDATA;

!                     (*AH->PrintTocDataPtr) (AH, te, ropt);

                      /*
                       * Terminate COPY if needed.
--- 858,864 ----
                      else
                          AH->outputKind = OUTPUT_OTHERDATA;

!                     (*AH->PrintTocDataPtr) (AH, te);

                      /*
                       * Terminate COPY if needed.
*************** restore_toc_entry(ArchiveHandle *AH, Toc
*** 862,868 ****
                      if (is_parallel && te->created)
                          CommitTransaction(&AH->public);

!                     _enableTriggersIfNecessary(AH, te, ropt);
                  }
              }
          }
--- 872,878 ----
                      if (is_parallel && te->created)
                          CommitTransaction(&AH->public);

!                     _enableTriggersIfNecessary(AH, te);
                  }
              }
          }
*************** restore_toc_entry(ArchiveHandle *AH, Toc
*** 870,876 ****
          {
              /* If we haven't already dumped the defn part, do so now */
              ahlog(AH, 1, "executing %s %s\n", te->desc, te->tag);
!             _printTocEntry(AH, te, ropt, false, false);
          }
      }

--- 880,886 ----
          {
              /* If we haven't already dumped the defn part, do so now */
              ahlog(AH, 1, "executing %s %s\n", te->desc, te->tag);
!             _printTocEntry(AH, te, false, false);
          }
      }

*************** NewRestoreOptions(void)
*** 900,907 ****
  }

  static void
! _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
  {
      /* This hack is only needed in a data-only restore */
      if (!ropt->dataOnly || !ropt->disable_triggers)
          return;
--- 910,919 ----
  }

  static void
! _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te)
  {
+     RestoreOptions *ropt = AH->public.ropt;
+
      /* This hack is only needed in a data-only restore */
      if (!ropt->dataOnly || !ropt->disable_triggers)
          return;
*************** _disableTriggersIfNecessary(ArchiveHandl
*** 926,933 ****
  }

  static void
! _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
  {
      /* This hack is only needed in a data-only restore */
      if (!ropt->dataOnly || !ropt->disable_triggers)
          return;
--- 938,947 ----
  }

  static void
! _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te)
  {
+     RestoreOptions *ropt = AH->public.ropt;
+
      /* This hack is only needed in a data-only restore */
      if (!ropt->dataOnly || !ropt->disable_triggers)
          return;
*************** ArchiveEntry(Archive *AHX,
*** 1040,1048 ****

  /* Public */
  void
! PrintTOCSummary(Archive *AHX, RestoreOptions *ropt)
  {
      ArchiveHandle *AH = (ArchiveHandle *) AHX;
      TocEntry   *te;
      teSection    curSection;
      OutputContext sav;
--- 1054,1063 ----

  /* Public */
  void
! PrintTOCSummary(Archive *AHX)
  {
      ArchiveHandle *AH = (ArchiveHandle *) AHX;
+     RestoreOptions *ropt = AH->public.ropt;
      TocEntry   *te;
      teSection    curSection;
      OutputContext sav;
*************** EndBlob(Archive *AHX, Oid oid)
*** 1159,1165 ****
  void
  StartRestoreBlobs(ArchiveHandle *AH)
  {
!     if (!AH->ropt->single_txn)
      {
          if (AH->connection)
              StartTransaction(&AH->public);
--- 1174,1182 ----
  void
  StartRestoreBlobs(ArchiveHandle *AH)
  {
!     RestoreOptions *ropt = AH->public.ropt;
!
!     if (!ropt->single_txn)
      {
          if (AH->connection)
              StartTransaction(&AH->public);
*************** StartRestoreBlobs(ArchiveHandle *AH)
*** 1176,1182 ****
  void
  EndRestoreBlobs(ArchiveHandle *AH)
  {
!     if (!AH->ropt->single_txn)
      {
          if (AH->connection)
              CommitTransaction(&AH->public);
--- 1193,1201 ----
  void
  EndRestoreBlobs(ArchiveHandle *AH)
  {
!     RestoreOptions *ropt = AH->public.ropt;
!
!     if (!ropt->single_txn)
      {
          if (AH->connection)
              CommitTransaction(&AH->public);
*************** EndRestoreBlob(ArchiveHandle *AH, Oid oi
*** 1265,1273 ****
   ***********/

  void
! SortTocFromFile(Archive *AHX, RestoreOptions *ropt)
  {
      ArchiveHandle *AH = (ArchiveHandle *) AHX;
      FILE       *fh;
      char        buf[100];
      bool        incomplete_line;
--- 1284,1293 ----
   ***********/

  void
! SortTocFromFile(Archive *AHX)
  {
      ArchiveHandle *AH = (ArchiveHandle *) AHX;
+     RestoreOptions *ropt = AH->public.ropt;
      FILE       *fh;
      char        buf[100];
      bool        incomplete_line;
*************** ahlog(ArchiveHandle *AH, int level, cons
*** 1550,1556 ****
  static int
  RestoringToDB(ArchiveHandle *AH)
  {
!     return (AH->ropt && AH->ropt->useDB && AH->connection);
  }

  /*
--- 1570,1578 ----
  static int
  RestoringToDB(ArchiveHandle *AH)
  {
!     RestoreOptions *ropt = AH->public.ropt;
!
!     return (ropt && ropt->useDB && AH->connection);
  }

  /*
*************** _allocAH(const char *FileSpec, const Arc
*** 2303,2309 ****
  }

  void
! WriteDataChunks(ArchiveHandle *AH, DumpOptions *dopt, ParallelState *pstate)
  {
      TocEntry   *te;

--- 2325,2331 ----
  }

  void
! WriteDataChunks(ArchiveHandle *AH, ParallelState *pstate)
  {
      TocEntry   *te;

*************** WriteDataChunks(ArchiveHandle *AH, DumpO
*** 2326,2338 ****
              DispatchJobForTocEntry(AH, pstate, te, ACT_DUMP);
          }
          else
!             WriteDataChunksForTocEntry(AH, dopt, te);
      }
      EnsureWorkersFinished(AH, pstate);
  }

  void
! WriteDataChunksForTocEntry(ArchiveHandle *AH, DumpOptions *dopt, TocEntry *te)
  {
      StartDataPtr startPtr;
      EndDataPtr    endPtr;
--- 2348,2360 ----
              DispatchJobForTocEntry(AH, pstate, te, ACT_DUMP);
          }
          else
!             WriteDataChunksForTocEntry(AH, te);
      }
      EnsureWorkersFinished(AH, pstate);
  }

  void
! WriteDataChunksForTocEntry(ArchiveHandle *AH, TocEntry *te)
  {
      StartDataPtr startPtr;
      EndDataPtr    endPtr;
*************** WriteDataChunksForTocEntry(ArchiveHandle
*** 2356,2362 ****
      /*
       * The user-provided DataDumper routine needs to call AH->WriteData
       */
!     (*te->dataDumper) ((Archive *) AH, dopt, te->dataDumperArg);

      if (endPtr != NULL)
          (*endPtr) (AH, te);
--- 2378,2384 ----
      /*
       * The user-provided DataDumper routine needs to call AH->WriteData
       */
!     (*te->dataDumper) ((Archive *) AH, te->dataDumperArg);

      if (endPtr != NULL)
          (*endPtr) (AH, te);
*************** _tocEntryIsACL(TocEntry *te)
*** 2827,2832 ****
--- 2849,2856 ----
  static void
  _doSetFixedOutputState(ArchiveHandle *AH)
  {
+     RestoreOptions *ropt = AH->public.ropt;
+
      /* Disable statement_timeout since restore is probably slow */
      ahprintf(AH, "SET statement_timeout = 0;\n");

*************** _doSetFixedOutputState(ArchiveHandle *AH
*** 2842,2849 ****
               AH->public.std_strings ? "on" : "off");

      /* Select the role to be used during restore */
!     if (AH->ropt && AH->ropt->use_role)
!         ahprintf(AH, "SET ROLE %s;\n", fmtId(AH->ropt->use_role));

      /* Make sure function checking is disabled */
      ahprintf(AH, "SET check_function_bodies = false;\n");
--- 2866,2873 ----
               AH->public.std_strings ? "on" : "off");

      /* Select the role to be used during restore */
!     if (ropt && ropt->use_role)
!         ahprintf(AH, "SET ROLE %s;\n", fmtId(ropt->use_role));

      /* Make sure function checking is disabled */
      ahprintf(AH, "SET check_function_bodies = false;\n");
*************** _doSetFixedOutputState(ArchiveHandle *AH
*** 2854,2860 ****
          ahprintf(AH, "SET escape_string_warning = off;\n");

      /* Adjust row-security state */
!     if (AH->ropt && AH->ropt->enable_row_security)
          ahprintf(AH, "SET row_security = on;\n");
      else
          ahprintf(AH, "SET row_security = off;\n");
--- 2878,2884 ----
          ahprintf(AH, "SET escape_string_warning = off;\n");

      /* Adjust row-security state */
!     if (ropt && ropt->enable_row_security)
          ahprintf(AH, "SET row_security = on;\n");
      else
          ahprintf(AH, "SET row_security = off;\n");
*************** _becomeUser(ArchiveHandle *AH, const cha
*** 3012,3018 ****
  static void
  _becomeOwner(ArchiveHandle *AH, TocEntry *te)
  {
!     if (AH->ropt && (AH->ropt->noOwner || !AH->ropt->use_setsessauth))
          return;

      _becomeUser(AH, te->owner);
--- 3036,3044 ----
  static void
  _becomeOwner(ArchiveHandle *AH, TocEntry *te)
  {
!     RestoreOptions *ropt = AH->public.ropt;
!
!     if (ropt && (ropt->noOwner || !ropt->use_setsessauth))
          return;

      _becomeUser(AH, te->owner);
*************** _selectOutputSchema(ArchiveHandle *AH, c
*** 3083,3094 ****
  static void
  _selectTablespace(ArchiveHandle *AH, const char *tablespace)
  {
      PQExpBuffer qry;
      const char *want,
                 *have;

      /* do nothing in --no-tablespaces mode */
!     if (AH->ropt->noTablespace)
          return;

      have = AH->currTablespace;
--- 3109,3121 ----
  static void
  _selectTablespace(ArchiveHandle *AH, const char *tablespace)
  {
+     RestoreOptions *ropt = AH->public.ropt;
      PQExpBuffer qry;
      const char *want,
                 *have;

      /* do nothing in --no-tablespaces mode */
!     if (ropt->noTablespace)
          return;

      have = AH->currTablespace;
*************** _getObjectDescription(PQExpBuffer buf, T
*** 3214,3221 ****
  }

  static void
! _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData, bool acl_pass)
  {
      /* ACLs are dumped only during acl pass */
      if (acl_pass)
      {
--- 3241,3250 ----
  }

  static void
! _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData, bool acl_pass)
  {
+     RestoreOptions *ropt = AH->public.ropt;
+
      /* ACLs are dumped only during acl pass */
      if (acl_pass)
      {
*************** dumpTimestamp(ArchiveHandle *AH, const c
*** 3624,3630 ****
  static void
  restore_toc_entries_prefork(ArchiveHandle *AH)
  {
-     RestoreOptions *ropt = AH->ropt;
      bool        skipped_some;
      TocEntry   *next_work_item;

--- 3653,3658 ----
*************** restore_toc_entries_prefork(ArchiveHandl
*** 3676,3682 ****
                next_work_item->dumpId,
                next_work_item->desc, next_work_item->tag);

!         (void) restore_toc_entry(AH, next_work_item, ropt, false);

          /* there should be no touch of ready_list here, so pass NULL */
          reduce_dependencies(AH, next_work_item, NULL);
--- 3704,3710 ----
                next_work_item->dumpId,
                next_work_item->desc, next_work_item->tag);

!         (void) restore_toc_entry(AH, next_work_item, false);

          /* there should be no touch of ready_list here, so pass NULL */
          reduce_dependencies(AH, next_work_item, NULL);
*************** restore_toc_entries_parallel(ArchiveHand
*** 3857,3863 ****
  static void
  restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list)
  {
!     RestoreOptions *ropt = AH->ropt;
      TocEntry   *te;

      ahlog(AH, 2, "entering restore_toc_entries_postfork\n");
--- 3885,3891 ----
  static void
  restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list)
  {
!     RestoreOptions *ropt = AH->public.ropt;
      TocEntry   *te;

      ahlog(AH, 2, "entering restore_toc_entries_postfork\n");
*************** restore_toc_entries_postfork(ArchiveHand
*** 3880,3886 ****
      {
          ahlog(AH, 1, "processing missed item %d %s %s\n",
                te->dumpId, te->desc, te->tag);
!         (void) restore_toc_entry(AH, te, ropt, false);
      }

      /* The ACLs will be handled back in RestoreArchive. */
--- 3908,3914 ----
      {
          ahlog(AH, 1, "processing missed item %d %s %s\n",
                te->dumpId, te->desc, te->tag);
!         (void) restore_toc_entry(AH, te, false);
      }

      /* The ACLs will be handled back in RestoreArchive. */
*************** parallel_restore(ParallelArgs *args)
*** 4045,4051 ****
  {
      ArchiveHandle *AH = args->AH;
      TocEntry   *te = args->te;
-     RestoreOptions *ropt = AH->ropt;
      int            status;

      _doSetFixedOutputState(AH);
--- 4073,4078 ----
*************** parallel_restore(ParallelArgs *args)
*** 4055,4061 ****
      AH->public.n_errors = 0;

      /* Restore the TOC item */
!     status = restore_toc_entry(AH, te, ropt, true);

      return status;
  }
--- 4082,4088 ----
      AH->public.n_errors = 0;

      /* Restore the TOC item */
!     status = restore_toc_entry(AH, te, true);

      return status;
  }
*************** CloneArchive(ArchiveHandle *AH)
*** 4417,4423 ****
       */
      if (AH->mode == archModeRead)
      {
!         RestoreOptions *ropt = AH->ropt;

          Assert(AH->connection == NULL);
          /* this also sets clone->connection */
--- 4444,4450 ----
       */
      if (AH->mode == archModeRead)
      {
!         RestoreOptions *ropt = AH->public.ropt;

          Assert(AH->connection == NULL);
          /* this also sets clone->connection */
diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h
index 620ada5..4aa7190 100644
*** a/src/bin/pg_dump/pg_backup_archiver.h
--- b/src/bin/pg_dump/pg_backup_archiver.h
*************** typedef enum T_Action
*** 136,142 ****
      ACT_RESTORE
  } T_Action;

! typedef void (*ClosePtr) (ArchiveHandle *AH, DumpOptions *dopt);
  typedef void (*ReopenPtr) (ArchiveHandle *AH);
  typedef void (*ArchiveEntryPtr) (ArchiveHandle *AH, TocEntry *te);

--- 136,142 ----
      ACT_RESTORE
  } T_Action;

! typedef void (*ClosePtr) (ArchiveHandle *AH);
  typedef void (*ReopenPtr) (ArchiveHandle *AH);
  typedef void (*ArchiveEntryPtr) (ArchiveHandle *AH, TocEntry *te);

*************** typedef void (*SaveArchivePtr) (ArchiveH
*** 157,169 ****
  typedef void (*WriteExtraTocPtr) (ArchiveHandle *AH, TocEntry *te);
  typedef void (*ReadExtraTocPtr) (ArchiveHandle *AH, TocEntry *te);
  typedef void (*PrintExtraTocPtr) (ArchiveHandle *AH, TocEntry *te);
! typedef void (*PrintTocDataPtr) (ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);

  typedef void (*ClonePtr) (ArchiveHandle *AH);
  typedef void (*DeClonePtr) (ArchiveHandle *AH);

  typedef char *(*WorkerJobRestorePtr) (ArchiveHandle *AH, TocEntry *te);
! typedef char *(*WorkerJobDumpPtr) (ArchiveHandle *AH, DumpOptions *dopt, TocEntry *te);
  typedef char *(*MasterStartParallelItemPtr) (ArchiveHandle *AH, TocEntry *te,
                                                           T_Action act);
  typedef int (*MasterEndParallelItemPtr) (ArchiveHandle *AH, TocEntry *te,
--- 157,169 ----
  typedef void (*WriteExtraTocPtr) (ArchiveHandle *AH, TocEntry *te);
  typedef void (*ReadExtraTocPtr) (ArchiveHandle *AH, TocEntry *te);
  typedef void (*PrintExtraTocPtr) (ArchiveHandle *AH, TocEntry *te);
! typedef void (*PrintTocDataPtr) (ArchiveHandle *AH, TocEntry *te);

  typedef void (*ClonePtr) (ArchiveHandle *AH);
  typedef void (*DeClonePtr) (ArchiveHandle *AH);

  typedef char *(*WorkerJobRestorePtr) (ArchiveHandle *AH, TocEntry *te);
! typedef char *(*WorkerJobDumpPtr) (ArchiveHandle *AH, TocEntry *te);
  typedef char *(*MasterStartParallelItemPtr) (ArchiveHandle *AH, TocEntry *te,
                                                           T_Action act);
  typedef int (*MasterEndParallelItemPtr) (ArchiveHandle *AH, TocEntry *te,
*************** struct _archiveHandle
*** 315,323 ****
      ArchiveMode mode;            /* File mode - r or w */
      void       *formatData;        /* Header data specific to file format */

-     RestoreOptions *ropt;        /* Used to check restore options in ahwrite
-                                  * etc */
-
      /* these vars track state to avoid sending redundant SET commands */
      char       *currUser;        /* current username, or NULL if unknown */
      char       *currSchema;        /* current schema, or NULL */
--- 315,320 ----
*************** extern void WriteHead(ArchiveHandle *AH)
*** 386,393 ****
  extern void ReadHead(ArchiveHandle *AH);
  extern void WriteToc(ArchiveHandle *AH);
  extern void ReadToc(ArchiveHandle *AH);
! extern void WriteDataChunks(ArchiveHandle *AH, DumpOptions *dopt, struct ParallelState *pstate);
! extern void WriteDataChunksForTocEntry(ArchiveHandle *AH, DumpOptions *dopt, TocEntry *te);
  extern ArchiveHandle *CloneArchive(ArchiveHandle *AH);
  extern void DeCloneArchive(ArchiveHandle *AH);

--- 383,390 ----
  extern void ReadHead(ArchiveHandle *AH);
  extern void WriteToc(ArchiveHandle *AH);
  extern void ReadToc(ArchiveHandle *AH);
! extern void WriteDataChunks(ArchiveHandle *AH, struct ParallelState *pstate);
! extern void WriteDataChunksForTocEntry(ArchiveHandle *AH, TocEntry *te);
  extern ArchiveHandle *CloneArchive(ArchiveHandle *AH);
  extern void DeCloneArchive(ArchiveHandle *AH);

diff --git a/src/bin/pg_dump/pg_backup_custom.c b/src/bin/pg_dump/pg_backup_custom.c
index ee05380..be6dbca 100644
*** a/src/bin/pg_dump/pg_backup_custom.c
--- b/src/bin/pg_dump/pg_backup_custom.c
*************** static int    _WriteByte(ArchiveHandle *AH,
*** 42,50 ****
  static int    _ReadByte(ArchiveHandle *);
  static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
  static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len);
! static void _CloseArchive(ArchiveHandle *AH, DumpOptions *dopt);
  static void _ReopenArchive(ArchiveHandle *AH);
! static void _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
  static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te);
  static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te);
  static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te);
--- 42,50 ----
  static int    _ReadByte(ArchiveHandle *);
  static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
  static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len);
! static void _CloseArchive(ArchiveHandle *AH);
  static void _ReopenArchive(ArchiveHandle *AH);
! static void _PrintTocData(ArchiveHandle *AH, TocEntry *te);
  static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te);
  static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te);
  static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te);
*************** _EndBlobs(ArchiveHandle *AH, TocEntry *t
*** 419,425 ****
   * Print data for a given TOC entry
   */
  static void
! _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
  {
      lclContext *ctx = (lclContext *) AH->formatData;
      lclTocEntry *tctx = (lclTocEntry *) te->formatData;
--- 419,425 ----
   * Print data for a given TOC entry
   */
  static void
! _PrintTocData(ArchiveHandle *AH, TocEntry *te)
  {
      lclContext *ctx = (lclContext *) AH->formatData;
      lclTocEntry *tctx = (lclTocEntry *) te->formatData;
*************** _PrintTocData(ArchiveHandle *AH, TocEntr
*** 500,506 ****
              break;

          case BLK_BLOBS:
!             _LoadBlobs(AH, ropt->dropSchema);
              break;

          default:                /* Always have a default */
--- 500,506 ----
              break;

          case BLK_BLOBS:
!             _LoadBlobs(AH, AH->public.ropt->dropSchema);
              break;

          default:                /* Always have a default */
*************** _ReadBuf(ArchiveHandle *AH, void *buf, s
*** 695,701 ****
   *
   */
  static void
! _CloseArchive(ArchiveHandle *AH, DumpOptions *dopt)
  {
      lclContext *ctx = (lclContext *) AH->formatData;
      pgoff_t        tpos;
--- 695,701 ----
   *
   */
  static void
! _CloseArchive(ArchiveHandle *AH)
  {
      lclContext *ctx = (lclContext *) AH->formatData;
      pgoff_t        tpos;
*************** _CloseArchive(ArchiveHandle *AH, DumpOpt
*** 710,716 ****
                            strerror(errno));
          WriteToc(AH);
          ctx->dataStart = _getFilePos(AH, ctx);
!         WriteDataChunks(AH, dopt, NULL);

          /*
           * If possible, re-write the TOC in order to update the data offset
--- 710,716 ----
                            strerror(errno));
          WriteToc(AH);
          ctx->dataStart = _getFilePos(AH, ctx);
!         WriteDataChunks(AH, NULL);

          /*
           * If possible, re-write the TOC in order to update the data offset
diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c
index 4ebdf04..727a7fe 100644
*** a/src/bin/pg_dump/pg_backup_directory.c
--- b/src/bin/pg_dump/pg_backup_directory.c
*************** static int    _WriteByte(ArchiveHandle *AH,
*** 72,80 ****
  static int    _ReadByte(ArchiveHandle *);
  static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
  static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len);
! static void _CloseArchive(ArchiveHandle *AH, DumpOptions *dopt);
  static void _ReopenArchive(ArchiveHandle *AH);
! static void _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);

  static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te);
  static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te);
--- 72,80 ----
  static int    _ReadByte(ArchiveHandle *);
  static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
  static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len);
! static void _CloseArchive(ArchiveHandle *AH);
  static void _ReopenArchive(ArchiveHandle *AH);
! static void _PrintTocData(ArchiveHandle *AH, TocEntry *te);

  static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te);
  static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te);
*************** static void _StartBlobs(ArchiveHandle *A
*** 84,90 ****
  static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
  static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
  static void _EndBlobs(ArchiveHandle *AH, TocEntry *te);
! static void _LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt);

  static void _Clone(ArchiveHandle *AH);
  static void _DeClone(ArchiveHandle *AH);
--- 84,90 ----
  static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
  static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
  static void _EndBlobs(ArchiveHandle *AH, TocEntry *te);
! static void _LoadBlobs(ArchiveHandle *AH);

  static void _Clone(ArchiveHandle *AH);
  static void _DeClone(ArchiveHandle *AH);
*************** static char *_MasterStartParallelItem(Ar
*** 93,99 ****
  static int _MasterEndParallelItem(ArchiveHandle *AH, TocEntry *te,
                         const char *str, T_Action act);
  static char *_WorkerJobRestoreDirectory(ArchiveHandle *AH, TocEntry *te);
! static char *_WorkerJobDumpDirectory(ArchiveHandle *AH, DumpOptions *dopt, TocEntry *te);

  static void setFilePath(ArchiveHandle *AH, char *buf,
              const char *relativeFilename);
--- 93,99 ----
  static int _MasterEndParallelItem(ArchiveHandle *AH, TocEntry *te,
                         const char *str, T_Action act);
  static char *_WorkerJobRestoreDirectory(ArchiveHandle *AH, TocEntry *te);
! static char *_WorkerJobDumpDirectory(ArchiveHandle *AH, TocEntry *te);

  static void setFilePath(ArchiveHandle *AH, char *buf,
              const char *relativeFilename);
*************** _EndData(ArchiveHandle *AH, TocEntry *te
*** 386,392 ****
   * Print data for a given file (can be a BLOB as well)
   */
  static void
! _PrintFileData(ArchiveHandle *AH, char *filename, RestoreOptions *ropt)
  {
      size_t        cnt;
      char       *buf;
--- 386,392 ----
   * Print data for a given file (can be a BLOB as well)
   */
  static void
! _PrintFileData(ArchiveHandle *AH, char *filename)
  {
      size_t        cnt;
      char       *buf;
*************** _PrintFileData(ArchiveHandle *AH, char *
*** 418,424 ****
   * Print data for a given TOC entry
  */
  static void
! _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
  {
      lclTocEntry *tctx = (lclTocEntry *) te->formatData;

--- 418,424 ----
   * Print data for a given TOC entry
  */
  static void
! _PrintTocData(ArchiveHandle *AH, TocEntry *te)
  {
      lclTocEntry *tctx = (lclTocEntry *) te->formatData;

*************** _PrintTocData(ArchiveHandle *AH, TocEntr
*** 426,443 ****
          return;

      if (strcmp(te->desc, "BLOBS") == 0)
!         _LoadBlobs(AH, ropt);
      else
      {
          char        fname[MAXPGPATH];

          setFilePath(AH, fname, tctx->filename);
!         _PrintFileData(AH, fname, ropt);
      }
  }

  static void
! _LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt)
  {
      Oid            oid;
      lclContext *ctx = (lclContext *) AH->formatData;
--- 426,443 ----
          return;

      if (strcmp(te->desc, "BLOBS") == 0)
!         _LoadBlobs(AH);
      else
      {
          char        fname[MAXPGPATH];

          setFilePath(AH, fname, tctx->filename);
!         _PrintFileData(AH, fname);
      }
  }

  static void
! _LoadBlobs(ArchiveHandle *AH)
  {
      Oid            oid;
      lclContext *ctx = (lclContext *) AH->formatData;
*************** _LoadBlobs(ArchiveHandle *AH, RestoreOpt
*** 465,473 ****
              exit_horribly(modulename, "invalid line in large object TOC file \"%s\": \"%s\"\n",
                            fname, line);

!         StartRestoreBlob(AH, oid, ropt->dropSchema);
          snprintf(path, MAXPGPATH, "%s/%s", ctx->directory, fname);
!         _PrintFileData(AH, path, ropt);
          EndRestoreBlob(AH, oid);
      }
      if (!cfeof(ctx->blobsTocFH))
--- 465,473 ----
              exit_horribly(modulename, "invalid line in large object TOC file \"%s\": \"%s\"\n",
                            fname, line);

!         StartRestoreBlob(AH, oid, AH->public.ropt->dropSchema);
          snprintf(path, MAXPGPATH, "%s/%s", ctx->directory, fname);
!         _PrintFileData(AH, path);
          EndRestoreBlob(AH, oid);
      }
      if (!cfeof(ctx->blobsTocFH))
*************** _ReadBuf(ArchiveHandle *AH, void *buf, s
*** 567,573 ****
   *        WriteDataChunks        to save all DATA & BLOBs.
   */
  static void
! _CloseArchive(ArchiveHandle *AH, DumpOptions *dopt)
  {
      lclContext *ctx = (lclContext *) AH->formatData;

--- 567,573 ----
   *        WriteDataChunks        to save all DATA & BLOBs.
   */
  static void
! _CloseArchive(ArchiveHandle *AH)
  {
      lclContext *ctx = (lclContext *) AH->formatData;

*************** _CloseArchive(ArchiveHandle *AH, DumpOpt
*** 579,585 ****
          setFilePath(AH, fname, "toc.dat");

          /* this will actually fork the processes for a parallel backup */
!         ctx->pstate = ParallelBackupStart(AH, dopt, NULL);

          /* The TOC is always created uncompressed */
          tocFH = cfopen_write(fname, PG_BINARY_W, 0);
--- 579,585 ----
          setFilePath(AH, fname, "toc.dat");

          /* this will actually fork the processes for a parallel backup */
!         ctx->pstate = ParallelBackupStart(AH);

          /* The TOC is always created uncompressed */
          tocFH = cfopen_write(fname, PG_BINARY_W, 0);
*************** _CloseArchive(ArchiveHandle *AH, DumpOpt
*** 600,606 ****
          if (cfclose(tocFH) != 0)
              exit_horribly(modulename, "could not close TOC file: %s\n",
                            strerror(errno));
!         WriteDataChunks(AH, dopt, ctx->pstate);

          ParallelBackupEnd(AH, ctx->pstate);
      }
--- 600,606 ----
          if (cfclose(tocFH) != 0)
              exit_horribly(modulename, "could not close TOC file: %s\n",
                            strerror(errno));
!         WriteDataChunks(AH, ctx->pstate);

          ParallelBackupEnd(AH, ctx->pstate);
      }
*************** _MasterStartParallelItem(ArchiveHandle *
*** 791,797 ****
   * function of the respective dump format.
   */
  static char *
! _WorkerJobDumpDirectory(ArchiveHandle *AH, DumpOptions *dopt, TocEntry *te)
  {
      /*
       * short fixed-size string + some ID so far, this needs to be malloc'ed
--- 791,797 ----
   * function of the respective dump format.
   */
  static char *
! _WorkerJobDumpDirectory(ArchiveHandle *AH, TocEntry *te)
  {
      /*
       * short fixed-size string + some ID so far, this needs to be malloc'ed
*************** _WorkerJobDumpDirectory(ArchiveHandle *A
*** 810,816 ****
       * succeed... A failure will be detected by the parent when the child dies
       * unexpectedly.
       */
!     WriteDataChunksForTocEntry(AH, dopt, te);

      snprintf(buf, buflen, "OK DUMP %d", te->dumpId);

--- 810,816 ----
       * succeed... A failure will be detected by the parent when the child dies
       * unexpectedly.
       */
!     WriteDataChunksForTocEntry(AH, te);

      snprintf(buf, buflen, "OK DUMP %d", te->dumpId);

diff --git a/src/bin/pg_dump/pg_backup_null.c b/src/bin/pg_dump/pg_backup_null.c
index 77cf3fd..848eed4 100644
*** a/src/bin/pg_dump/pg_backup_null.c
--- b/src/bin/pg_dump/pg_backup_null.c
*************** static void _WriteBlobData(ArchiveHandle
*** 33,40 ****
  static void _EndData(ArchiveHandle *AH, TocEntry *te);
  static int    _WriteByte(ArchiveHandle *AH, const int i);
  static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
! static void _CloseArchive(ArchiveHandle *AH, DumpOptions *dopt);
! static void _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
  static void _StartBlobs(ArchiveHandle *AH, TocEntry *te);
  static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
  static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
--- 33,40 ----
  static void _EndData(ArchiveHandle *AH, TocEntry *te);
  static int    _WriteByte(ArchiveHandle *AH, const int i);
  static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
! static void _CloseArchive(ArchiveHandle *AH);
! static void _PrintTocData(ArchiveHandle *AH, TocEntry *te);
  static void _StartBlobs(ArchiveHandle *AH, TocEntry *te);
  static void _StartBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
  static void _EndBlob(ArchiveHandle *AH, TocEntry *te, Oid oid);
*************** _StartBlob(ArchiveHandle *AH, TocEntry *
*** 149,155 ****
          exit_horribly(NULL, "invalid OID for large object\n");

      /* With an old archive we must do drop and create logic here */
!     if (old_blob_style && AH->ropt->dropSchema)
          DropBlobIfExists(AH, oid);

      if (old_blob_style)
--- 149,155 ----
          exit_horribly(NULL, "invalid OID for large object\n");

      /* With an old archive we must do drop and create logic here */
!     if (old_blob_style && AH->public.ropt->dropSchema)
          DropBlobIfExists(AH, oid);

      if (old_blob_style)
*************** _EndBlobs(ArchiveHandle *AH, TocEntry *t
*** 192,211 ****
   *------
   */
  static void
! _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
  {
      if (te->dataDumper)
      {
-         DumpOptions *dopt;
-
          AH->currToc = te;

          if (strcmp(te->desc, "BLOBS") == 0)
              _StartBlobs(AH, te);

!         dopt = dumpOptionsFromRestoreOptions(ropt);
!         (*te->dataDumper) ((Archive *) AH, dopt, te->dataDumperArg);
!         pg_free(dopt);

          if (strcmp(te->desc, "BLOBS") == 0)
              _EndBlobs(AH, te);
--- 192,207 ----
   *------
   */
  static void
! _PrintTocData(ArchiveHandle *AH, TocEntry *te)
  {
      if (te->dataDumper)
      {
          AH->currToc = te;

          if (strcmp(te->desc, "BLOBS") == 0)
              _StartBlobs(AH, te);

!         (*te->dataDumper) ((Archive *) AH, te->dataDumperArg);

          if (strcmp(te->desc, "BLOBS") == 0)
              _EndBlobs(AH, te);
*************** _WriteBuf(ArchiveHandle *AH, const void
*** 229,235 ****
  }

  static void
! _CloseArchive(ArchiveHandle *AH, DumpOptions *dopt)
  {
      /* Nothing to do */
  }
--- 225,231 ----
  }

  static void
! _CloseArchive(ArchiveHandle *AH)
  {
      /* Nothing to do */
  }
diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c
index c40dfe5..eb5bcbb 100644
*** a/src/bin/pg_dump/pg_backup_tar.c
--- b/src/bin/pg_dump/pg_backup_tar.c
*************** static int    _WriteByte(ArchiveHandle *AH,
*** 47,54 ****
  static int    _ReadByte(ArchiveHandle *);
  static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
  static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len);
! static void _CloseArchive(ArchiveHandle *AH, DumpOptions *dopt);
! static void _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
  static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te);
  static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te);
  static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te);
--- 47,54 ----
  static int    _ReadByte(ArchiveHandle *);
  static void _WriteBuf(ArchiveHandle *AH, const void *buf, size_t len);
  static void _ReadBuf(ArchiveHandle *AH, void *buf, size_t len);
! static void _CloseArchive(ArchiveHandle *AH);
! static void _PrintTocData(ArchiveHandle *AH, TocEntry *te);
  static void _WriteExtraToc(ArchiveHandle *AH, TocEntry *te);
  static void _ReadExtraToc(ArchiveHandle *AH, TocEntry *te);
  static void _PrintExtraToc(ArchiveHandle *AH, TocEntry *te);
*************** typedef struct
*** 100,106 ****
  /* translator: this is a module name */
  static const char *modulename = gettext_noop("tar archiver");

! static void _LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt);

  static TAR_MEMBER *tarOpen(ArchiveHandle *AH, const char *filename, char mode);
  static void tarClose(ArchiveHandle *AH, TAR_MEMBER *TH);
--- 100,106 ----
  /* translator: this is a module name */
  static const char *modulename = gettext_noop("tar archiver");

! static void _LoadBlobs(ArchiveHandle *AH);

  static TAR_MEMBER *tarOpen(ArchiveHandle *AH, const char *filename, char mode);
  static void tarClose(ArchiveHandle *AH, TAR_MEMBER *TH);
*************** _EndData(ArchiveHandle *AH, TocEntry *te
*** 632,638 ****
   * Print data for a given file
   */
  static void
! _PrintFileData(ArchiveHandle *AH, char *filename, RestoreOptions *ropt)
  {
      lclContext *ctx = (lclContext *) AH->formatData;
      char        buf[4096];
--- 632,638 ----
   * Print data for a given file
   */
  static void
! _PrintFileData(ArchiveHandle *AH, char *filename)
  {
      lclContext *ctx = (lclContext *) AH->formatData;
      char        buf[4096];
*************** _PrintFileData(ArchiveHandle *AH, char *
*** 659,665 ****
   * Print data for a given TOC entry
  */
  static void
! _PrintTocData(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
  {
      lclContext *ctx = (lclContext *) AH->formatData;
      lclTocEntry *tctx = (lclTocEntry *) te->formatData;
--- 659,665 ----
   * Print data for a given TOC entry
  */
  static void
! _PrintTocData(ArchiveHandle *AH, TocEntry *te)
  {
      lclContext *ctx = (lclContext *) AH->formatData;
      lclTocEntry *tctx = (lclTocEntry *) te->formatData;
*************** _PrintTocData(ArchiveHandle *AH, TocEntr
*** 708,720 ****
      }

      if (strcmp(te->desc, "BLOBS") == 0)
!         _LoadBlobs(AH, ropt);
      else
!         _PrintFileData(AH, tctx->filename, ropt);
  }

  static void
! _LoadBlobs(ArchiveHandle *AH, RestoreOptions *ropt)
  {
      Oid            oid;
      lclContext *ctx = (lclContext *) AH->formatData;
--- 708,720 ----
      }

      if (strcmp(te->desc, "BLOBS") == 0)
!         _LoadBlobs(AH);
      else
!         _PrintFileData(AH, tctx->filename);
  }

  static void
! _LoadBlobs(ArchiveHandle *AH)
  {
      Oid            oid;
      lclContext *ctx = (lclContext *) AH->formatData;
*************** _LoadBlobs(ArchiveHandle *AH, RestoreOpt
*** 737,743 ****
              {
                  ahlog(AH, 1, "restoring large object with OID %u\n", oid);

!                 StartRestoreBlob(AH, oid, ropt->dropSchema);

                  while ((cnt = tarRead(buf, 4095, th)) > 0)
                  {
--- 737,743 ----
              {
                  ahlog(AH, 1, "restoring large object with OID %u\n", oid);

!                 StartRestoreBlob(AH, oid, AH->public.ropt->dropSchema);

                  while ((cnt = tarRead(buf, 4095, th)) > 0)
                  {
*************** _ReadBuf(ArchiveHandle *AH, void *buf, s
*** 824,835 ****
  }

  static void
! _CloseArchive(ArchiveHandle *AH, DumpOptions *dopt)
  {
      lclContext *ctx = (lclContext *) AH->formatData;
      TAR_MEMBER *th;
      RestoreOptions *ropt;
      RestoreOptions *savRopt;
      int            savVerbose,
                  i;

--- 824,836 ----
  }

  static void
! _CloseArchive(ArchiveHandle *AH)
  {
      lclContext *ctx = (lclContext *) AH->formatData;
      TAR_MEMBER *th;
      RestoreOptions *ropt;
      RestoreOptions *savRopt;
+     DumpOptions *savDopt;
      int            savVerbose,
                  i;

*************** _CloseArchive(ArchiveHandle *AH, DumpOpt
*** 847,853 ****
          /*
           * Now send the data (tables & blobs)
           */
!         WriteDataChunks(AH, dopt, NULL);

          /*
           * Now this format wants to append a script which does a full restore
--- 848,854 ----
          /*
           * Now send the data (tables & blobs)
           */
!         WriteDataChunks(AH, NULL);

          /*
           * Now this format wants to append a script which does a full restore
*************** _CloseArchive(ArchiveHandle *AH, DumpOpt
*** 869,890 ****
          ctx->scriptTH = th;

          ropt = NewRestoreOptions();
!         memcpy(ropt, AH->ropt, sizeof(RestoreOptions));
          ropt->filename = NULL;
          ropt->dropSchema = 1;
          ropt->compression = 0;
          ropt->superuser = NULL;
          ropt->suppressDumpWarnings = true;

!         savRopt = AH->ropt;
!         AH->ropt = ropt;

          savVerbose = AH->public.verbose;
          AH->public.verbose = 0;

          RestoreArchive((Archive *) AH);

!         AH->ropt = savRopt;
          AH->public.verbose = savVerbose;

          tarClose(AH, th);
--- 870,894 ----
          ctx->scriptTH = th;

          ropt = NewRestoreOptions();
!         memcpy(ropt, AH->public.ropt, sizeof(RestoreOptions));
          ropt->filename = NULL;
          ropt->dropSchema = 1;
          ropt->compression = 0;
          ropt->superuser = NULL;
          ropt->suppressDumpWarnings = true;

!         savDopt = AH->public.dopt;
!         savRopt = AH->public.ropt;
!
!         SetArchiveOptions((Archive *) AH, NULL, ropt);

          savVerbose = AH->public.verbose;
          AH->public.verbose = 0;

          RestoreArchive((Archive *) AH);

!         SetArchiveOptions((Archive *) AH, savDopt, savRopt);
!
          AH->public.verbose = savVerbose;

          tarClose(AH, th);
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 56c0528..d68d782 100644
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
*************** char        g_comment_end[10];
*** 128,134 ****
  static const CatalogId nilCatalogId = {0, 0};

  static void help(const char *progname);
! static void setup_connection(Archive *AH, DumpOptions *dopt,
                   const char *dumpencoding, const char *dumpsnapshot,
                   char *use_role);
  static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
--- 128,134 ----
  static const CatalogId nilCatalogId = {0, 0};

  static void help(const char *progname);
! static void setup_connection(Archive *AH,
                   const char *dumpencoding, const char *dumpsnapshot,
                   char *use_role);
  static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
*************** static void expand_table_name_patterns(A
*** 141,206 ****
                             SimpleOidList *oids,
                             bool strict_names);
  static NamespaceInfo *findNamespace(Archive *fout, Oid nsoid, Oid objoid);
! static void dumpTableData(Archive *fout, DumpOptions *dopt, TableDataInfo *tdinfo);
  static void refreshMatViewData(Archive *fout, TableDataInfo *tdinfo);
  static void guessConstraintInheritance(TableInfo *tblinfo, int numTables);
! static void dumpComment(Archive *fout, DumpOptions *dopt, const char *target,
              const char *namespace, const char *owner,
              CatalogId catalogId, int subid, DumpId dumpId);
  static int findComments(Archive *fout, Oid classoid, Oid objoid,
               CommentItem **items);
  static int    collectComments(Archive *fout, CommentItem **items);
! static void dumpSecLabel(Archive *fout, DumpOptions *dopt, 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 int    collectSecLabels(Archive *fout, SecLabelItem **items);
! static void dumpDumpableObject(Archive *fout, DumpOptions *dopt, DumpableObject *dobj);
! static void dumpNamespace(Archive *fout, DumpOptions *dopt, NamespaceInfo *nspinfo);
! static void dumpExtension(Archive *fout, DumpOptions *dopt, ExtensionInfo *extinfo);
! static void dumpType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
! static void dumpBaseType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
! static void dumpEnumType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
! static void dumpRangeType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
! static void dumpUndefinedType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
! static void dumpDomain(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
! static void dumpCompositeType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo);
  static void dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo);
! static void dumpShellType(Archive *fout, DumpOptions *dopt, ShellTypeInfo *stinfo);
! static void dumpProcLang(Archive *fout, DumpOptions *dopt, ProcLangInfo *plang);
! static void dumpFunc(Archive *fout, DumpOptions *dopt, FuncInfo *finfo);
! static void dumpCast(Archive *fout, DumpOptions *dopt, CastInfo *cast);
! static void dumpTransform(Archive *fout, DumpOptions *dopt, TransformInfo *transform);
! static void dumpOpr(Archive *fout, DumpOptions *dopt, OprInfo *oprinfo);
! static void dumpOpclass(Archive *fout, DumpOptions *dopt, OpclassInfo *opcinfo);
! static void dumpOpfamily(Archive *fout, DumpOptions *dopt, OpfamilyInfo *opfinfo);
! static void dumpCollation(Archive *fout, DumpOptions *dopt, CollInfo *convinfo);
! static void dumpConversion(Archive *fout, DumpOptions *dopt, ConvInfo *convinfo);
! static void dumpRule(Archive *fout, DumpOptions *dopt, RuleInfo *rinfo);
! static void dumpAgg(Archive *fout, DumpOptions *dopt, AggInfo *agginfo);
! static void dumpTrigger(Archive *fout, DumpOptions *dopt, TriggerInfo *tginfo);
! static void dumpEventTrigger(Archive *fout, DumpOptions *dopt, EventTriggerInfo *evtinfo);
! static void dumpTable(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo);
! static void dumpTableSchema(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo);
! static void dumpAttrDef(Archive *fout, DumpOptions *dopt, AttrDefInfo *adinfo);
! static void dumpSequence(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo);
  static void dumpSequenceData(Archive *fout, TableDataInfo *tdinfo);
! static void dumpIndex(Archive *fout, DumpOptions *dopt, IndxInfo *indxinfo);
! static void dumpConstraint(Archive *fout, DumpOptions *dopt, ConstraintInfo *coninfo);
! static void dumpTableConstraintComment(Archive *fout, DumpOptions *dopt, ConstraintInfo *coninfo);
! static void dumpTSParser(Archive *fout, DumpOptions *dopt, TSParserInfo *prsinfo);
! static void dumpTSDictionary(Archive *fout, DumpOptions *dopt, TSDictInfo *dictinfo);
! static void dumpTSTemplate(Archive *fout, DumpOptions *dopt, TSTemplateInfo *tmplinfo);
! static void dumpTSConfig(Archive *fout, DumpOptions *dopt, TSConfigInfo *cfginfo);
! static void dumpForeignDataWrapper(Archive *fout, DumpOptions *dopt, FdwInfo *fdwinfo);
! static void dumpForeignServer(Archive *fout, DumpOptions *dopt, ForeignServerInfo *srvinfo);
  static void dumpUserMappings(Archive *fout,
                   const char *servername, const char *namespace,
                   const char *owner, CatalogId catalogId, DumpId dumpId);
! static void dumpDefaultACL(Archive *fout, DumpOptions *dopt, DefaultACLInfo *daclinfo);

! static void dumpACL(Archive *fout, DumpOptions *dopt, 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);
--- 141,206 ----
                             SimpleOidList *oids,
                             bool strict_names);
  static NamespaceInfo *findNamespace(Archive *fout, Oid nsoid, Oid objoid);
! 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 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 int    collectSecLabels(Archive *fout, SecLabelItem **items);
! static void dumpDumpableObject(Archive *fout, DumpableObject *dobj);
! static void dumpNamespace(Archive *fout, NamespaceInfo *nspinfo);
! static void dumpExtension(Archive *fout, ExtensionInfo *extinfo);
! static void dumpType(Archive *fout, TypeInfo *tyinfo);
! static void dumpBaseType(Archive *fout, TypeInfo *tyinfo);
! static void dumpEnumType(Archive *fout, TypeInfo *tyinfo);
! static void dumpRangeType(Archive *fout, TypeInfo *tyinfo);
! static void dumpUndefinedType(Archive *fout, TypeInfo *tyinfo);
! static void dumpDomain(Archive *fout, TypeInfo *tyinfo);
! static void dumpCompositeType(Archive *fout, TypeInfo *tyinfo);
  static void dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo);
! static void dumpShellType(Archive *fout, ShellTypeInfo *stinfo);
! static void dumpProcLang(Archive *fout, ProcLangInfo *plang);
! static void dumpFunc(Archive *fout, FuncInfo *finfo);
! static void dumpCast(Archive *fout, CastInfo *cast);
! static void dumpTransform(Archive *fout, TransformInfo *transform);
! static void dumpOpr(Archive *fout, OprInfo *oprinfo);
! static void dumpOpclass(Archive *fout, OpclassInfo *opcinfo);
! static void dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo);
! static void dumpCollation(Archive *fout, CollInfo *convinfo);
! static void dumpConversion(Archive *fout, ConvInfo *convinfo);
! static void dumpRule(Archive *fout, RuleInfo *rinfo);
! static void dumpAgg(Archive *fout, AggInfo *agginfo);
! static void dumpTrigger(Archive *fout, TriggerInfo *tginfo);
! static void dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo);
! static void dumpTable(Archive *fout, TableInfo *tbinfo);
! static void dumpTableSchema(Archive *fout, TableInfo *tbinfo);
! static void dumpAttrDef(Archive *fout, AttrDefInfo *adinfo);
! static void dumpSequence(Archive *fout, TableInfo *tbinfo);
  static void dumpSequenceData(Archive *fout, TableDataInfo *tdinfo);
! static void dumpIndex(Archive *fout, IndxInfo *indxinfo);
! static void dumpConstraint(Archive *fout, ConstraintInfo *coninfo);
! static void dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo);
! static void dumpTSParser(Archive *fout, TSParserInfo *prsinfo);
! static void dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo);
! static void dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo);
! static void dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo);
! static void 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);
! 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);
*************** static void selectSourceSchema(Archive *
*** 238,247 ****
  static char *getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts);
  static char *myFormatType(const char *typname, int32 typmod);
  static void getBlobs(Archive *fout);
! static void dumpBlob(Archive *fout, DumpOptions *dopt, BlobInfo *binfo);
! static int    dumpBlobs(Archive *fout, DumpOptions *dopt, void *arg);
! static void dumpPolicy(Archive *fout, DumpOptions *dopt, PolicyInfo *polinfo);
! static void dumpDatabase(Archive *AH, DumpOptions *dopt);
  static void dumpEncoding(Archive *AH);
  static void dumpStdStrings(Archive *AH);
  static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
--- 238,247 ----
  static char *getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts);
  static char *myFormatType(const char *typname, int32 typmod);
  static void getBlobs(Archive *fout);
! static void dumpBlob(Archive *fout, BlobInfo *binfo);
! static int    dumpBlobs(Archive *fout, void *arg);
! static void dumpPolicy(Archive *fout, PolicyInfo *polinfo);
! static void dumpDatabase(Archive *AH);
  static void dumpEncoding(Archive *AH);
  static void dumpStdStrings(Archive *AH);
  static void binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
*************** static void fmtReloptionsArray(Archive *
*** 261,267 ****
                     const char *reloptions, const char *prefix);
  static char *get_synchronized_snapshot(Archive *fout);
  static PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, char *query);
! static void setupDumpWorker(Archive *AHX, DumpOptions *dopt, RestoreOptions *ropt);


  int
--- 261,267 ----
                     const char *reloptions, const char *prefix);
  static char *get_synchronized_snapshot(Archive *fout);
  static PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, char *query);
! static void setupDumpWorker(Archive *AHX);


  int
*************** main(int argc, char **argv)
*** 611,616 ****
--- 611,619 ----
      fout = CreateArchive(filename, archiveFormat, compressLevel, archiveMode,
                           setupDumpWorker);

+     /* Make dump options accessible right away */
+     SetArchiveOptions(fout, &dopt, NULL);
+
      /* Register the cleanup hook */
      on_exit_close_archive(fout);

*************** main(int argc, char **argv)
*** 634,640 ****
       * death.
       */
      ConnectDatabase(fout, dopt.dbname, dopt.pghost, dopt.pgport, dopt.username, prompt_password);
!     setup_connection(fout, &dopt, dumpencoding, dumpsnapshot, use_role);

      /*
       * Disable security label support if server version < v9.1.x (prevents
--- 637,643 ----
       * death.
       */
      ConnectDatabase(fout, dopt.dbname, dopt.pghost, dopt.pgport, dopt.username, prompt_password);
!     setup_connection(fout, dumpencoding, dumpsnapshot, use_role);

      /*
       * Disable security label support if server version < v9.1.x (prevents
*************** main(int argc, char **argv)
*** 739,745 ****
       * Now scan the database and create DumpableObject structs for all the
       * objects we intend to dump.
       */
!     tblinfo = getSchemaData(fout, &dopt, &numTables);

      if (fout->remoteVersion < 80400)
          guessConstraintInheritance(tblinfo, numTables);
--- 742,748 ----
       * Now scan the database and create DumpableObject structs for all the
       * objects we intend to dump.
       */
!     tblinfo = getSchemaData(fout, &numTables);

      if (fout->remoteVersion < 80400)
          guessConstraintInheritance(tblinfo, numTables);
*************** main(int argc, char **argv)
*** 803,813 ****

      /* The database item is always next, unless we don't want it at all */
      if (dopt.include_everything && !dopt.dataOnly)
!         dumpDatabase(fout, &dopt);

      /* Now the rearrangeable objects. */
      for (i = 0; i < numObjs; i++)
!         dumpDumpableObject(fout, &dopt, dobjs[i]);

      /*
       * Set up options info to ensure we dump what we want.
--- 806,816 ----

      /* The database item is always next, unless we don't want it at all */
      if (dopt.include_everything && !dopt.dataOnly)
!         dumpDatabase(fout);

      /* Now the rearrangeable objects. */
      for (i = 0; i < numObjs; i++)
!         dumpDumpableObject(fout, dobjs[i]);

      /*
       * Set up options info to ensure we dump what we want.
*************** main(int argc, char **argv)
*** 843,849 ****

      ropt->suppressDumpWarnings = true;    /* We've already shown them */

!     SetArchiveRestoreOptions(fout, ropt);

      /*
       * The archive's TOC entries are now marked as to which ones will actually
--- 846,855 ----

      ropt->suppressDumpWarnings = true;    /* We've already shown them */

!     SetArchiveOptions(fout, &dopt, ropt);
!
!     /* Mark which entries should be output */
!     ProcessArchiveRestoreOptions(fout);

      /*
       * The archive's TOC entries are now marked as to which ones will actually
*************** main(int argc, char **argv)
*** 863,869 ****
      if (plainText)
          RestoreArchive(fout);

!     CloseArchive(fout, &dopt);

      exit_nicely(0);
  }
--- 869,875 ----
      if (plainText)
          RestoreArchive(fout);

!     CloseArchive(fout);

      exit_nicely(0);
  }
*************** help(const char *progname)
*** 941,949 ****
  }

  static void
! setup_connection(Archive *AH, DumpOptions *dopt, const char *dumpencoding,
                   const char *dumpsnapshot, char *use_role)
  {
      PGconn       *conn = GetConnection(AH);
      const char *std_strings;

--- 947,956 ----
  }

  static void
! setup_connection(Archive *AH, const char *dumpencoding,
                   const char *dumpsnapshot, char *use_role)
  {
+     DumpOptions *dopt = AH->dopt;
      PGconn       *conn = GetConnection(AH);
      const char *std_strings;

*************** setup_connection(Archive *AH, DumpOption
*** 1092,1100 ****
  }

  static void
! setupDumpWorker(Archive *AHX, DumpOptions *dopt, RestoreOptions *ropt)
  {
!     setup_connection(AHX, dopt, NULL, NULL, NULL);
  }

  static char *
--- 1099,1107 ----
  }

  static void
! setupDumpWorker(Archive *AHX)
  {
!     setup_connection(AHX, NULL, NULL, NULL);
  }

  static char *
*************** selectDumpableObject(DumpableObject *dob
*** 1437,1443 ****
   */

  static int
! dumpTableData_copy(Archive *fout, DumpOptions *dopt, void *dcontext)
  {
      TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
      TableInfo  *tbinfo = tdinfo->tdtable;
--- 1444,1450 ----
   */

  static int
! dumpTableData_copy(Archive *fout, void *dcontext)
  {
      TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
      TableInfo  *tbinfo = tdinfo->tdtable;
*************** dumpTableData_copy(Archive *fout, DumpOp
*** 1612,1622 ****
   * E'' strings, or dollar-quoted strings.  So don't emit anything like that.
   */
  static int
! dumpTableData_insert(Archive *fout, DumpOptions *dopt, void *dcontext)
  {
      TableDataInfo *tdinfo = (TableDataInfo *) dcontext;
      TableInfo  *tbinfo = tdinfo->tdtable;
      const char *classname = tbinfo->dobj.name;
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer insertStmt = NULL;
      PGresult   *res;
--- 1619,1630 ----
   * E'' strings, or dollar-quoted strings.  So don't emit anything like that.
   */
  static int
! 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;
*************** dumpTableData_insert(Archive *fout, Dump
*** 1798,1805 ****
   * Actually, this just makes an ArchiveEntry for the table contents.
   */
  static void
! dumpTableData(Archive *fout, DumpOptions *dopt, TableDataInfo *tdinfo)
  {
      TableInfo  *tbinfo = tdinfo->tdtable;
      PQExpBuffer copyBuf = createPQExpBuffer();
      PQExpBuffer clistBuf = createPQExpBuffer();
--- 1806,1814 ----
   * Actually, this just makes an ArchiveEntry for the table contents.
   */
  static void
! dumpTableData(Archive *fout, TableDataInfo *tdinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      TableInfo  *tbinfo = tdinfo->tdtable;
      PQExpBuffer copyBuf = createPQExpBuffer();
      PQExpBuffer clistBuf = createPQExpBuffer();
*************** guessConstraintInheritance(TableInfo *tb
*** 2201,2208 ****
   *    dump the database definition
   */
  static void
! dumpDatabase(Archive *fout, DumpOptions *dopt)
  {
      PQExpBuffer dbQry = createPQExpBuffer();
      PQExpBuffer delQry = createPQExpBuffer();
      PQExpBuffer creaQry = createPQExpBuffer();
--- 2210,2218 ----
   *    dump the database definition
   */
  static void
! dumpDatabase(Archive *fout)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer dbQry = createPQExpBuffer();
      PQExpBuffer delQry = createPQExpBuffer();
      PQExpBuffer creaQry = createPQExpBuffer();
*************** dumpDatabase(Archive *fout, DumpOptions
*** 2522,2528 ****
      {
          resetPQExpBuffer(dbQry);
          appendPQExpBuffer(dbQry, "DATABASE %s", fmtId(datname));
!         dumpComment(fout, dopt, dbQry->data, NULL, "",
                      dbCatId, 0, dbDumpId);
      }

--- 2532,2538 ----
      {
          resetPQExpBuffer(dbQry);
          appendPQExpBuffer(dbQry, "DATABASE %s", fmtId(datname));
!         dumpComment(fout, dbQry->data, NULL, "",
                      dbCatId, 0, dbDumpId);
      }

*************** getBlobs(Archive *fout)
*** 2693,2699 ****
   * dump the definition (metadata) of the given large object
   */
  static void
! dumpBlob(Archive *fout, DumpOptions *dopt, BlobInfo *binfo)
  {
      PQExpBuffer cquery = createPQExpBuffer();
      PQExpBuffer dquery = createPQExpBuffer();
--- 2703,2709 ----
   * dump the definition (metadata) of the given large object
   */
  static void
! dumpBlob(Archive *fout, BlobInfo *binfo)
  {
      PQExpBuffer cquery = createPQExpBuffer();
      PQExpBuffer dquery = createPQExpBuffer();
*************** dumpBlob(Archive *fout, DumpOptions *dop
*** 2720,2737 ****
      appendPQExpBuffer(cquery, "LARGE OBJECT %s", binfo->dobj.name);

      /* Dump comment if any */
!     dumpComment(fout, dopt, cquery->data,
                  NULL, binfo->rolname,
                  binfo->dobj.catId, 0, binfo->dobj.dumpId);

      /* Dump security label if any */
!     dumpSecLabel(fout, dopt, cquery->data,
                   NULL, binfo->rolname,
                   binfo->dobj.catId, 0, binfo->dobj.dumpId);

      /* Dump ACL if any */
      if (binfo->blobacl)
!         dumpACL(fout, dopt, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT",
                  binfo->dobj.name, NULL, cquery->data,
                  NULL, binfo->rolname, binfo->blobacl);

--- 2730,2747 ----
      appendPQExpBuffer(cquery, "LARGE OBJECT %s", binfo->dobj.name);

      /* Dump comment if any */
!     dumpComment(fout, cquery->data,
                  NULL, binfo->rolname,
                  binfo->dobj.catId, 0, binfo->dobj.dumpId);

      /* Dump security label if any */
!     dumpSecLabel(fout, cquery->data,
                   NULL, binfo->rolname,
                   binfo->dobj.catId, 0, binfo->dobj.dumpId);

      /* Dump ACL if any */
      if (binfo->blobacl)
!         dumpACL(fout, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT",
                  binfo->dobj.name, NULL, cquery->data,
                  NULL, binfo->rolname, binfo->blobacl);

*************** dumpBlob(Archive *fout, DumpOptions *dop
*** 2744,2750 ****
   *    dump the data contents of all large objects
   */
  static int
! dumpBlobs(Archive *fout, DumpOptions *dopt, void *arg)
  {
      const char *blobQry;
      const char *blobFetchQry;
--- 2754,2760 ----
   *    dump the data contents of all large objects
   */
  static int
! dumpBlobs(Archive *fout, void *arg)
  {
      const char *blobQry;
      const char *blobFetchQry;
*************** getPolicies(Archive *fout, TableInfo tbl
*** 2968,2975 ****
   *      dump the definition of the given policy
   */
  static void
! dumpPolicy(Archive *fout, DumpOptions *dopt, PolicyInfo *polinfo)
  {
      TableInfo  *tbinfo = polinfo->poltable;
      PQExpBuffer query;
      PQExpBuffer delqry;
--- 2978,2986 ----
   *      dump the definition of the given policy
   */
  static void
! dumpPolicy(Archive *fout, PolicyInfo *polinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      TableInfo  *tbinfo = polinfo->poltable;
      PQExpBuffer query;
      PQExpBuffer delqry;
*************** findNamespace(Archive *fout, Oid nsoid,
*** 3390,3397 ****
   *    numExtensions is set to the number of extensions read in
   */
  ExtensionInfo *
! getExtensions(Archive *fout, DumpOptions *dopt, int *numExtensions)
  {
      PGresult   *res;
      int            ntups;
      int            i;
--- 3401,3409 ----
   *    numExtensions is set to the number of extensions read in
   */
  ExtensionInfo *
! getExtensions(Archive *fout, int *numExtensions)
  {
+     DumpOptions *dopt = fout->dopt;
      PGresult   *res;
      int            ntups;
      int            i;
*************** getOpfamilies(Archive *fout, int *numOpf
*** 4205,4212 ****
   * numAggs is set to the number of aggregates read in
   */
  AggInfo *
! getAggregates(Archive *fout, DumpOptions *dopt, int *numAggs)
  {
      PGresult   *res;
      int            ntups;
      int            i;
--- 4217,4225 ----
   * numAggs is set to the number of aggregates read in
   */
  AggInfo *
! getAggregates(Archive *fout, int *numAggs)
  {
+     DumpOptions *dopt = fout->dopt;
      PGresult   *res;
      int            ntups;
      int            i;
*************** getAggregates(Archive *fout, DumpOptions
*** 4362,4369 ****
   * numFuncs is set to the number of functions read in
   */
  FuncInfo *
! getFuncs(Archive *fout, DumpOptions *dopt, int *numFuncs)
  {
      PGresult   *res;
      int            ntups;
      int            i;
--- 4375,4383 ----
   * numFuncs is set to the number of functions read in
   */
  FuncInfo *
! getFuncs(Archive *fout, int *numFuncs)
  {
+     DumpOptions *dopt = fout->dopt;
      PGresult   *res;
      int            ntups;
      int            i;
*************** getFuncs(Archive *fout, DumpOptions *dop
*** 4524,4531 ****
   * numTables is set to the number of tables read in
   */
  TableInfo *
! getTables(Archive *fout, DumpOptions *dopt, int *numTables)
  {
      PGresult   *res;
      int            ntups;
      int            i;
--- 4538,4546 ----
   * numTables is set to the number of tables read in
   */
  TableInfo *
! getTables(Archive *fout, int *numTables)
  {
+     DumpOptions *dopt = fout->dopt;
      PGresult   *res;
      int            ntups;
      int            i;
*************** getProcLangs(Archive *fout, int *numProc
*** 6493,6500 ****
   * numCasts is set to the number of casts read in
   */
  CastInfo *
! getCasts(Archive *fout, DumpOptions *dopt, int *numCasts)
  {
      PGresult   *res;
      int            ntups;
      int            i;
--- 6508,6516 ----
   * numCasts is set to the number of casts read in
   */
  CastInfo *
! getCasts(Archive *fout, int *numCasts)
  {
+     DumpOptions *dopt = fout->dopt;
      PGresult   *res;
      int            ntups;
      int            i;
*************** getTransforms(Archive *fout, int *numTra
*** 6731,6738 ****
   *    modifies tblinfo
   */
  void
! getTableAttrs(Archive *fout, DumpOptions *dopt, TableInfo *tblinfo, int numTables)
  {
      int            i,
                  j;
      PQExpBuffer q = createPQExpBuffer();
--- 6747,6755 ----
   *    modifies tblinfo
   */
  void
! getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
  {
+     DumpOptions *dopt = fout->dopt;
      int            i,
                  j;
      PQExpBuffer q = createPQExpBuffer();
*************** getForeignServers(Archive *fout, int *nu
*** 7847,7854 ****
   *    numDefaultACLs is set to the number of ACLs read in
   */
  DefaultACLInfo *
! getDefaultACLs(Archive *fout, DumpOptions *dopt, int *numDefaultACLs)
  {
      DefaultACLInfo *daclinfo;
      PQExpBuffer query;
      PGresult   *res;
--- 7864,7872 ----
   *    numDefaultACLs is set to the number of ACLs read in
   */
  DefaultACLInfo *
! getDefaultACLs(Archive *fout, int *numDefaultACLs)
  {
+     DumpOptions *dopt = fout->dopt;
      DefaultACLInfo *daclinfo;
      PQExpBuffer query;
      PGresult   *res;
*************** getDefaultACLs(Archive *fout, DumpOption
*** 7945,7954 ****
   * calling ArchiveEntry() for the specified object.
   */
  static void
! dumpComment(Archive *fout, DumpOptions *dopt, const char *target,
              const char *namespace, const char *owner,
              CatalogId catalogId, int subid, DumpId dumpId)
  {
      CommentItem *comments;
      int            ncomments;

--- 7963,7973 ----
   * calling ArchiveEntry() for the specified object.
   */
  static void
! dumpComment(Archive *fout, const char *target,
              const char *namespace, const char *owner,
              CatalogId catalogId, int subid, DumpId dumpId)
  {
+     DumpOptions *dopt = fout->dopt;
      CommentItem *comments;
      int            ncomments;

*************** dumpComment(Archive *fout, DumpOptions *
*** 8009,8017 ****
   * and its columns.
   */
  static void
! dumpTableComment(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo,
                   const char *reltypename)
  {
      CommentItem *comments;
      int            ncomments;
      PQExpBuffer query;
--- 8028,8037 ----
   * and its columns.
   */
  static void
! dumpTableComment(Archive *fout, TableInfo *tbinfo,
                   const char *reltypename)
  {
+     DumpOptions *dopt = fout->dopt;
      CommentItem *comments;
      int            ncomments;
      PQExpBuffer query;
*************** collectComments(Archive *fout, CommentIt
*** 8263,8373 ****
   * ArchiveEntries (TOC objects) for each object to be dumped.
   */
  static void
! dumpDumpableObject(Archive *fout, DumpOptions *dopt, DumpableObject *dobj)
  {
      switch (dobj->objType)
      {
          case DO_NAMESPACE:
!             dumpNamespace(fout, dopt, (NamespaceInfo *) dobj);
              break;
          case DO_EXTENSION:
!             dumpExtension(fout, dopt, (ExtensionInfo *) dobj);
              break;
          case DO_TYPE:
!             dumpType(fout, dopt, (TypeInfo *) dobj);
              break;
          case DO_SHELL_TYPE:
!             dumpShellType(fout, dopt, (ShellTypeInfo *) dobj);
              break;
          case DO_FUNC:
!             dumpFunc(fout, dopt, (FuncInfo *) dobj);
              break;
          case DO_AGG:
!             dumpAgg(fout, dopt, (AggInfo *) dobj);
              break;
          case DO_OPERATOR:
!             dumpOpr(fout, dopt, (OprInfo *) dobj);
              break;
          case DO_OPCLASS:
!             dumpOpclass(fout, dopt, (OpclassInfo *) dobj);
              break;
          case DO_OPFAMILY:
!             dumpOpfamily(fout, dopt, (OpfamilyInfo *) dobj);
              break;
          case DO_COLLATION:
!             dumpCollation(fout, dopt, (CollInfo *) dobj);
              break;
          case DO_CONVERSION:
!             dumpConversion(fout, dopt, (ConvInfo *) dobj);
              break;
          case DO_TABLE:
!             dumpTable(fout, dopt, (TableInfo *) dobj);
              break;
          case DO_ATTRDEF:
!             dumpAttrDef(fout, dopt, (AttrDefInfo *) dobj);
              break;
          case DO_INDEX:
!             dumpIndex(fout, dopt, (IndxInfo *) dobj);
              break;
          case DO_REFRESH_MATVIEW:
              refreshMatViewData(fout, (TableDataInfo *) dobj);
              break;
          case DO_RULE:
!             dumpRule(fout, dopt, (RuleInfo *) dobj);
              break;
          case DO_TRIGGER:
!             dumpTrigger(fout, dopt, (TriggerInfo *) dobj);
              break;
          case DO_EVENT_TRIGGER:
!             dumpEventTrigger(fout, dopt, (EventTriggerInfo *) dobj);
              break;
          case DO_CONSTRAINT:
!             dumpConstraint(fout, dopt, (ConstraintInfo *) dobj);
              break;
          case DO_FK_CONSTRAINT:
!             dumpConstraint(fout, dopt, (ConstraintInfo *) dobj);
              break;
          case DO_PROCLANG:
!             dumpProcLang(fout, dopt, (ProcLangInfo *) dobj);
              break;
          case DO_CAST:
!             dumpCast(fout, dopt, (CastInfo *) dobj);
              break;
          case DO_TRANSFORM:
!             dumpTransform(fout, dopt, (TransformInfo *) dobj);
              break;
          case DO_TABLE_DATA:
              if (((TableDataInfo *) dobj)->tdtable->relkind == RELKIND_SEQUENCE)
                  dumpSequenceData(fout, (TableDataInfo *) dobj);
              else
!                 dumpTableData(fout, dopt, (TableDataInfo *) dobj);
              break;
          case DO_DUMMY_TYPE:
              /* table rowtypes and array types are never dumped separately */
              break;
          case DO_TSPARSER:
!             dumpTSParser(fout, dopt, (TSParserInfo *) dobj);
              break;
          case DO_TSDICT:
!             dumpTSDictionary(fout, dopt, (TSDictInfo *) dobj);
              break;
          case DO_TSTEMPLATE:
!             dumpTSTemplate(fout, dopt, (TSTemplateInfo *) dobj);
              break;
          case DO_TSCONFIG:
!             dumpTSConfig(fout, dopt, (TSConfigInfo *) dobj);
              break;
          case DO_FDW:
!             dumpForeignDataWrapper(fout, dopt, (FdwInfo *) dobj);
              break;
          case DO_FOREIGN_SERVER:
!             dumpForeignServer(fout, dopt, (ForeignServerInfo *) dobj);
              break;
          case DO_DEFAULT_ACL:
!             dumpDefaultACL(fout, dopt, (DefaultACLInfo *) dobj);
              break;
          case DO_BLOB:
!             dumpBlob(fout, dopt, (BlobInfo *) dobj);
              break;
          case DO_BLOB_DATA:
              ArchiveEntry(fout, dobj->catId, dobj->dumpId,
--- 8283,8393 ----
   * ArchiveEntries (TOC objects) for each object to be dumped.
   */
  static void
! dumpDumpableObject(Archive *fout, DumpableObject *dobj)
  {
      switch (dobj->objType)
      {
          case DO_NAMESPACE:
!             dumpNamespace(fout, (NamespaceInfo *) dobj);
              break;
          case DO_EXTENSION:
!             dumpExtension(fout, (ExtensionInfo *) dobj);
              break;
          case DO_TYPE:
!             dumpType(fout, (TypeInfo *) dobj);
              break;
          case DO_SHELL_TYPE:
!             dumpShellType(fout, (ShellTypeInfo *) dobj);
              break;
          case DO_FUNC:
!             dumpFunc(fout, (FuncInfo *) dobj);
              break;
          case DO_AGG:
!             dumpAgg(fout, (AggInfo *) dobj);
              break;
          case DO_OPERATOR:
!             dumpOpr(fout, (OprInfo *) dobj);
              break;
          case DO_OPCLASS:
!             dumpOpclass(fout, (OpclassInfo *) dobj);
              break;
          case DO_OPFAMILY:
!             dumpOpfamily(fout, (OpfamilyInfo *) dobj);
              break;
          case DO_COLLATION:
!             dumpCollation(fout, (CollInfo *) dobj);
              break;
          case DO_CONVERSION:
!             dumpConversion(fout, (ConvInfo *) dobj);
              break;
          case DO_TABLE:
!             dumpTable(fout, (TableInfo *) dobj);
              break;
          case DO_ATTRDEF:
!             dumpAttrDef(fout, (AttrDefInfo *) dobj);
              break;
          case DO_INDEX:
!             dumpIndex(fout, (IndxInfo *) dobj);
              break;
          case DO_REFRESH_MATVIEW:
              refreshMatViewData(fout, (TableDataInfo *) dobj);
              break;
          case DO_RULE:
!             dumpRule(fout, (RuleInfo *) dobj);
              break;
          case DO_TRIGGER:
!             dumpTrigger(fout, (TriggerInfo *) dobj);
              break;
          case DO_EVENT_TRIGGER:
!             dumpEventTrigger(fout, (EventTriggerInfo *) dobj);
              break;
          case DO_CONSTRAINT:
!             dumpConstraint(fout, (ConstraintInfo *) dobj);
              break;
          case DO_FK_CONSTRAINT:
!             dumpConstraint(fout, (ConstraintInfo *) dobj);
              break;
          case DO_PROCLANG:
!             dumpProcLang(fout, (ProcLangInfo *) dobj);
              break;
          case DO_CAST:
!             dumpCast(fout, (CastInfo *) dobj);
              break;
          case DO_TRANSFORM:
!             dumpTransform(fout, (TransformInfo *) dobj);
              break;
          case DO_TABLE_DATA:
              if (((TableDataInfo *) dobj)->tdtable->relkind == RELKIND_SEQUENCE)
                  dumpSequenceData(fout, (TableDataInfo *) dobj);
              else
!                 dumpTableData(fout, (TableDataInfo *) dobj);
              break;
          case DO_DUMMY_TYPE:
              /* table rowtypes and array types are never dumped separately */
              break;
          case DO_TSPARSER:
!             dumpTSParser(fout, (TSParserInfo *) dobj);
              break;
          case DO_TSDICT:
!             dumpTSDictionary(fout, (TSDictInfo *) dobj);
              break;
          case DO_TSTEMPLATE:
!             dumpTSTemplate(fout, (TSTemplateInfo *) dobj);
              break;
          case DO_TSCONFIG:
!             dumpTSConfig(fout, (TSConfigInfo *) dobj);
              break;
          case DO_FDW:
!             dumpForeignDataWrapper(fout, (FdwInfo *) dobj);
              break;
          case DO_FOREIGN_SERVER:
!             dumpForeignServer(fout, (ForeignServerInfo *) dobj);
              break;
          case DO_DEFAULT_ACL:
!             dumpDefaultACL(fout, (DefaultACLInfo *) dobj);
              break;
          case DO_BLOB:
!             dumpBlob(fout, (BlobInfo *) dobj);
              break;
          case DO_BLOB_DATA:
              ArchiveEntry(fout, dobj->catId, dobj->dumpId,
*************** dumpDumpableObject(Archive *fout, DumpOp
*** 8378,8384 ****
                           dumpBlobs, NULL);
              break;
          case DO_POLICY:
!             dumpPolicy(fout, dopt, (PolicyInfo *) dobj);
              break;
          case DO_PRE_DATA_BOUNDARY:
          case DO_POST_DATA_BOUNDARY:
--- 8398,8404 ----
                           dumpBlobs, NULL);
              break;
          case DO_POLICY:
!             dumpPolicy(fout, (PolicyInfo *) dobj);
              break;
          case DO_PRE_DATA_BOUNDARY:
          case DO_POST_DATA_BOUNDARY:
*************** dumpDumpableObject(Archive *fout, DumpOp
*** 8392,8399 ****
   *      writes out to fout the queries to recreate a user-defined namespace
   */
  static void
! dumpNamespace(Archive *fout, DumpOptions *dopt, NamespaceInfo *nspinfo)
  {
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
--- 8412,8420 ----
   *      writes out to fout the queries to recreate a user-defined namespace
   */
  static void
! dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
*************** dumpNamespace(Archive *fout, DumpOptions
*** 8432,8445 ****
                   NULL, NULL);

      /* Dump Schema Comments and Security Labels */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, nspinfo->rolname,
                  nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
!     dumpSecLabel(fout, dopt, labelq->data,
                   NULL, nspinfo->rolname,
                   nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);

!     dumpACL(fout, dopt, nspinfo->dobj.catId, nspinfo->dobj.dumpId, "SCHEMA",
              qnspname, NULL, nspinfo->dobj.name, NULL,
              nspinfo->rolname, nspinfo->nspacl);

--- 8453,8466 ----
                   NULL, NULL);

      /* Dump Schema Comments and Security Labels */
!     dumpComment(fout, labelq->data,
                  NULL, nspinfo->rolname,
                  nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
!     dumpSecLabel(fout, labelq->data,
                   NULL, nspinfo->rolname,
                   nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);

!     dumpACL(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, "SCHEMA",
              qnspname, NULL, nspinfo->dobj.name, NULL,
              nspinfo->rolname, nspinfo->nspacl);

*************** dumpNamespace(Archive *fout, DumpOptions
*** 8455,8462 ****
   *      writes out to fout the queries to recreate an extension
   */
  static void
! dumpExtension(Archive *fout, DumpOptions *dopt, ExtensionInfo *extinfo)
  {
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
--- 8476,8484 ----
   *      writes out to fout the queries to recreate an extension
   */
  static void
! dumpExtension(Archive *fout, ExtensionInfo *extinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
*************** dumpExtension(Archive *fout, DumpOptions
*** 8560,8569 ****
                   NULL, NULL);

      /* Dump Extension Comments and Security Labels */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, "",
                  extinfo->dobj.catId, 0, extinfo->dobj.dumpId);
!     dumpSecLabel(fout, dopt, labelq->data,
                   NULL, "",
                   extinfo->dobj.catId, 0, extinfo->dobj.dumpId);

--- 8582,8591 ----
                   NULL, NULL);

      /* Dump Extension Comments and Security Labels */
!     dumpComment(fout, labelq->data,
                  NULL, "",
                  extinfo->dobj.catId, 0, extinfo->dobj.dumpId);
!     dumpSecLabel(fout, labelq->data,
                   NULL, "",
                   extinfo->dobj.catId, 0, extinfo->dobj.dumpId);

*************** dumpExtension(Archive *fout, DumpOptions
*** 8579,8603 ****
   *      writes out to fout the queries to recreate a user-defined type
   */
  static void
! dumpType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo)
  {
      /* Skip if not to be dumped */
      if (!tyinfo->dobj.dump || dopt->dataOnly)
          return;

      /* Dump out in proper style */
      if (tyinfo->typtype == TYPTYPE_BASE)
!         dumpBaseType(fout, dopt, tyinfo);
      else if (tyinfo->typtype == TYPTYPE_DOMAIN)
!         dumpDomain(fout, dopt, tyinfo);
      else if (tyinfo->typtype == TYPTYPE_COMPOSITE)
!         dumpCompositeType(fout, dopt, tyinfo);
      else if (tyinfo->typtype == TYPTYPE_ENUM)
!         dumpEnumType(fout, dopt, tyinfo);
      else if (tyinfo->typtype == TYPTYPE_RANGE)
!         dumpRangeType(fout, dopt, tyinfo);
      else if (tyinfo->typtype == TYPTYPE_PSEUDO && !tyinfo->isDefined)
!         dumpUndefinedType(fout, dopt, tyinfo);
      else
          write_msg(NULL, "WARNING: typtype of data type \"%s\" appears to be invalid\n",
                    tyinfo->dobj.name);
--- 8601,8627 ----
   *      writes out to fout the queries to recreate a user-defined type
   */
  static void
! dumpType(Archive *fout, TypeInfo *tyinfo)
  {
+     DumpOptions *dopt = fout->dopt;
+
      /* Skip if not to be dumped */
      if (!tyinfo->dobj.dump || dopt->dataOnly)
          return;

      /* Dump out in proper style */
      if (tyinfo->typtype == TYPTYPE_BASE)
!         dumpBaseType(fout, tyinfo);
      else if (tyinfo->typtype == TYPTYPE_DOMAIN)
!         dumpDomain(fout, tyinfo);
      else if (tyinfo->typtype == TYPTYPE_COMPOSITE)
!         dumpCompositeType(fout, tyinfo);
      else if (tyinfo->typtype == TYPTYPE_ENUM)
!         dumpEnumType(fout, tyinfo);
      else if (tyinfo->typtype == TYPTYPE_RANGE)
!         dumpRangeType(fout, 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);
*************** dumpType(Archive *fout, DumpOptions *dop
*** 8608,8615 ****
   *      writes out to fout the queries to recreate a user-defined enum type
   */
  static void
! dumpEnumType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo)
  {
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
      PQExpBuffer labelq = createPQExpBuffer();
--- 8632,8640 ----
   *      writes out to fout the queries to recreate a user-defined enum type
   */
  static void
! dumpEnumType(Archive *fout, TypeInfo *tyinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
      PQExpBuffer labelq = createPQExpBuffer();
*************** dumpEnumType(Archive *fout, DumpOptions
*** 8713,8726 ****
                   NULL, NULL);

      /* Dump Type Comments and Security Labels */
!     dumpComment(fout, dopt, labelq->data,
                  tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                  tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
!     dumpSecLabel(fout, dopt, labelq->data,
                   tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                   tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);

!     dumpACL(fout, dopt, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
              qtypname, NULL, tyinfo->dobj.name,
              tyinfo->dobj.namespace->dobj.name,
              tyinfo->rolname, tyinfo->typacl);
--- 8738,8751 ----
                   NULL, NULL);

      /* Dump Type Comments and Security Labels */
!     dumpComment(fout, labelq->data,
                  tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                  tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
!     dumpSecLabel(fout, labelq->data,
                   tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                   tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);

!     dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
              qtypname, NULL, tyinfo->dobj.name,
              tyinfo->dobj.namespace->dobj.name,
              tyinfo->rolname, tyinfo->typacl);
*************** dumpEnumType(Archive *fout, DumpOptions
*** 8737,8744 ****
   *      writes out to fout the queries to recreate a user-defined range type
   */
  static void
! dumpRangeType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo)
  {
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
      PQExpBuffer labelq = createPQExpBuffer();
--- 8762,8770 ----
   *      writes out to fout the queries to recreate a user-defined range type
   */
  static void
! dumpRangeType(Archive *fout, TypeInfo *tyinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
      PQExpBuffer labelq = createPQExpBuffer();
*************** dumpRangeType(Archive *fout, DumpOptions
*** 8845,8858 ****
                   NULL, NULL);

      /* Dump Type Comments and Security Labels */
!     dumpComment(fout, dopt, labelq->data,
                  tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                  tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
!     dumpSecLabel(fout, dopt, labelq->data,
                   tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                   tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);

!     dumpACL(fout, dopt, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
              qtypname, NULL, tyinfo->dobj.name,
              tyinfo->dobj.namespace->dobj.name,
              tyinfo->rolname, tyinfo->typacl);
--- 8871,8884 ----
                   NULL, NULL);

      /* Dump Type Comments and Security Labels */
!     dumpComment(fout, labelq->data,
                  tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                  tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
!     dumpSecLabel(fout, labelq->data,
                   tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                   tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);

!     dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
              qtypname, NULL, tyinfo->dobj.name,
              tyinfo->dobj.namespace->dobj.name,
              tyinfo->rolname, tyinfo->typacl);
*************** dumpRangeType(Archive *fout, DumpOptions
*** 8874,8881 ****
   * depending on it.
   */
  static void
! dumpUndefinedType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo)
  {
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
      PQExpBuffer labelq = createPQExpBuffer();
--- 8900,8908 ----
   * depending on it.
   */
  static void
! dumpUndefinedType(Archive *fout, TypeInfo *tyinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
      PQExpBuffer labelq = createPQExpBuffer();
*************** dumpUndefinedType(Archive *fout, DumpOpt
*** 8914,8927 ****
                   NULL, NULL);

      /* Dump Type Comments and Security Labels */
!     dumpComment(fout, dopt, labelq->data,
                  tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                  tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
!     dumpSecLabel(fout, dopt, labelq->data,
                   tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                   tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);

!     dumpACL(fout, dopt, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
              qtypname, NULL, tyinfo->dobj.name,
              tyinfo->dobj.namespace->dobj.name,
              tyinfo->rolname, tyinfo->typacl);
--- 8941,8954 ----
                   NULL, NULL);

      /* Dump Type Comments and Security Labels */
!     dumpComment(fout, labelq->data,
                  tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                  tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
!     dumpSecLabel(fout, labelq->data,
                   tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                   tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);

!     dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
              qtypname, NULL, tyinfo->dobj.name,
              tyinfo->dobj.namespace->dobj.name,
              tyinfo->rolname, tyinfo->typacl);
*************** dumpUndefinedType(Archive *fout, DumpOpt
*** 8936,8943 ****
   *      writes out to fout the queries to recreate a user-defined base type
   */
  static void
! dumpBaseType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo)
  {
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
      PQExpBuffer labelq = createPQExpBuffer();
--- 8963,8971 ----
   *      writes out to fout the queries to recreate a user-defined base type
   */
  static void
! dumpBaseType(Archive *fout, TypeInfo *tyinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
      PQExpBuffer labelq = createPQExpBuffer();
*************** dumpBaseType(Archive *fout, DumpOptions
*** 9302,9315 ****
                   NULL, NULL);

      /* Dump Type Comments and Security Labels */
!     dumpComment(fout, dopt, labelq->data,
                  tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                  tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
!     dumpSecLabel(fout, dopt, labelq->data,
                   tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                   tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);

!     dumpACL(fout, dopt, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
              qtypname, NULL, tyinfo->dobj.name,
              tyinfo->dobj.namespace->dobj.name,
              tyinfo->rolname, tyinfo->typacl);
--- 9330,9343 ----
                   NULL, NULL);

      /* Dump Type Comments and Security Labels */
!     dumpComment(fout, labelq->data,
                  tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                  tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
!     dumpSecLabel(fout, labelq->data,
                   tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                   tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);

!     dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
              qtypname, NULL, tyinfo->dobj.name,
              tyinfo->dobj.namespace->dobj.name,
              tyinfo->rolname, tyinfo->typacl);
*************** dumpBaseType(Archive *fout, DumpOptions
*** 9326,9333 ****
   *      writes out to fout the queries to recreate a user-defined domain
   */
  static void
! dumpDomain(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo)
  {
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
      PQExpBuffer labelq = createPQExpBuffer();
--- 9354,9362 ----
   *      writes out to fout the queries to recreate a user-defined domain
   */
  static void
! dumpDomain(Archive *fout, TypeInfo *tyinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
      PQExpBuffer labelq = createPQExpBuffer();
*************** dumpDomain(Archive *fout, DumpOptions *d
*** 9464,9477 ****
                   NULL, NULL);

      /* Dump Domain Comments and Security Labels */
!     dumpComment(fout, dopt, labelq->data,
                  tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                  tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
!     dumpSecLabel(fout, dopt, labelq->data,
                   tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                   tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);

!     dumpACL(fout, dopt, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
              qtypname, NULL, tyinfo->dobj.name,
              tyinfo->dobj.namespace->dobj.name,
              tyinfo->rolname, tyinfo->typacl);
--- 9493,9506 ----
                   NULL, NULL);

      /* Dump Domain Comments and Security Labels */
!     dumpComment(fout, labelq->data,
                  tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                  tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
!     dumpSecLabel(fout, labelq->data,
                   tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                   tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);

!     dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
              qtypname, NULL, tyinfo->dobj.name,
              tyinfo->dobj.namespace->dobj.name,
              tyinfo->rolname, tyinfo->typacl);
*************** dumpDomain(Archive *fout, DumpOptions *d
*** 9486,9492 ****
                            fmtId(domcheck->dobj.name));
          appendPQExpBuffer(labelq, "ON DOMAIN %s",
                            fmtId(qtypname));
!         dumpComment(fout, dopt, labelq->data,
                      tyinfo->dobj.namespace->dobj.name,
                      tyinfo->rolname,
                      domcheck->dobj.catId, 0, tyinfo->dobj.dumpId);
--- 9515,9521 ----
                            fmtId(domcheck->dobj.name));
          appendPQExpBuffer(labelq, "ON DOMAIN %s",
                            fmtId(qtypname));
!         dumpComment(fout, labelq->data,
                      tyinfo->dobj.namespace->dobj.name,
                      tyinfo->rolname,
                      domcheck->dobj.catId, 0, tyinfo->dobj.dumpId);
*************** dumpDomain(Archive *fout, DumpOptions *d
*** 9505,9512 ****
   *      composite type
   */
  static void
! dumpCompositeType(Archive *fout, DumpOptions *dopt, TypeInfo *tyinfo)
  {
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer dropped = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
--- 9534,9542 ----
   *      composite type
   */
  static void
! dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer dropped = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
*************** dumpCompositeType(Archive *fout, DumpOpt
*** 9690,9703 ****


      /* Dump Type Comments and Security Labels */
!     dumpComment(fout, dopt, labelq->data,
                  tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                  tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
!     dumpSecLabel(fout, dopt, labelq->data,
                   tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                   tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);

!     dumpACL(fout, dopt, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
              qtypname, NULL, tyinfo->dobj.name,
              tyinfo->dobj.namespace->dobj.name,
              tyinfo->rolname, tyinfo->typacl);
--- 9720,9733 ----


      /* Dump Type Comments and Security Labels */
!     dumpComment(fout, labelq->data,
                  tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                  tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
!     dumpSecLabel(fout, labelq->data,
                   tyinfo->dobj.namespace->dobj.name, tyinfo->rolname,
                   tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);

!     dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
              qtypname, NULL, tyinfo->dobj.name,
              tyinfo->dobj.namespace->dobj.name,
              tyinfo->rolname, tyinfo->typacl);
*************** dumpCompositeTypeColComments(Archive *fo
*** 9828,9835 ****
   * We dump a shell definition in advance of the I/O functions for the type.
   */
  static void
! dumpShellType(Archive *fout, DumpOptions *dopt, ShellTypeInfo *stinfo)
  {
      PQExpBuffer q;

      /* Skip if not to be dumped */
--- 9858,9866 ----
   * We dump a shell definition in advance of the I/O functions for the type.
   */
  static void
! dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q;

      /* Skip if not to be dumped */
*************** shouldDumpProcLangs(DumpOptions *dopt)
*** 9899,9906 ****
   *          procedural language
   */
  static void
! dumpProcLang(Archive *fout, DumpOptions *dopt, ProcLangInfo *plang)
  {
      PQExpBuffer defqry;
      PQExpBuffer delqry;
      PQExpBuffer labelq;
--- 9930,9938 ----
   *          procedural language
   */
  static void
! dumpProcLang(Archive *fout, ProcLangInfo *plang)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer defqry;
      PQExpBuffer delqry;
      PQExpBuffer labelq;
*************** dumpProcLang(Archive *fout, DumpOptions
*** 10037,10051 ****
                   NULL, NULL);

      /* Dump Proc Lang Comments and Security Labels */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, "",
                  plang->dobj.catId, 0, plang->dobj.dumpId);
!     dumpSecLabel(fout, dopt, labelq->data,
                   NULL, "",
                   plang->dobj.catId, 0, plang->dobj.dumpId);

      if (plang->lanpltrusted)
!         dumpACL(fout, dopt, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
                  qlanname, NULL, plang->dobj.name,
                  lanschema,
                  plang->lanowner, plang->lanacl);
--- 10069,10083 ----
                   NULL, NULL);

      /* Dump Proc Lang Comments and Security Labels */
!     dumpComment(fout, labelq->data,
                  NULL, "",
                  plang->dobj.catId, 0, plang->dobj.dumpId);
!     dumpSecLabel(fout, labelq->data,
                   NULL, "",
                   plang->dobj.catId, 0, plang->dobj.dumpId);

      if (plang->lanpltrusted)
!         dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
                  qlanname, NULL, plang->dobj.name,
                  lanschema,
                  plang->lanowner, plang->lanacl);
*************** format_function_signature(Archive *fout,
*** 10192,10199 ****
   *      dump out one function
   */
  static void
! dumpFunc(Archive *fout, DumpOptions *dopt, FuncInfo *finfo)
  {
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delqry;
--- 10224,10232 ----
   *      dump out one function
   */
  static void
! dumpFunc(Archive *fout, FuncInfo *finfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delqry;
*************** dumpFunc(Archive *fout, DumpOptions *dop
*** 10703,10716 ****
                   NULL, NULL);

      /* Dump Function Comments and Security Labels */
!     dumpComment(fout, dopt, labelq->data,
                  finfo->dobj.namespace->dobj.name, finfo->rolname,
                  finfo->dobj.catId, 0, finfo->dobj.dumpId);
!     dumpSecLabel(fout, dopt, labelq->data,
                   finfo->dobj.namespace->dobj.name, finfo->rolname,
                   finfo->dobj.catId, 0, finfo->dobj.dumpId);

!     dumpACL(fout, dopt, finfo->dobj.catId, finfo->dobj.dumpId, "FUNCTION",
              funcsig, NULL, funcsig_tag,
              finfo->dobj.namespace->dobj.name,
              finfo->rolname, finfo->proacl);
--- 10736,10749 ----
                   NULL, NULL);

      /* Dump Function Comments and Security Labels */
!     dumpComment(fout, labelq->data,
                  finfo->dobj.namespace->dobj.name, finfo->rolname,
                  finfo->dobj.catId, 0, finfo->dobj.dumpId);
!     dumpSecLabel(fout, labelq->data,
                   finfo->dobj.namespace->dobj.name, finfo->rolname,
                   finfo->dobj.catId, 0, finfo->dobj.dumpId);

!     dumpACL(fout, finfo->dobj.catId, finfo->dobj.dumpId, "FUNCTION",
              funcsig, NULL, funcsig_tag,
              finfo->dobj.namespace->dobj.name,
              finfo->rolname, finfo->proacl);
*************** dumpFunc(Archive *fout, DumpOptions *dop
*** 10741,10748 ****
   * Dump a user-defined cast
   */
  static void
! dumpCast(Archive *fout, DumpOptions *dopt, CastInfo *cast)
  {
      PQExpBuffer defqry;
      PQExpBuffer delqry;
      PQExpBuffer labelq;
--- 10774,10782 ----
   * Dump a user-defined cast
   */
  static void
! dumpCast(Archive *fout, CastInfo *cast)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer defqry;
      PQExpBuffer delqry;
      PQExpBuffer labelq;
*************** dumpCast(Archive *fout, DumpOptions *dop
*** 10830,10836 ****
                   NULL, NULL);

      /* Dump Cast Comments */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, "",
                  cast->dobj.catId, 0, cast->dobj.dumpId);

--- 10864,10870 ----
                   NULL, NULL);

      /* Dump Cast Comments */
!     dumpComment(fout, labelq->data,
                  NULL, "",
                  cast->dobj.catId, 0, cast->dobj.dumpId);

*************** dumpCast(Archive *fout, DumpOptions *dop
*** 10846,10853 ****
   * Dump a transform
   */
  static void
! dumpTransform(Archive *fout, DumpOptions *dopt, TransformInfo *transform)
  {
      PQExpBuffer defqry;
      PQExpBuffer delqry;
      PQExpBuffer labelq;
--- 10880,10888 ----
   * Dump a transform
   */
  static void
! dumpTransform(Archive *fout, TransformInfo *transform)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer defqry;
      PQExpBuffer delqry;
      PQExpBuffer labelq;
*************** dumpTransform(Archive *fout, DumpOptions
*** 10949,10955 ****
                   NULL, NULL);

      /* Dump Transform Comments */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, "",
                  transform->dobj.catId, 0, transform->dobj.dumpId);

--- 10984,10990 ----
                   NULL, NULL);

      /* Dump Transform Comments */
!     dumpComment(fout, labelq->data,
                  NULL, "",
                  transform->dobj.catId, 0, transform->dobj.dumpId);

*************** dumpTransform(Archive *fout, DumpOptions
*** 10966,10973 ****
   *      write out a single operator definition
   */
  static void
! dumpOpr(Archive *fout, DumpOptions *dopt, OprInfo *oprinfo)
  {
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delq;
--- 11001,11009 ----
   *      write out a single operator definition
   */
  static void
! dumpOpr(Archive *fout, OprInfo *oprinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delq;
*************** dumpOpr(Archive *fout, DumpOptions *dopt
*** 11204,11210 ****
                   NULL, NULL);

      /* Dump Operator Comments */
!     dumpComment(fout, dopt, labelq->data,
                  oprinfo->dobj.namespace->dobj.name, oprinfo->rolname,
                  oprinfo->dobj.catId, 0, oprinfo->dobj.dumpId);

--- 11240,11246 ----
                   NULL, NULL);

      /* Dump Operator Comments */
!     dumpComment(fout, labelq->data,
                  oprinfo->dobj.namespace->dobj.name, oprinfo->rolname,
                  oprinfo->dobj.catId, 0, oprinfo->dobj.dumpId);

*************** convertTSFunction(Archive *fout, Oid fun
*** 11354,11361 ****
   *      write out a single operator class definition
   */
  static void
! dumpOpclass(Archive *fout, DumpOptions *dopt, OpclassInfo *opcinfo)
  {
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delq;
--- 11390,11398 ----
   *      write out a single operator class definition
   */
  static void
! dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delq;
*************** dumpOpclass(Archive *fout, DumpOptions *
*** 11712,11718 ****
                   NULL, NULL);

      /* Dump Operator Class Comments */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, opcinfo->rolname,
                  opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId);

--- 11749,11755 ----
                   NULL, NULL);

      /* Dump Operator Class Comments */
!     dumpComment(fout, labelq->data,
                  NULL, opcinfo->rolname,
                  opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId);

*************** dumpOpclass(Archive *fout, DumpOptions *
*** 11731,11738 ****
   * specific opclass within the opfamily.
   */
  static void
! dumpOpfamily(Archive *fout, DumpOptions *dopt, OpfamilyInfo *opfinfo)
  {
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delq;
--- 11768,11776 ----
   * specific opclass within the opfamily.
   */
  static void
! dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delq;
*************** dumpOpfamily(Archive *fout, DumpOptions
*** 12025,12031 ****
                   NULL, NULL);

      /* Dump Operator Family Comments */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, opfinfo->rolname,
                  opfinfo->dobj.catId, 0, opfinfo->dobj.dumpId);

--- 12063,12069 ----
                   NULL, NULL);

      /* Dump Operator Family Comments */
!     dumpComment(fout, labelq->data,
                  NULL, opfinfo->rolname,
                  opfinfo->dobj.catId, 0, opfinfo->dobj.dumpId);

*************** dumpOpfamily(Archive *fout, DumpOptions
*** 12043,12050 ****
   *      write out a single collation definition
   */
  static void
! dumpCollation(Archive *fout, DumpOptions *dopt, CollInfo *collinfo)
  {
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delq;
--- 12081,12089 ----
   *      write out a single collation definition
   */
  static void
! dumpCollation(Archive *fout, CollInfo *collinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delq;
*************** dumpCollation(Archive *fout, DumpOptions
*** 12114,12120 ****
                   NULL, NULL);

      /* Dump Collation Comments */
!     dumpComment(fout, dopt, labelq->data,
                  collinfo->dobj.namespace->dobj.name, collinfo->rolname,
                  collinfo->dobj.catId, 0, collinfo->dobj.dumpId);

--- 12153,12159 ----
                   NULL, NULL);

      /* Dump Collation Comments */
!     dumpComment(fout, labelq->data,
                  collinfo->dobj.namespace->dobj.name, collinfo->rolname,
                  collinfo->dobj.catId, 0, collinfo->dobj.dumpId);

*************** dumpCollation(Archive *fout, DumpOptions
*** 12131,12138 ****
   *      write out a single conversion definition
   */
  static void
! dumpConversion(Archive *fout, DumpOptions *dopt, ConvInfo *convinfo)
  {
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delq;
--- 12170,12178 ----
   *      write out a single conversion definition
   */
  static void
! dumpConversion(Archive *fout, ConvInfo *convinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delq;
*************** dumpConversion(Archive *fout, DumpOption
*** 12213,12219 ****
                   NULL, NULL);

      /* Dump Conversion Comments */
!     dumpComment(fout, dopt, labelq->data,
                  convinfo->dobj.namespace->dobj.name, convinfo->rolname,
                  convinfo->dobj.catId, 0, convinfo->dobj.dumpId);

--- 12253,12259 ----
                   NULL, NULL);

      /* Dump Conversion Comments */
!     dumpComment(fout, labelq->data,
                  convinfo->dobj.namespace->dobj.name, convinfo->rolname,
                  convinfo->dobj.catId, 0, convinfo->dobj.dumpId);

*************** format_aggregate_signature(AggInfo *aggi
*** 12270,12277 ****
   *      write out a single aggregate definition
   */
  static void
! dumpAgg(Archive *fout, DumpOptions *dopt, AggInfo *agginfo)
  {
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delq;
--- 12310,12318 ----
   *      write out a single aggregate definition
   */
  static void
! dumpAgg(Archive *fout, AggInfo *agginfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer query;
      PQExpBuffer q;
      PQExpBuffer delq;
*************** dumpAgg(Archive *fout, DumpOptions *dopt
*** 12609,12618 ****
                   NULL, NULL);

      /* Dump Aggregate Comments */
!     dumpComment(fout, dopt, labelq->data,
              agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname,
                  agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
!     dumpSecLabel(fout, dopt, labelq->data,
              agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname,
                   agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);

--- 12650,12659 ----
                   NULL, NULL);

      /* Dump Aggregate Comments */
!     dumpComment(fout, labelq->data,
              agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname,
                  agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);
!     dumpSecLabel(fout, labelq->data,
              agginfo->aggfn.dobj.namespace->dobj.name, agginfo->aggfn.rolname,
                   agginfo->aggfn.dobj.catId, 0, agginfo->aggfn.dobj.dumpId);

*************** dumpAgg(Archive *fout, DumpOptions *dopt
*** 12627,12633 ****
      aggsig = format_function_signature(fout, &agginfo->aggfn, true);
      aggsig_tag = format_function_signature(fout, &agginfo->aggfn, false);

!     dumpACL(fout, dopt, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
              "FUNCTION",
              aggsig, NULL, aggsig_tag,
              agginfo->aggfn.dobj.namespace->dobj.name,
--- 12668,12674 ----
      aggsig = format_function_signature(fout, &agginfo->aggfn, true);
      aggsig_tag = format_function_signature(fout, &agginfo->aggfn, false);

!     dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
              "FUNCTION",
              aggsig, NULL, aggsig_tag,
              agginfo->aggfn.dobj.namespace->dobj.name,
*************** dumpAgg(Archive *fout, DumpOptions *dopt
*** 12652,12659 ****
   *      write out a single text search parser
   */
  static void
! dumpTSParser(Archive *fout, DumpOptions *dopt, TSParserInfo *prsinfo)
  {
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
--- 12693,12701 ----
   *      write out a single text search parser
   */
  static void
! dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
*************** dumpTSParser(Archive *fout, DumpOptions
*** 12709,12715 ****
                   NULL, NULL);

      /* Dump Parser Comments */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, "",
                  prsinfo->dobj.catId, 0, prsinfo->dobj.dumpId);

--- 12751,12757 ----
                   NULL, NULL);

      /* Dump Parser Comments */
!     dumpComment(fout, labelq->data,
                  NULL, "",
                  prsinfo->dobj.catId, 0, prsinfo->dobj.dumpId);

*************** dumpTSParser(Archive *fout, DumpOptions
*** 12723,12730 ****
   *      write out a single text search dictionary
   */
  static void
! dumpTSDictionary(Archive *fout, DumpOptions *dopt, TSDictInfo *dictinfo)
  {
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
--- 12765,12773 ----
   *      write out a single text search dictionary
   */
  static void
! dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
*************** dumpTSDictionary(Archive *fout, DumpOpti
*** 12796,12802 ****
                   NULL, NULL);

      /* Dump Dictionary Comments */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, dictinfo->rolname,
                  dictinfo->dobj.catId, 0, dictinfo->dobj.dumpId);

--- 12839,12845 ----
                   NULL, NULL);

      /* Dump Dictionary Comments */
!     dumpComment(fout, labelq->data,
                  NULL, dictinfo->rolname,
                  dictinfo->dobj.catId, 0, dictinfo->dobj.dumpId);

*************** dumpTSDictionary(Archive *fout, DumpOpti
*** 12811,12818 ****
   *      write out a single text search template
   */
  static void
! dumpTSTemplate(Archive *fout, DumpOptions *dopt, TSTemplateInfo *tmplinfo)
  {
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
--- 12854,12862 ----
   *      write out a single text search template
   */
  static void
! dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
*************** dumpTSTemplate(Archive *fout, DumpOption
*** 12862,12868 ****
                   NULL, NULL);

      /* Dump Template Comments */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, "",
                  tmplinfo->dobj.catId, 0, tmplinfo->dobj.dumpId);

--- 12906,12912 ----
                   NULL, NULL);

      /* Dump Template Comments */
!     dumpComment(fout, labelq->data,
                  NULL, "",
                  tmplinfo->dobj.catId, 0, tmplinfo->dobj.dumpId);

*************** dumpTSTemplate(Archive *fout, DumpOption
*** 12876,12883 ****
   *      write out a single text search configuration
   */
  static void
! dumpTSConfig(Archive *fout, DumpOptions *dopt, TSConfigInfo *cfginfo)
  {
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
--- 12920,12928 ----
   *      write out a single text search configuration
   */
  static void
! dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
*************** dumpTSConfig(Archive *fout, DumpOptions
*** 12990,12996 ****
                   NULL, NULL);

      /* Dump Configuration Comments */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, cfginfo->rolname,
                  cfginfo->dobj.catId, 0, cfginfo->dobj.dumpId);

--- 13035,13041 ----
                   NULL, NULL);

      /* Dump Configuration Comments */
!     dumpComment(fout, labelq->data,
                  NULL, cfginfo->rolname,
                  cfginfo->dobj.catId, 0, cfginfo->dobj.dumpId);

*************** dumpTSConfig(Archive *fout, DumpOptions
*** 13005,13012 ****
   *      write out a single foreign-data wrapper definition
   */
  static void
! dumpForeignDataWrapper(Archive *fout, DumpOptions *dopt, FdwInfo *fdwinfo)
  {
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
--- 13050,13058 ----
   *      write out a single foreign-data wrapper definition
   */
  static void
! dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
*************** dumpForeignDataWrapper(Archive *fout, Du
*** 13064,13077 ****
                   NULL, NULL);

      /* Handle the ACL */
!     dumpACL(fout, dopt, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
              "FOREIGN DATA WRAPPER",
              qfdwname, NULL, fdwinfo->dobj.name,
              NULL, fdwinfo->rolname,
              fdwinfo->fdwacl);

      /* Dump Foreign Data Wrapper Comments */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, fdwinfo->rolname,
                  fdwinfo->dobj.catId, 0, fdwinfo->dobj.dumpId);

--- 13110,13123 ----
                   NULL, NULL);

      /* Handle the ACL */
!     dumpACL(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
              "FOREIGN DATA WRAPPER",
              qfdwname, NULL, fdwinfo->dobj.name,
              NULL, fdwinfo->rolname,
              fdwinfo->fdwacl);

      /* Dump Foreign Data Wrapper Comments */
!     dumpComment(fout, labelq->data,
                  NULL, fdwinfo->rolname,
                  fdwinfo->dobj.catId, 0, fdwinfo->dobj.dumpId);

*************** dumpForeignDataWrapper(Archive *fout, Du
*** 13087,13094 ****
   *      write out a foreign server definition
   */
  static void
! dumpForeignServer(Archive *fout, DumpOptions *dopt, ForeignServerInfo *srvinfo)
  {
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
--- 13133,13141 ----
   *      write out a foreign server definition
   */
  static void
! dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q;
      PQExpBuffer delq;
      PQExpBuffer labelq;
*************** dumpForeignServer(Archive *fout, DumpOpt
*** 13156,13162 ****
                   NULL, NULL);

      /* Handle the ACL */
!     dumpACL(fout, dopt, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
              "FOREIGN SERVER",
              qsrvname, NULL, srvinfo->dobj.name,
              NULL, srvinfo->rolname,
--- 13203,13209 ----
                   NULL, NULL);

      /* Handle the ACL */
!     dumpACL(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
              "FOREIGN SERVER",
              qsrvname, NULL, srvinfo->dobj.name,
              NULL, srvinfo->rolname,
*************** dumpForeignServer(Archive *fout, DumpOpt
*** 13169,13175 ****
                       srvinfo->dobj.catId, srvinfo->dobj.dumpId);

      /* Dump Foreign Server Comments */
!     dumpComment(fout, dopt, labelq->data,
                  NULL, srvinfo->rolname,
                  srvinfo->dobj.catId, 0, srvinfo->dobj.dumpId);

--- 13216,13222 ----
                       srvinfo->dobj.catId, srvinfo->dobj.dumpId);

      /* Dump Foreign Server Comments */
!     dumpComment(fout, labelq->data,
                  NULL, srvinfo->rolname,
                  srvinfo->dobj.catId, 0, srvinfo->dobj.dumpId);

*************** dumpUserMappings(Archive *fout,
*** 13285,13292 ****
   * Write out default privileges information
   */
  static void
! dumpDefaultACL(Archive *fout, DumpOptions *dopt, DefaultACLInfo *daclinfo)
  {
      PQExpBuffer q;
      PQExpBuffer tag;
      const char *type;
--- 13332,13340 ----
   * Write out default privileges information
   */
  static void
! dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q;
      PQExpBuffer tag;
      const char *type;
*************** dumpDefaultACL(Archive *fout, DumpOption
*** 13365,13375 ****
   *----------
   */
  static void
! dumpACL(Archive *fout, DumpOptions *dopt, 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)
  {
      PQExpBuffer sql;

      /* Do nothing if ACL dump is not enabled */
--- 13413,13424 ----
   *----------
   */
  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)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer sql;

      /* Do nothing if ACL dump is not enabled */
*************** dumpACL(Archive *fout, DumpOptions *dopt
*** 13420,13429 ****
   * calling ArchiveEntry() for the specified object.
   */
  static void
! dumpSecLabel(Archive *fout, DumpOptions *dopt, const char *target,
               const char *namespace, const char *owner,
               CatalogId catalogId, int subid, DumpId dumpId)
  {
      SecLabelItem *labels;
      int            nlabels;
      int            i;
--- 13469,13479 ----
   * calling ArchiveEntry() for the specified object.
   */
  static void
! dumpSecLabel(Archive *fout, const char *target,
               const char *namespace, const char *owner,
               CatalogId catalogId, int subid, DumpId dumpId)
  {
+     DumpOptions *dopt = fout->dopt;
      SecLabelItem *labels;
      int            nlabels;
      int            i;
*************** dumpSecLabel(Archive *fout, DumpOptions
*** 13484,13491 ****
   * and its columns.
   */
  static void
! dumpTableSecLabel(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo, const char *reltypename)
  {
      SecLabelItem *labels;
      int            nlabels;
      int            i;
--- 13534,13542 ----
   * and its columns.
   */
  static void
! dumpTableSecLabel(Archive *fout, TableInfo *tbinfo, const char *reltypename)
  {
+     DumpOptions *dopt = fout->dopt;
      SecLabelItem *labels;
      int            nlabels;
      int            i;
*************** collectSecLabels(Archive *fout, SecLabel
*** 13705,13724 ****
   *      write out to fout the declarations (not data) of a user-defined table
   */
  static void
! dumpTable(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
  {
      if (tbinfo->dobj.dump && !dopt->dataOnly)
      {
          char       *namecopy;

          if (tbinfo->relkind == RELKIND_SEQUENCE)
!             dumpSequence(fout, dopt, tbinfo);
          else
!             dumpTableSchema(fout, dopt, tbinfo);

          /* Handle the ACL here */
          namecopy = pg_strdup(fmtId(tbinfo->dobj.name));
!         dumpACL(fout, dopt, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
                  (tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" :
                  "TABLE",
                  namecopy, NULL, tbinfo->dobj.name,
--- 13756,13777 ----
   *      write out to fout the declarations (not data) of a user-defined table
   */
  static void
! dumpTable(Archive *fout, TableInfo *tbinfo)
  {
+     DumpOptions *dopt = fout->dopt;
+
      if (tbinfo->dobj.dump && !dopt->dataOnly)
      {
          char       *namecopy;

          if (tbinfo->relkind == RELKIND_SEQUENCE)
!             dumpSequence(fout, tbinfo);
          else
!             dumpTableSchema(fout, tbinfo);

          /* Handle the ACL here */
          namecopy = pg_strdup(fmtId(tbinfo->dobj.name));
!         dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
                  (tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" :
                  "TABLE",
                  namecopy, NULL, tbinfo->dobj.name,
*************** dumpTable(Archive *fout, DumpOptions *do
*** 13753,13759 ****
                  attnamecopy = pg_strdup(fmtId(attname));
                  acltag = psprintf("%s.%s", tbinfo->dobj.name, attname);
                  /* Column's GRANT type is always TABLE */
!                 dumpACL(fout, dopt, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE",
                          namecopy, attnamecopy, acltag,
                          tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                          attacl);
--- 13806,13812 ----
                  attnamecopy = pg_strdup(fmtId(attname));
                  acltag = psprintf("%s.%s", tbinfo->dobj.name, attname);
                  /* Column's GRANT type is always TABLE */
!                 dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE",
                          namecopy, attnamecopy, acltag,
                          tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                          attacl);
*************** createViewAsClause(Archive *fout, TableI
*** 13830,13837 ****
   *      write the declaration (not data) of one user-defined table or view
   */
  static void
! dumpTableSchema(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
  {
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
      PQExpBuffer labelq = createPQExpBuffer();
--- 13883,13891 ----
   *      write the declaration (not data) of one user-defined table or view
   */
  static void
! dumpTableSchema(Archive *fout, TableInfo *tbinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer q = createPQExpBuffer();
      PQExpBuffer delq = createPQExpBuffer();
      PQExpBuffer labelq = createPQExpBuffer();
*************** dumpTableSchema(Archive *fout, DumpOptio
*** 14456,14465 ****


      /* Dump Table Comments */
!     dumpTableComment(fout, dopt, tbinfo, reltypename);

      /* Dump Table Security Labels */
!     dumpTableSecLabel(fout, dopt, tbinfo, reltypename);

      /* Dump comments on inlined table constraints */
      for (j = 0; j < tbinfo->ncheck; j++)
--- 14510,14519 ----


      /* Dump Table Comments */
!     dumpTableComment(fout, tbinfo, reltypename);

      /* Dump Table Security Labels */
!     dumpTableSecLabel(fout, tbinfo, reltypename);

      /* Dump comments on inlined table constraints */
      for (j = 0; j < tbinfo->ncheck; j++)
*************** dumpTableSchema(Archive *fout, DumpOptio
*** 14469,14475 ****
          if (constr->separate || !constr->conislocal)
              continue;

!         dumpTableConstraintComment(fout, dopt, constr);
      }

      destroyPQExpBuffer(q);
--- 14523,14529 ----
          if (constr->separate || !constr->conislocal)
              continue;

!         dumpTableConstraintComment(fout, constr);
      }

      destroyPQExpBuffer(q);
*************** dumpTableSchema(Archive *fout, DumpOptio
*** 14481,14488 ****
   * dumpAttrDef --- dump an attribute's default-value declaration
   */
  static void
! dumpAttrDef(Archive *fout, DumpOptions *dopt, AttrDefInfo *adinfo)
  {
      TableInfo  *tbinfo = adinfo->adtable;
      int            adnum = adinfo->adnum;
      PQExpBuffer q;
--- 14535,14543 ----
   * dumpAttrDef --- dump an attribute's default-value declaration
   */
  static void
! dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      TableInfo  *tbinfo = adinfo->adtable;
      int            adnum = adinfo->adnum;
      PQExpBuffer q;
*************** getAttrName(int attrnum, TableInfo *tblI
*** 14568,14575 ****
   *      write out to fout a user-defined index
   */
  static void
! dumpIndex(Archive *fout, DumpOptions *dopt, IndxInfo *indxinfo)
  {
      TableInfo  *tbinfo = indxinfo->indextable;
      bool        is_constraint = (indxinfo->indexconstraint != 0);
      PQExpBuffer q;
--- 14623,14631 ----
   *      write out to fout a user-defined index
   */
  static void
! dumpIndex(Archive *fout, IndxInfo *indxinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      TableInfo  *tbinfo = indxinfo->indextable;
      bool        is_constraint = (indxinfo->indexconstraint != 0);
      PQExpBuffer q;
*************** dumpIndex(Archive *fout, DumpOptions *do
*** 14641,14647 ****
      }

      /* Dump Index Comments */
!     dumpComment(fout, dopt, labelq->data,
                  tbinfo->dobj.namespace->dobj.name,
                  tbinfo->rolname,
                  indxinfo->dobj.catId, 0,
--- 14697,14703 ----
      }

      /* Dump Index Comments */
!     dumpComment(fout, labelq->data,
                  tbinfo->dobj.namespace->dobj.name,
                  tbinfo->rolname,
                  indxinfo->dobj.catId, 0,
*************** dumpIndex(Archive *fout, DumpOptions *do
*** 14658,14665 ****
   *      write out to fout a user-defined constraint
   */
  static void
! dumpConstraint(Archive *fout, DumpOptions *dopt, ConstraintInfo *coninfo)
  {
      TableInfo  *tbinfo = coninfo->contable;
      PQExpBuffer q;
      PQExpBuffer delq;
--- 14714,14722 ----
   *      write out to fout a user-defined constraint
   */
  static void
! dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
  {
+     DumpOptions *dopt = fout->dopt;
      TableInfo  *tbinfo = coninfo->contable;
      PQExpBuffer q;
      PQExpBuffer delq;
*************** dumpConstraint(Archive *fout, DumpOption
*** 14879,14885 ****

      /* Dump Constraint Comments --- only works for table constraints */
      if (tbinfo && coninfo->separate)
!         dumpTableConstraintComment(fout, dopt, coninfo);

      destroyPQExpBuffer(q);
      destroyPQExpBuffer(delq);
--- 14936,14942 ----

      /* Dump Constraint Comments --- only works for table constraints */
      if (tbinfo && coninfo->separate)
!         dumpTableConstraintComment(fout, coninfo);

      destroyPQExpBuffer(q);
      destroyPQExpBuffer(delq);
*************** dumpConstraint(Archive *fout, DumpOption
*** 14893,14899 ****
   * or as a separate ALTER command.
   */
  static void
! dumpTableConstraintComment(Archive *fout, DumpOptions *dopt, ConstraintInfo *coninfo)
  {
      TableInfo  *tbinfo = coninfo->contable;
      PQExpBuffer labelq = createPQExpBuffer();
--- 14950,14956 ----
   * or as a separate ALTER command.
   */
  static void
! dumpTableConstraintComment(Archive *fout, ConstraintInfo *coninfo)
  {
      TableInfo  *tbinfo = coninfo->contable;
      PQExpBuffer labelq = createPQExpBuffer();
*************** dumpTableConstraintComment(Archive *fout
*** 14902,14908 ****
                        fmtId(coninfo->dobj.name));
      appendPQExpBuffer(labelq, "ON %s",
                        fmtId(tbinfo->dobj.name));
!     dumpComment(fout, dopt, labelq->data,
                  tbinfo->dobj.namespace->dobj.name,
                  tbinfo->rolname,
                  coninfo->dobj.catId, 0,
--- 14959,14965 ----
                        fmtId(coninfo->dobj.name));
      appendPQExpBuffer(labelq, "ON %s",
                        fmtId(tbinfo->dobj.name));
!     dumpComment(fout, labelq->data,
                  tbinfo->dobj.namespace->dobj.name,
                  tbinfo->rolname,
                  coninfo->dobj.catId, 0,
*************** findLastBuiltinOid_V70(Archive *fout)
*** 14962,14969 ****
   *      write the declaration (not data) of one user-defined sequence
   */
  static void
! dumpSequence(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
  {
      PGresult   *res;
      char       *startv,
                 *incby,
--- 15019,15027 ----
   *      write the declaration (not data) of one user-defined sequence
   */
  static void
! dumpSequence(Archive *fout, TableInfo *tbinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PGresult   *res;
      char       *startv,
                 *incby,
*************** dumpSequence(Archive *fout, DumpOptions
*** 15148,15157 ****
      }

      /* Dump Sequence Comments and Security Labels */
!     dumpComment(fout, dopt, labelq->data,
                  tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                  tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
!     dumpSecLabel(fout, dopt, labelq->data,
                   tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                   tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);

--- 15206,15215 ----
      }

      /* Dump Sequence Comments and Security Labels */
!     dumpComment(fout, labelq->data,
                  tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                  tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
!     dumpSecLabel(fout, labelq->data,
                   tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                   tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);

*************** dumpSequenceData(Archive *fout, TableDat
*** 15222,15229 ****
   *      write the declaration of one user-defined table trigger
   */
  static void
! dumpTrigger(Archive *fout, DumpOptions *dopt, TriggerInfo *tginfo)
  {
      TableInfo  *tbinfo = tginfo->tgtable;
      PQExpBuffer query;
      PQExpBuffer delqry;
--- 15280,15288 ----
   *      write the declaration of one user-defined table trigger
   */
  static void
! dumpTrigger(Archive *fout, TriggerInfo *tginfo)
  {
+     DumpOptions *dopt = fout->dopt;
      TableInfo  *tbinfo = tginfo->tgtable;
      PQExpBuffer query;
      PQExpBuffer delqry;
*************** dumpTrigger(Archive *fout, DumpOptions *
*** 15418,15424 ****
                   NULL, 0,
                   NULL, NULL);

!     dumpComment(fout, dopt, labelq->data,
                  tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                  tginfo->dobj.catId, 0, tginfo->dobj.dumpId);

--- 15477,15483 ----
                   NULL, 0,
                   NULL, NULL);

!     dumpComment(fout, labelq->data,
                  tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
                  tginfo->dobj.catId, 0, tginfo->dobj.dumpId);

*************** dumpTrigger(Archive *fout, DumpOptions *
*** 15432,15439 ****
   *      write the declaration of one user-defined event trigger
   */
  static void
! dumpEventTrigger(Archive *fout, DumpOptions *dopt, EventTriggerInfo *evtinfo)
  {
      PQExpBuffer query;
      PQExpBuffer labelq;

--- 15491,15499 ----
   *      write the declaration of one user-defined event trigger
   */
  static void
! dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer query;
      PQExpBuffer labelq;

*************** dumpEventTrigger(Archive *fout, DumpOpti
*** 15489,15495 ****
                   "EVENT TRIGGER", SECTION_POST_DATA,
                   query->data, "", NULL, NULL, 0, NULL, NULL);

!     dumpComment(fout, dopt, labelq->data,
                  NULL, evtinfo->evtowner,
                  evtinfo->dobj.catId, 0, evtinfo->dobj.dumpId);

--- 15549,15555 ----
                   "EVENT TRIGGER", SECTION_POST_DATA,
                   query->data, "", NULL, NULL, 0, NULL, NULL);

!     dumpComment(fout, labelq->data,
                  NULL, evtinfo->evtowner,
                  evtinfo->dobj.catId, 0, evtinfo->dobj.dumpId);

*************** dumpEventTrigger(Archive *fout, DumpOpti
*** 15502,15509 ****
   *        Dump a rule
   */
  static void
! dumpRule(Archive *fout, DumpOptions *dopt, RuleInfo *rinfo)
  {
      TableInfo  *tbinfo = rinfo->ruletable;
      PQExpBuffer query;
      PQExpBuffer cmd;
--- 15562,15570 ----
   *        Dump a rule
   */
  static void
! dumpRule(Archive *fout, RuleInfo *rinfo)
  {
+     DumpOptions *dopt = fout->dopt;
      TableInfo  *tbinfo = rinfo->ruletable;
      PQExpBuffer query;
      PQExpBuffer cmd;
*************** dumpRule(Archive *fout, DumpOptions *dop
*** 15618,15624 ****
                   NULL, NULL);

      /* Dump rule comments */
!     dumpComment(fout, dopt, labelq->data,
                  tbinfo->dobj.namespace->dobj.name,
                  tbinfo->rolname,
                  rinfo->dobj.catId, 0, rinfo->dobj.dumpId);
--- 15679,15685 ----
                   NULL, NULL);

      /* Dump rule comments */
!     dumpComment(fout, labelq->data,
                  tbinfo->dobj.namespace->dobj.name,
                  tbinfo->rolname,
                  rinfo->dobj.catId, 0, rinfo->dobj.dumpId);
*************** dumpRule(Archive *fout, DumpOptions *dop
*** 15662,15670 ****
   *      but perhaps we can provide a better solution in the future.
   */
  void
! getExtensionMembership(Archive *fout, DumpOptions *dopt, ExtensionInfo extinfo[],
                         int numExtensions)
  {
      PQExpBuffer query;
      PGresult   *res;
      int            ntups,
--- 15723,15732 ----
   *      but perhaps we can provide a better solution in the future.
   */
  void
! getExtensionMembership(Archive *fout, ExtensionInfo extinfo[],
                         int numExtensions)
  {
+     DumpOptions *dopt = fout->dopt;
      PQExpBuffer query;
      PGresult   *res;
      int            ntups,
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index ba37c4c..ec83d02 100644
*** a/src/bin/pg_dump/pg_dump.h
--- b/src/bin/pg_dump/pg_dump.h
*************** extern char g_opaque_type[10];    /* name f
*** 493,499 ****
   *    common utility functions
   */

! extern TableInfo *getSchemaData(Archive *, DumpOptions *dopt, int *numTablesPtr);

  extern void AssignDumpId(DumpableObject *dobj);
  extern DumpId createDumpId(void);
--- 493,499 ----
   *    common utility functions
   */

! extern TableInfo *getSchemaData(Archive *fout, int *numTablesPtr);

  extern void AssignDumpId(DumpableObject *dobj);
  extern DumpId createDumpId(void);
*************** extern void sortDataAndIndexObjectsBySiz
*** 527,542 ****
   * version specific routines
   */
  extern NamespaceInfo *getNamespaces(Archive *fout, int *numNamespaces);
! extern ExtensionInfo *getExtensions(Archive *fout, DumpOptions *dopt, int *numExtensions);
  extern TypeInfo *getTypes(Archive *fout, int *numTypes);
! extern FuncInfo *getFuncs(Archive *fout, DumpOptions *dopt, int *numFuncs);
! extern AggInfo *getAggregates(Archive *fout, DumpOptions *dopt, int *numAggregates);
  extern OprInfo *getOperators(Archive *fout, int *numOperators);
  extern OpclassInfo *getOpclasses(Archive *fout, int *numOpclasses);
  extern OpfamilyInfo *getOpfamilies(Archive *fout, int *numOpfamilies);
  extern CollInfo *getCollations(Archive *fout, int *numCollations);
  extern ConvInfo *getConversions(Archive *fout, int *numConversions);
! extern TableInfo *getTables(Archive *fout, DumpOptions *dopt, int *numTables);
  extern void getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables);
  extern InhInfo *getInherits(Archive *fout, int *numInherits);
  extern void getIndexes(Archive *fout, TableInfo tblinfo[], int numTables);
--- 527,542 ----
   * version specific routines
   */
  extern NamespaceInfo *getNamespaces(Archive *fout, int *numNamespaces);
! extern ExtensionInfo *getExtensions(Archive *fout, int *numExtensions);
  extern TypeInfo *getTypes(Archive *fout, int *numTypes);
! extern FuncInfo *getFuncs(Archive *fout, int *numFuncs);
! extern AggInfo *getAggregates(Archive *fout, int *numAggregates);
  extern OprInfo *getOperators(Archive *fout, int *numOperators);
  extern OpclassInfo *getOpclasses(Archive *fout, int *numOpclasses);
  extern OpfamilyInfo *getOpfamilies(Archive *fout, int *numOpfamilies);
  extern CollInfo *getCollations(Archive *fout, int *numCollations);
  extern ConvInfo *getConversions(Archive *fout, int *numConversions);
! extern TableInfo *getTables(Archive *fout, int *numTables);
  extern void getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables);
  extern InhInfo *getInherits(Archive *fout, int *numInherits);
  extern void getIndexes(Archive *fout, TableInfo tblinfo[], int numTables);
*************** extern void getConstraints(Archive *fout
*** 544,552 ****
  extern RuleInfo *getRules(Archive *fout, int *numRules);
  extern void getTriggers(Archive *fout, TableInfo tblinfo[], int numTables);
  extern ProcLangInfo *getProcLangs(Archive *fout, int *numProcLangs);
! extern CastInfo *getCasts(Archive *fout, DumpOptions *dopt, int *numCasts);
  extern TransformInfo *getTransforms(Archive *fout, int *numTransforms);
! extern void getTableAttrs(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo, int numTables);
  extern bool shouldPrintColumn(DumpOptions *dopt, TableInfo *tbinfo, int colno);
  extern TSParserInfo *getTSParsers(Archive *fout, int *numTSParsers);
  extern TSDictInfo *getTSDictionaries(Archive *fout, int *numTSDicts);
--- 544,552 ----
  extern RuleInfo *getRules(Archive *fout, int *numRules);
  extern void getTriggers(Archive *fout, TableInfo tblinfo[], int numTables);
  extern ProcLangInfo *getProcLangs(Archive *fout, int *numProcLangs);
! extern CastInfo *getCasts(Archive *fout, int *numCasts);
  extern TransformInfo *getTransforms(Archive *fout, int *numTransforms);
! extern void getTableAttrs(Archive *fout, TableInfo *tbinfo, int numTables);
  extern bool shouldPrintColumn(DumpOptions *dopt, TableInfo *tbinfo, int colno);
  extern TSParserInfo *getTSParsers(Archive *fout, int *numTSParsers);
  extern TSDictInfo *getTSDictionaries(Archive *fout, int *numTSDicts);
*************** extern FdwInfo *getForeignDataWrappers(A
*** 556,563 ****
                         int *numForeignDataWrappers);
  extern ForeignServerInfo *getForeignServers(Archive *fout,
                    int *numForeignServers);
! extern DefaultACLInfo *getDefaultACLs(Archive *fout, DumpOptions *dopt, int *numDefaultACLs);
! extern void getExtensionMembership(Archive *fout, DumpOptions *dopt, ExtensionInfo extinfo[],
                         int numExtensions);
  extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers);
  extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables);
--- 556,563 ----
                         int *numForeignDataWrappers);
  extern ForeignServerInfo *getForeignServers(Archive *fout,
                    int *numForeignServers);
! extern DefaultACLInfo *getDefaultACLs(Archive *fout, int *numDefaultACLs);
! extern void getExtensionMembership(Archive *fout, ExtensionInfo extinfo[],
                         int numExtensions);
  extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers);
  extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables);
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
index af8dff5..1559f1e 100644
*** a/src/bin/pg_dump/pg_restore.c
--- b/src/bin/pg_dump/pg_restore.c
*************** main(int argc, char **argv)
*** 377,382 ****
--- 377,384 ----

      AH = OpenArchive(inputFileSpec, opts->format);

+     SetArchiveOptions(AH, NULL, opts);
+
      /*
       * We don't have a connection yet but that doesn't matter. The connection
       * is initialized to NULL and if we terminate through exit_nicely() while
*************** main(int argc, char **argv)
*** 393,399 ****
      AH->exit_on_error = opts->exit_on_error;

      if (opts->tocFile)
!         SortTocFromFile(AH, opts);

      /* See comments in pg_dump.c */
  #ifdef WIN32
--- 395,401 ----
      AH->exit_on_error = opts->exit_on_error;

      if (opts->tocFile)
!         SortTocFromFile(AH);

      /* See comments in pg_dump.c */
  #ifdef WIN32
*************** main(int argc, char **argv)
*** 408,417 ****
      AH->numWorkers = numWorkers;

      if (opts->tocSummary)
!         PrintTOCSummary(AH, opts);
      else
      {
!         SetArchiveRestoreOptions(AH, opts);
          RestoreArchive(AH);
      }

--- 410,419 ----
      AH->numWorkers = numWorkers;

      if (opts->tocSummary)
!         PrintTOCSummary(AH);
      else
      {
!         ProcessArchiveRestoreOptions(AH);
          RestoreArchive(AH);
      }

*************** main(int argc, char **argv)
*** 423,429 ****
      /* AH may be freed in CloseArchive? */
      exit_code = AH->n_errors ? 1 : 0;

!     CloseArchive(AH, NULL);

      return exit_code;
  }
--- 425,431 ----
      /* AH may be freed in CloseArchive? */
      exit_code = AH->n_errors ? 1 : 0;

!     CloseArchive(AH);

      return exit_code;
  }