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 */
