diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index f4df6df10fa71c50194f0d0c749b95c11ba375f6..00a9aea556543574952ee2018a47c3a78defbb33 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -27,7 +27,10 @@
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
+#include "catalog/pg_aggregate.h"
+#include "catalog/pg_am.h"
 #include "catalog/pg_authid.h"
+#include "catalog/pg_cast.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_conversion.h"
 #include "catalog/pg_database.h"
@@ -50,6 +53,9 @@
 #include "catalog/pg_type.h"
 #include "catalog/pg_ts_config.h"
 #include "catalog/pg_ts_dict.h"
+#include "catalog/pg_ts_parser.h"
+#include "catalog/pg_ts_template.h"
+#include "catalog/pg_transform.h"
 #include "commands/dbcommands.h"
 #include "commands/event_trigger.h"
 #include "commands/extension.h"
@@ -131,6 +137,8 @@ static AclMode pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnu
 		   Oid roleid, AclMode mask, AclMaskHow how);
 static void recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid,
 						Acl *new_acl);
+static void recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid,
+							  Acl *new_acl);
 
 
 #ifdef ACLDEBUG
@@ -5288,10 +5296,367 @@ get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
 }
 
 /*
- * Record initial ACL for an extension object
+ * Record initial privileges for the top-level object passed in.
  *
- * This will perform a wholesale replacement of the entire ACL for the object
- * passed in, therefore be sure to pass in the complete new ACL to use.
+ * For the object passed in, this will record its ACL (if any) and the ACLs of
+ * any sub-objects (eg: columns) into pg_init_privs.
+ *
+ * Any new kinds of objects which have ACLs associated with them and can be
+ * added to an extension should be added to the if-else tree below.
+ */
+void
+recordExtObjInitPriv(Oid objoid, Oid classoid)
+{
+	/*
+	 * pg_class / pg_attribute
+	 *
+	 * If this is a relation then we need to see if there are any sub-objects
+	 * (eg: columns) for it and, if so, be sure to call
+	 * recordExtensionInitPrivWorker() for each one.
+	 */
+	if (classoid == RelationRelationId)
+	{
+		Form_pg_class pg_class_tuple;
+		Datum		aclDatum;
+		bool		isNull;
+		HeapTuple	tuple;
+
+		tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
+		if (!HeapTupleIsValid(tuple))
+			elog(ERROR, "cache lookup failed for relation %u", objoid);
+		pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
+
+		/* Indexes don't have permissions */
+		if (pg_class_tuple->relkind == RELKIND_INDEX)
+			return;
+
+		/* Composite types don't have permissions either */
+		if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
+			return;
+
+		/*
+		 * If this isn't a sequence, index, or composite type then it's
+		 * possibly going to have columns associated with it that might have
+		 * ACLs.
+		 */
+		if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
+		{
+			AttrNumber	curr_att;
+			AttrNumber	nattrs = pg_class_tuple->relnatts;
+
+			for (curr_att = 1; curr_att <= nattrs; curr_att++)
+			{
+				HeapTuple	attTuple;
+				Datum		attaclDatum;
+
+				attTuple = SearchSysCache2(ATTNUM,
+										   ObjectIdGetDatum(objoid),
+										   Int16GetDatum(curr_att));
+
+				if (!HeapTupleIsValid(attTuple))
+					continue;
+
+				/* ignore dropped columns */
+				if (((Form_pg_attribute) GETSTRUCT(attTuple))->attisdropped)
+				{
+					ReleaseSysCache(attTuple);
+					continue;
+				}
+
+				attaclDatum = SysCacheGetAttr(ATTNUM, attTuple,
+											  Anum_pg_attribute_attacl,
+											  &isNull);
+
+				/* no need to do anything for a NULL ACL */
+				if (isNull)
+				{
+					ReleaseSysCache(attTuple);
+					continue;
+				}
+
+				recordExtensionInitPrivWorker(objoid, classoid, curr_att,
+											  DatumGetAclP(attaclDatum));
+
+				ReleaseSysCache(attTuple);
+			}
+		}
+
+		aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
+								   &isNull);
+
+		/* Add the record, if any, for the top-level object */
+		if (!isNull)
+			recordExtensionInitPrivWorker(objoid, classoid, 0,
+										  DatumGetAclP(aclDatum));
+
+		ReleaseSysCache(tuple);
+	}
+	/* pg_foreign_data_wrapper */
+	else if (classoid == ForeignDataWrapperRelationId)
+	{
+		Datum		aclDatum;
+		bool		isNull;
+		HeapTuple	tuple;
+
+		tuple = SearchSysCache1(FOREIGNDATAWRAPPEROID,
+								ObjectIdGetDatum(objoid));
+		if (!HeapTupleIsValid(tuple))
+			elog(ERROR, "cache lookup failed for foreign data wrapper %u",
+				 objoid);
+
+		aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
+								   Anum_pg_foreign_data_wrapper_fdwacl,
+								   &isNull);
+
+		/* Add the record, if any, for the top-level object */
+		if (!isNull)
+			recordExtensionInitPrivWorker(objoid, classoid, 0,
+										  DatumGetAclP(aclDatum));
+
+		ReleaseSysCache(tuple);
+	}
+	/* pg_foreign_server */
+	else if (classoid == ForeignServerRelationId)
+	{
+		Datum		aclDatum;
+		bool		isNull;
+		HeapTuple	tuple;
+
+		tuple = SearchSysCache1(FOREIGNSERVEROID, ObjectIdGetDatum(objoid));
+		if (!HeapTupleIsValid(tuple))
+			elog(ERROR, "cache lookup failed for foreign data wrapper %u",
+				 objoid);
+
+		aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
+								   Anum_pg_foreign_server_srvacl,
+								   &isNull);
+
+		/* Add the record, if any, for the top-level object */
+		if (!isNull)
+			recordExtensionInitPrivWorker(objoid, classoid, 0,
+										  DatumGetAclP(aclDatum));
+
+		ReleaseSysCache(tuple);
+	}
+	/* pg_language */
+	else if (classoid == LanguageRelationId)
+	{
+		Datum		aclDatum;
+		bool		isNull;
+		HeapTuple	tuple;
+
+		tuple = SearchSysCache1(LANGOID, ObjectIdGetDatum(objoid));
+		if (!HeapTupleIsValid(tuple))
+			elog(ERROR, "cache lookup failed for language %u", objoid);
+
+		aclDatum = SysCacheGetAttr(LANGOID, tuple, Anum_pg_language_lanacl,
+								   &isNull);
+
+		/* Add the record, if any, for the top-level object */
+		if (!isNull)
+			recordExtensionInitPrivWorker(objoid, classoid, 0,
+										  DatumGetAclP(aclDatum));
+
+		ReleaseSysCache(tuple);
+	}
+	/* pg_largeobject_metadata */
+	else if (classoid == LargeObjectMetadataRelationId)
+	{
+		Datum		aclDatum;
+		bool		isNull;
+		HeapTuple	tuple;
+		ScanKeyData entry[1];
+		SysScanDesc scan;
+		Relation	relation;
+
+		relation = heap_open(LargeObjectMetadataRelationId, RowExclusiveLock);
+
+		/* There's no syscache for pg_largeobject_metadata */
+		ScanKeyInit(&entry[0],
+					ObjectIdAttributeNumber,
+					BTEqualStrategyNumber, F_OIDEQ,
+					ObjectIdGetDatum(objoid));
+
+		scan = systable_beginscan(relation,
+								  LargeObjectMetadataOidIndexId, true,
+								  NULL, 1, entry);
+
+		tuple = systable_getnext(scan);
+		if (!HeapTupleIsValid(tuple))
+			elog(ERROR, "cache lookup failed for large object %u", objoid);
+
+		aclDatum = heap_getattr(tuple,
+								Anum_pg_largeobject_metadata_lomacl,
+								RelationGetDescr(relation), &isNull);
+
+		/* Add the record, if any, for the top-level object */
+		if (!isNull)
+			recordExtensionInitPrivWorker(objoid, classoid, 0,
+										  DatumGetAclP(aclDatum));
+
+		systable_endscan(scan);
+	}
+	/* pg_namespace */
+	else if (classoid == NamespaceRelationId)
+	{
+		Datum		aclDatum;
+		bool		isNull;
+		HeapTuple	tuple;
+
+		tuple = SearchSysCache1(NAMESPACEOID, ObjectIdGetDatum(objoid));
+		if (!HeapTupleIsValid(tuple))
+			elog(ERROR, "cache lookup failed for function %u", objoid);
+
+		aclDatum = SysCacheGetAttr(NAMESPACEOID, tuple,
+								   Anum_pg_namespace_nspacl, &isNull);
+
+		/* Add the record, if any, for the top-level object */
+		if (!isNull)
+			recordExtensionInitPrivWorker(objoid, classoid, 0,
+										  DatumGetAclP(aclDatum));
+
+		ReleaseSysCache(tuple);
+	}
+	/* pg_proc */
+	else if (classoid == ProcedureRelationId)
+	{
+		Datum		aclDatum;
+		bool		isNull;
+		HeapTuple	tuple;
+
+		tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(objoid));
+		if (!HeapTupleIsValid(tuple))
+			elog(ERROR, "cache lookup failed for function %u", objoid);
+
+		aclDatum = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_proacl,
+								   &isNull);
+
+		/* Add the record, if any, for the top-level object */
+		if (!isNull)
+			recordExtensionInitPrivWorker(objoid, classoid, 0,
+										  DatumGetAclP(aclDatum));
+
+		ReleaseSysCache(tuple);
+	}
+	/* pg_type */
+	else if (classoid == TypeRelationId)
+	{
+		Datum		aclDatum;
+		bool		isNull;
+		HeapTuple	tuple;
+
+		tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(objoid));
+		if (!HeapTupleIsValid(tuple))
+			elog(ERROR, "cache lookup failed for function %u", objoid);
+
+		aclDatum = SysCacheGetAttr(TYPEOID, tuple, Anum_pg_type_typacl,
+								   &isNull);
+
+		/* Add the record, if any, for the top-level object */
+		if (!isNull)
+			recordExtensionInitPrivWorker(objoid, classoid, 0,
+										  DatumGetAclP(aclDatum));
+
+		ReleaseSysCache(tuple);
+	}
+	else if (classoid == AccessMethodRelationId ||
+			 classoid == AggregateRelationId ||
+			 classoid == CastRelationId ||
+			 classoid == CollationRelationId ||
+			 classoid == ConversionRelationId ||
+			 classoid == EventTriggerRelationId ||
+			 classoid == OperatorRelationId ||
+			 classoid == OperatorClassRelationId ||
+			 classoid == OperatorFamilyRelationId ||
+			 classoid == NamespaceRelationId ||
+			 classoid == TSConfigRelationId ||
+			 classoid == TSDictionaryRelationId ||
+			 classoid == TSParserRelationId ||
+			 classoid == TSTemplateRelationId ||
+			 classoid == TransformRelationId
+		)
+	{
+		/* no ACL for these object types, so do nothing. */
+	}
+
+	/*
+	 * complain if we are given a class OID for a class that extensions don't
+	 * support or that we don't recognize.
+	 */
+	else
+	{
+		elog(ERROR, "unrecognized or unsupported class OID: %u", classoid);
+	}
+}
+
+/*
+ * For the object passed in, remove its ACL and the ACLs of any object subIds
+ * from pg_init_privs (via recordExtensionInitPrivWorker()).
+ */
+void
+removeExtObjInitPriv(Oid objoid, Oid classoid)
+{
+	/*
+	 * If this is a relation then we need to see if there are any sub-objects
+	 * (eg: columns) for it and, if so, be sure to call
+	 * recordExtensionInitPrivWorker() for each one.
+	 */
+	if (classoid == RelationRelationId)
+	{
+		Form_pg_class pg_class_tuple;
+		HeapTuple	tuple;
+
+		tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objoid));
+		if (!HeapTupleIsValid(tuple))
+			elog(ERROR, "cache lookup failed for relation %u", objoid);
+		pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
+
+		/* Indexes don't have permissions */
+		if (pg_class_tuple->relkind == RELKIND_INDEX)
+			return;
+
+		/* Composite types don't have permissions either */
+		if (pg_class_tuple->relkind == RELKIND_COMPOSITE_TYPE)
+			return;
+
+		/*
+		 * If this isn't a sequence, index, or composite type then it's
+		 * possibly going to have columns associated with it that might have
+		 * ACLs.
+		 */
+		if (pg_class_tuple->relkind != RELKIND_SEQUENCE)
+		{
+			AttrNumber	curr_att;
+			AttrNumber	nattrs = pg_class_tuple->relnatts;
+
+			for (curr_att = 1; curr_att <= nattrs; curr_att++)
+			{
+				HeapTuple	attTuple;
+
+				attTuple = SearchSysCache2(ATTNUM,
+										   ObjectIdGetDatum(objoid),
+										   Int16GetDatum(curr_att));
+
+				if (!HeapTupleIsValid(attTuple))
+					continue;
+
+				/* when removing, remove all entires, even dropped columns */
+
+				recordExtensionInitPrivWorker(objoid, classoid, curr_att, NULL);
+
+				ReleaseSysCache(attTuple);
+			}
+		}
+
+		ReleaseSysCache(tuple);
+	}
+
+	/* Remove the record, if any, for the top-level object */
+	recordExtensionInitPrivWorker(objoid, classoid, 0, NULL);
+}
+
+/*
+ * Record initial ACL for an extension object
  *
  * Can be called at any time, we check if 'creating_extension' is set and, if
  * not, exit immediately.
@@ -5310,12 +5675,6 @@ get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
 static void
 recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
 {
-	Relation	relation;
-	ScanKeyData key[3];
-	SysScanDesc scan;
-	HeapTuple	tuple;
-	HeapTuple	oldtuple;
-
 	/*
 	 * Generally, we only record the initial privileges when an extension is
 	 * being created, but because we don't actually use CREATE EXTENSION
@@ -5327,6 +5686,30 @@ recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
 	if (!creating_extension && !binary_upgrade_record_init_privs)
 		return;
 
+	recordExtensionInitPrivWorker(objoid, classoid, objsubid, new_acl);
+}
+
+/*
+ * Record initial ACL for an extension object, worker.
+ *
+ * This will perform a wholesale replacement of the entire ACL for the object
+ * passed in, therefore be sure to pass in the complete new ACL to use.
+ *
+ * Generally speaking, do *not* use this function directly but instead use
+ * recordExtensionInitPriv(), which checks if 'creating_extension' is set.
+ * This function does *not* check if 'creating_extension' is set as it is also
+ * used when an object is added to or removed from an extension via ALTER
+ * EXTENSION ... ADD/DROP.
+ */
+static void
+recordExtensionInitPrivWorker(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
+{
+	Relation	relation;
+	ScanKeyData key[3];
+	SysScanDesc scan;
+	HeapTuple	tuple;
+	HeapTuple	oldtuple;
+
 	relation = heap_open(InitPrivsRelationId, RowExclusiveLock);
 
 	ScanKeyInit(&key[0],
@@ -5379,28 +5762,37 @@ recordExtensionInitPriv(Oid objoid, Oid classoid, int objsubid, Acl *new_acl)
 	}
 	else
 	{
-		/* No entry found, so add it. */
 		Datum		values[Natts_pg_init_privs];
 		bool		nulls[Natts_pg_init_privs];
 
-		MemSet(nulls, false, sizeof(nulls));
+		/*
+		 * Only add a new entry if the new ACL is non-NULL.
+		 *
+		 * If we are passed in a NULL ACL and no entry exists, we can just
+		 * fall through and do nothing.
+		 */
+		if (new_acl)
+		{
+			/* No entry found, so add it. */
+			MemSet(nulls, false, sizeof(nulls));
 
-		values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
-		values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
-		values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
+			values[Anum_pg_init_privs_objoid - 1] = ObjectIdGetDatum(objoid);
+			values[Anum_pg_init_privs_classoid - 1] = ObjectIdGetDatum(classoid);
+			values[Anum_pg_init_privs_objsubid - 1] = Int32GetDatum(objsubid);
 
-		/* This function only handles initial privileges of extensions */
-		values[Anum_pg_init_privs_privtype - 1] =
-			CharGetDatum(INITPRIVS_EXTENSION);
+			/* This function only handles initial privileges of extensions */
+			values[Anum_pg_init_privs_privtype - 1] =
+				CharGetDatum(INITPRIVS_EXTENSION);
 
-		values[Anum_pg_init_privs_privs - 1] = PointerGetDatum(new_acl);
+			values[Anum_pg_init_privs_privs - 1] = PointerGetDatum(new_acl);
 
-		tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
+			tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
 
-		simple_heap_insert(relation, tuple);
+			simple_heap_insert(relation, tuple);
 
-		/* keep the catalog indexes up to date */
-		CatalogUpdateIndexes(relation, tuple);
+			/* keep the catalog indexes up to date */
+			CatalogUpdateIndexes(relation, tuple);
+		}
 	}
 
 	systable_endscan(scan);
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 9680d986a014e4ee39c67ddaeec775616743d5a8..f23c6977cb27ae0d98fe372d848db806ce76d094 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -52,6 +52,7 @@
 #include "nodes/makefuncs.h"
 #include "storage/fd.h"
 #include "tcop/utility.h"
+#include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
 #include "utils/lsyscache.h"
@@ -3240,6 +3241,16 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
 		 * OK, add the dependency.
 		 */
 		recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
+
+		/*
+		 * Also record the initial ACL on the object, if any.
+		 *
+		 * Note that this will handle the object's ACLs, as well as any ACLs
+		 * on object subIds.  (In other words, when the object is a table,
+		 * this will record the table's ACL and the ACLs for the columns on
+		 * the table, if any).
+		 */
+		recordExtObjInitPriv(object.objectId, object.classId);
 	}
 	else
 	{
@@ -3267,6 +3278,16 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt,
 		 */
 		if (object.classId == RelationRelationId)
 			extension_config_remove(extension.objectId, object.objectId);
+
+		/*
+		 * Remove all the initial ACLs, if any.
+		 *
+		 * Note that this will remove the object's ACLs, as well as any ACLs
+		 * on object subIds.  (In other words, when the object is a table,
+		 * this will remove the table's ACL and the ACLs for the columns on
+		 * the table, if any).
+		 */
+		removeExtObjInitPriv(object.objectId, object.classId);
 	}
 
 	InvokeObjectPostAlterHook(ExtensionRelationId, extension.objectId, 0);
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 686141b5f9abb0d842da71edb14ac7b6ec67ea59..0d118525c9cb3dd1df43df82ff4c3ed24c10c4c1 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -300,6 +300,10 @@ extern void aclcheck_error_col(AclResult aclerr, AclObjectKind objectkind,
 
 extern void aclcheck_error_type(AclResult aclerr, Oid typeOid);
 
+extern void recordExtObjInitPriv(Oid objoid, Oid classoid);
+extern void removeExtObjInitPriv(Oid objoid, Oid classoid);
+
+
 /* ownercheck routines just return true (owner) or false (not) */
 extern bool pg_class_ownercheck(Oid class_oid, Oid roleid);
 extern bool pg_type_ownercheck(Oid type_oid, Oid roleid);
diff --git a/src/test/modules/test_pg_dump/expected/test_pg_dump.out b/src/test/modules/test_pg_dump/expected/test_pg_dump.out
index 360caa2cb30d57ac3fa151f45897ecfe6d69ab85..c9bc6f762588233ab26c037f1a34051f01ddc647 100644
--- a/src/test/modules/test_pg_dump/expected/test_pg_dump.out
+++ b/src/test/modules/test_pg_dump/expected/test_pg_dump.out
@@ -1,6 +1,94 @@
-SELECT 1;
- ?column? 
-----------
-        1
-(1 row)
-
+CREATE ROLE regress_dump_test_role;
+CREATE EXTENSION test_pg_dump;
+ALTER EXTENSION test_pg_dump ADD DATABASE postgres; -- error
+ERROR:  syntax error at or near "DATABASE"
+LINE 1: ALTER EXTENSION test_pg_dump ADD DATABASE postgres;
+                                         ^
+CREATE TABLE test_pg_dump_t1 (c1 int);
+CREATE VIEW test_pg_dump_v1 AS SELECT * FROM test_pg_dump_t1;
+CREATE MATERIALIZED VIEW test_pg_dump_mv1 AS SELECT * FROM test_pg_dump_t1;
+CREATE SCHEMA test_pg_dump_s1;
+CREATE TYPE test_pg_dump_e1 AS ENUM ('abc', 'def');
+CREATE AGGREGATE newavg (
+   sfunc = int4_avg_accum, basetype = int4, stype = _int8,
+   finalfunc = int8_avg,
+   initcond1 = '{0,0}'
+);
+CREATE FUNCTION test_pg_dump(int) RETURNS int AS $$
+BEGIN
+RETURN abs($1);
+END
+$$ LANGUAGE plpgsql IMMUTABLE;
+CREATE OPERATOR ==== (
+    LEFTARG = int,
+    RIGHTARG = int,
+    PROCEDURE = int4eq,
+    COMMUTATOR = ====
+);
+CREATE ACCESS METHOD gist2 TYPE INDEX HANDLER gisthandler;
+CREATE TYPE casttesttype;
+CREATE FUNCTION casttesttype_in(cstring)
+   RETURNS casttesttype
+   AS 'textin'
+   LANGUAGE internal STRICT IMMUTABLE;
+NOTICE:  return type casttesttype is only a shell
+CREATE FUNCTION casttesttype_out(casttesttype)
+   RETURNS cstring
+   AS 'textout'
+   LANGUAGE internal STRICT IMMUTABLE;
+NOTICE:  argument type casttesttype is only a shell
+CREATE TYPE casttesttype (
+   internallength = variable,
+   input = casttesttype_in,
+   output = casttesttype_out,
+   alignment = int4
+);
+CREATE CAST (text AS casttesttype) WITHOUT FUNCTION;
+CREATE FOREIGN DATA WRAPPER dummy;
+CREATE SERVER s0 FOREIGN DATA WRAPPER dummy;
+CREATE FOREIGN TABLE ft1 (
+        c1 integer OPTIONS ("param 1" 'val1') NOT NULL,
+        c2 text OPTIONS (param2 'val2', param3 'val3') CHECK (c2 <> ''),
+        c3 date,
+        CHECK (c3 BETWEEN '1994-01-01'::date AND '1994-01-31'::date)
+) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value');
+REVOKE EXECUTE ON FUNCTION test_pg_dump(int) FROM PUBLIC;
+GRANT EXECUTE ON FUNCTION test_pg_dump(int) TO regress_dump_test_role;
+GRANT SELECT (c1) ON test_pg_dump_t1 TO regress_dump_test_role;
+GRANT SELECT ON test_pg_dump_v1 TO regress_dump_test_role;
+GRANT USAGE ON FOREIGN DATA WRAPPER dummy TO regress_dump_test_role;
+GRANT USAGE ON FOREIGN SERVER s0 TO regress_dump_test_role;
+GRANT SELECT (c1) ON ft1 TO regress_dump_test_role;
+GRANT SELECT ON ft1 TO regress_dump_test_role;
+GRANT UPDATE ON test_pg_dump_mv1 TO regress_dump_test_role;
+GRANT USAGE ON SCHEMA test_pg_dump_s1 TO regress_dump_test_role;
+GRANT USAGE ON TYPE test_pg_dump_e1 TO regress_dump_test_role;
+ALTER EXTENSION test_pg_dump ADD ACCESS METHOD gist2;
+ALTER EXTENSION test_pg_dump ADD AGGREGATE newavg(int4);
+ALTER EXTENSION test_pg_dump ADD CAST (text AS casttesttype);
+ALTER EXTENSION test_pg_dump ADD FOREIGN DATA WRAPPER dummy;
+ALTER EXTENSION test_pg_dump ADD FOREIGN TABLE ft1;
+ALTER EXTENSION test_pg_dump ADD MATERIALIZED VIEW test_pg_dump_mv1;
+ALTER EXTENSION test_pg_dump ADD OPERATOR ==== (int, int);
+ALTER EXTENSION test_pg_dump ADD SCHEMA test_pg_dump_s1;
+ALTER EXTENSION test_pg_dump ADD SERVER s0;
+ALTER EXTENSION test_pg_dump ADD FUNCTION test_pg_dump(int);
+ALTER EXTENSION test_pg_dump ADD TABLE test_pg_dump_t1;
+ALTER EXTENSION test_pg_dump ADD TYPE test_pg_dump_e1;
+ALTER EXTENSION test_pg_dump ADD VIEW test_pg_dump_v1;
+REVOKE SELECT (c1) ON test_pg_dump_t1 FROM regress_dump_test_role;
+REVOKE SELECT ON test_pg_dump_v1 FROM regress_dump_test_role;
+REVOKE USAGE ON FOREIGN DATA WRAPPER dummy FROM regress_dump_test_role;
+ALTER EXTENSION test_pg_dump DROP ACCESS METHOD gist2;
+ALTER EXTENSION test_pg_dump DROP AGGREGATE newavg(int4);
+ALTER EXTENSION test_pg_dump DROP CAST (text AS casttesttype);
+ALTER EXTENSION test_pg_dump DROP FOREIGN DATA WRAPPER dummy;
+ALTER EXTENSION test_pg_dump DROP FOREIGN TABLE ft1;
+ALTER EXTENSION test_pg_dump DROP FUNCTION test_pg_dump(int);
+ALTER EXTENSION test_pg_dump DROP MATERIALIZED VIEW test_pg_dump_mv1;
+ALTER EXTENSION test_pg_dump DROP OPERATOR ==== (int, int);
+ALTER EXTENSION test_pg_dump DROP SCHEMA test_pg_dump_s1;
+ALTER EXTENSION test_pg_dump DROP SERVER s0;
+ALTER EXTENSION test_pg_dump DROP TABLE test_pg_dump_t1;
+ALTER EXTENSION test_pg_dump DROP TYPE test_pg_dump_e1;
+ALTER EXTENSION test_pg_dump DROP VIEW test_pg_dump_v1;
diff --git a/src/test/modules/test_pg_dump/sql/test_pg_dump.sql b/src/test/modules/test_pg_dump/sql/test_pg_dump.sql
index e0ac49d1ecfb8f96f2418b1a87e1d20e587d9d0f..e463dec40402babdbaa7449c3fd0bad6fc6b7088 100644
--- a/src/test/modules/test_pg_dump/sql/test_pg_dump.sql
+++ b/src/test/modules/test_pg_dump/sql/test_pg_dump.sql
@@ -1 +1,107 @@
-SELECT 1;
+CREATE ROLE regress_dump_test_role;
+CREATE EXTENSION test_pg_dump;
+
+ALTER EXTENSION test_pg_dump ADD DATABASE postgres; -- error
+
+CREATE TABLE test_pg_dump_t1 (c1 int);
+CREATE VIEW test_pg_dump_v1 AS SELECT * FROM test_pg_dump_t1;
+CREATE MATERIALIZED VIEW test_pg_dump_mv1 AS SELECT * FROM test_pg_dump_t1;
+CREATE SCHEMA test_pg_dump_s1;
+CREATE TYPE test_pg_dump_e1 AS ENUM ('abc', 'def');
+
+CREATE AGGREGATE newavg (
+   sfunc = int4_avg_accum, basetype = int4, stype = _int8,
+   finalfunc = int8_avg,
+   initcond1 = '{0,0}'
+);
+
+CREATE FUNCTION test_pg_dump(int) RETURNS int AS $$
+BEGIN
+RETURN abs($1);
+END
+$$ LANGUAGE plpgsql IMMUTABLE;
+
+CREATE OPERATOR ==== (
+    LEFTARG = int,
+    RIGHTARG = int,
+    PROCEDURE = int4eq,
+    COMMUTATOR = ====
+);
+
+CREATE ACCESS METHOD gist2 TYPE INDEX HANDLER gisthandler;
+
+CREATE TYPE casttesttype;
+
+CREATE FUNCTION casttesttype_in(cstring)
+   RETURNS casttesttype
+   AS 'textin'
+   LANGUAGE internal STRICT IMMUTABLE;
+CREATE FUNCTION casttesttype_out(casttesttype)
+   RETURNS cstring
+   AS 'textout'
+   LANGUAGE internal STRICT IMMUTABLE;
+
+CREATE TYPE casttesttype (
+   internallength = variable,
+   input = casttesttype_in,
+   output = casttesttype_out,
+   alignment = int4
+);
+
+CREATE CAST (text AS casttesttype) WITHOUT FUNCTION;
+
+CREATE FOREIGN DATA WRAPPER dummy;
+
+CREATE SERVER s0 FOREIGN DATA WRAPPER dummy;
+
+CREATE FOREIGN TABLE ft1 (
+        c1 integer OPTIONS ("param 1" 'val1') NOT NULL,
+        c2 text OPTIONS (param2 'val2', param3 'val3') CHECK (c2 <> ''),
+        c3 date,
+        CHECK (c3 BETWEEN '1994-01-01'::date AND '1994-01-31'::date)
+) SERVER s0 OPTIONS (delimiter ',', quote '"', "be quoted" 'value');
+
+REVOKE EXECUTE ON FUNCTION test_pg_dump(int) FROM PUBLIC;
+GRANT EXECUTE ON FUNCTION test_pg_dump(int) TO regress_dump_test_role;
+
+GRANT SELECT (c1) ON test_pg_dump_t1 TO regress_dump_test_role;
+GRANT SELECT ON test_pg_dump_v1 TO regress_dump_test_role;
+GRANT USAGE ON FOREIGN DATA WRAPPER dummy TO regress_dump_test_role;
+GRANT USAGE ON FOREIGN SERVER s0 TO regress_dump_test_role;
+GRANT SELECT (c1) ON ft1 TO regress_dump_test_role;
+GRANT SELECT ON ft1 TO regress_dump_test_role;
+GRANT UPDATE ON test_pg_dump_mv1 TO regress_dump_test_role;
+GRANT USAGE ON SCHEMA test_pg_dump_s1 TO regress_dump_test_role;
+GRANT USAGE ON TYPE test_pg_dump_e1 TO regress_dump_test_role;
+
+ALTER EXTENSION test_pg_dump ADD ACCESS METHOD gist2;
+ALTER EXTENSION test_pg_dump ADD AGGREGATE newavg(int4);
+ALTER EXTENSION test_pg_dump ADD CAST (text AS casttesttype);
+ALTER EXTENSION test_pg_dump ADD FOREIGN DATA WRAPPER dummy;
+ALTER EXTENSION test_pg_dump ADD FOREIGN TABLE ft1;
+ALTER EXTENSION test_pg_dump ADD MATERIALIZED VIEW test_pg_dump_mv1;
+ALTER EXTENSION test_pg_dump ADD OPERATOR ==== (int, int);
+ALTER EXTENSION test_pg_dump ADD SCHEMA test_pg_dump_s1;
+ALTER EXTENSION test_pg_dump ADD SERVER s0;
+ALTER EXTENSION test_pg_dump ADD FUNCTION test_pg_dump(int);
+ALTER EXTENSION test_pg_dump ADD TABLE test_pg_dump_t1;
+ALTER EXTENSION test_pg_dump ADD TYPE test_pg_dump_e1;
+ALTER EXTENSION test_pg_dump ADD VIEW test_pg_dump_v1;
+
+REVOKE SELECT (c1) ON test_pg_dump_t1 FROM regress_dump_test_role;
+REVOKE SELECT ON test_pg_dump_v1 FROM regress_dump_test_role;
+REVOKE USAGE ON FOREIGN DATA WRAPPER dummy FROM regress_dump_test_role;
+
+ALTER EXTENSION test_pg_dump DROP ACCESS METHOD gist2;
+ALTER EXTENSION test_pg_dump DROP AGGREGATE newavg(int4);
+ALTER EXTENSION test_pg_dump DROP CAST (text AS casttesttype);
+ALTER EXTENSION test_pg_dump DROP FOREIGN DATA WRAPPER dummy;
+ALTER EXTENSION test_pg_dump DROP FOREIGN TABLE ft1;
+ALTER EXTENSION test_pg_dump DROP FUNCTION test_pg_dump(int);
+ALTER EXTENSION test_pg_dump DROP MATERIALIZED VIEW test_pg_dump_mv1;
+ALTER EXTENSION test_pg_dump DROP OPERATOR ==== (int, int);
+ALTER EXTENSION test_pg_dump DROP SCHEMA test_pg_dump_s1;
+ALTER EXTENSION test_pg_dump DROP SERVER s0;
+ALTER EXTENSION test_pg_dump DROP TABLE test_pg_dump_t1;
+ALTER EXTENSION test_pg_dump DROP TYPE test_pg_dump_e1;
+ALTER EXTENSION test_pg_dump DROP VIEW test_pg_dump_v1;
diff --git a/src/test/modules/test_pg_dump/t/001_base.pl b/src/test/modules/test_pg_dump/t/001_base.pl
index 156bd3d1723641ab209b61a2a81515bee4560d06..c8e8d4a94ce3106231912c78539e11f12beb8150 100644
--- a/src/test/modules/test_pg_dump/t/001_base.pl
+++ b/src/test/modules/test_pg_dump/t/001_base.pl
@@ -236,6 +236,30 @@ my %pgdump_runs = (
 # as the regexps are used for each run the test applies to.
 
 my %tests = (
+	'ALTER EXTENSION test_pg_dump' => {
+		create_order => 9,
+		create_sql   => 'ALTER EXTENSION test_pg_dump ADD TABLE regress_pg_dump_table_added;',
+		regexp => qr/^
+			\QCREATE TABLE regress_pg_dump_table_added (\E
+			\n\s+\Qcol1 integer NOT NULL,\E
+			\n\s+\Qcol2 integer\E
+			\n\);\n/xm,
+		like   => {
+			binary_upgrade      => 1,
+		},
+		unlike => {
+			clean               => 1,
+			clean_if_exists     => 1,
+			createdb            => 1,
+			defaults            => 1,
+			no_privs            => 1,
+			no_owner            => 1,
+			pg_dumpall_globals  => 1,
+			schema_only         => 1,
+			section_pre_data    => 1,
+			section_post_data   => 1,
+		 }, },
+
 	'CREATE EXTENSION test_pg_dump' => {
 		create_order => 2,
 		create_sql   => 'CREATE EXTENSION test_pg_dump;',
@@ -303,6 +327,30 @@ my %tests = (
 			section_post_data   => 1,
 		}, },
 
+	'CREATE TABLE regress_pg_dump_table_added' => {
+		create_order => 7,
+		create_sql => 'CREATE TABLE regress_pg_dump_table_added (col1 int not null, col2 int);',
+		regexp => qr/^
+			\QCREATE TABLE regress_pg_dump_table_added (\E
+			\n\s+\Qcol1 integer NOT NULL,\E
+			\n\s+\Qcol2 integer\E
+			\n\);\n/xm,
+		like   => {
+			binary_upgrade      => 1,
+		},
+		unlike => {
+			clean               => 1,
+			clean_if_exists     => 1,
+			createdb            => 1,
+			defaults            => 1,
+			no_privs            => 1,
+			no_owner            => 1,
+			pg_dumpall_globals  => 1,
+			schema_only         => 1,
+			section_pre_data    => 1,
+			section_post_data   => 1,
+		}, },
+
 	'CREATE SEQUENCE regress_pg_dump_seq' => {
 		regexp => qr/^
                     \QCREATE SEQUENCE regress_pg_dump_seq\E
@@ -413,6 +461,50 @@ my %tests = (
 			section_post_data   => 1,
 		}, },
 
+	'GRANT SELECT regress_pg_dump_table_added pre-ALTER EXTENSION' => {
+		create_order => 8,
+		create_sql   => 'GRANT SELECT ON regress_pg_dump_table_added TO regress_dump_test_role;',
+		regexp => qr/^
+			\QGRANT SELECT ON TABLE regress_pg_dump_table_added TO regress_dump_test_role;\E
+			\n/xm,
+		like   => {
+			binary_upgrade => 1,
+		},
+		unlike => {
+			clean              => 1,
+			clean_if_exists    => 1,
+			createdb           => 1,
+			defaults           => 1,
+			no_privs           => 1,
+			no_owner           => 1,
+			pg_dumpall_globals => 1,
+			schema_only        => 1,
+			section_pre_data   => 1,
+			section_post_data  => 1,
+		}, },
+
+	'REVOKE SELECT regress_pg_dump_table_added post-ALTER EXTENSION' => {
+		create_order => 10,
+		create_sql   => 'REVOKE SELECT ON regress_pg_dump_table_added FROM regress_dump_test_role;',
+		regexp => qr/^
+			\QREVOKE SELECT ON TABLE regress_pg_dump_table_added FROM regress_dump_test_role;\E
+			\n/xm,
+		like => {
+			binary_upgrade     => 1,
+			clean              => 1,
+			clean_if_exists    => 1,
+			createdb           => 1,
+			defaults           => 1,
+			no_owner           => 1,
+			schema_only        => 1,
+			section_pre_data   => 1,
+		},
+		unlike   => {
+			no_privs           => 1,
+			pg_dumpall_globals => 1,
+			section_post_data  => 1,
+		}, },
+
 	'GRANT SELECT ON TABLE regress_pg_dump_table' => {
 		regexp => qr/^
 			\QSELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\E\n