diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index f55aa36..fb03793 100644
*** a/src/bin/pg_dump/pg_backup_archiver.c
--- b/src/bin/pg_dump/pg_backup_archiver.c
*************** _printTocEntry(ArchiveHandle *AH, TocEnt
*** 3453,3481 ****
  {
  	RestoreOptions *ropt = AH->public.ropt;
  
- 	/*
- 	 * Avoid dumping the public schema, as it will already be created ...
- 	 * unless we are using --clean mode (and *not* --create mode), in which
- 	 * case we've previously issued a DROP for it so we'd better recreate it.
- 	 *
- 	 * Likewise for its comment, if any.  (We could try issuing the COMMENT
- 	 * command anyway; but it'd fail if the restore is done as non-super-user,
- 	 * so let's not.)
- 	 *
- 	 * XXX it looks pretty ugly to hard-wire the public schema like this, but
- 	 * it sits in a sort of no-mans-land between being a system object and a
- 	 * user object, so it really is special in a way.
- 	 */
- 	if (!(ropt->dropSchema && !ropt->createDB))
- 	{
- 		if (strcmp(te->desc, "SCHEMA") == 0 &&
- 			strcmp(te->tag, "public") == 0)
- 			return;
- 		if (strcmp(te->desc, "COMMENT") == 0 &&
- 			strcmp(te->tag, "SCHEMA public") == 0)
- 			return;
- 	}
- 
  	/* Select owner, schema, and tablespace as necessary */
  	_becomeOwner(AH, te);
  	_selectOutputSchema(AH, te->namespace);
--- 3453,3458 ----
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index d65ea54..50399c9 100644
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
*************** selectDumpableNamespace(NamespaceInfo *n
*** 1407,1412 ****
--- 1407,1425 ----
  		/* Other system schemas don't get dumped */
  		nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_NONE;
  	}
+ 	else if (strcmp(nsinfo->dobj.name, "public") == 0)
+ 	{
+ 		/*
+ 		 * The public schema is a strange beast that sits in a sort of
+ 		 * no-mans-land between being a system object and a user object.  We
+ 		 * don't want to dump creation or comment commands for it, because
+ 		 * that complicates matters for non-superuser use of pg_dump.  But we
+ 		 * should dump any ACL changes that have occurred for it, and of
+ 		 * course we should dump contained objects.
+ 		 */
+ 		nsinfo->dobj.dump = DUMP_COMPONENT_ACL;
+ 		nsinfo->dobj.dump_contains = DUMP_COMPONENT_ALL;
+ 	}
  	else
  		nsinfo->dobj.dump_contains = nsinfo->dobj.dump = DUMP_COMPONENT_ALL;
  
*************** selectDumpableAccessMethod(AccessMethodI
*** 1617,1637 ****
   * selectDumpableExtension: policy-setting subroutine
   *		Mark an extension as to be dumped or not
   *
!  * Normally, we dump all extensions, or none of them if include_everything
!  * is false (i.e., a --schema or --table switch was given).  However, in
!  * binary-upgrade mode it's necessary to skip built-in extensions, since we
   * assume those will already be installed in the target database.  We identify
   * such extensions by their having OIDs in the range reserved for initdb.
   */
  static void
  selectDumpableExtension(ExtensionInfo *extinfo, DumpOptions *dopt)
  {
  	/*
! 	 * Use DUMP_COMPONENT_ACL for from-initdb extensions, to allow users to
! 	 * change permissions on those objects, if they wish to, and have those
! 	 * changes preserved.
  	 */
! 	if (dopt->binary_upgrade && extinfo->dobj.catId.oid <= (Oid) g_last_builtin_oid)
  		extinfo->dobj.dump = extinfo->dobj.dump_contains = DUMP_COMPONENT_ACL;
  	else
  		extinfo->dobj.dump = extinfo->dobj.dump_contains =
--- 1630,1650 ----
   * selectDumpableExtension: policy-setting subroutine
   *		Mark an extension as to be dumped or not
   *
!  * Built-in extensions should be skipped except for checking ACLs, since we
   * assume those will already be installed in the target database.  We identify
   * such extensions by their having OIDs in the range reserved for initdb.
+  * We dump all user-added extensions by default, or none of them if
+  * include_everything is false (i.e., a --schema or --table switch was given).
   */
  static void
  selectDumpableExtension(ExtensionInfo *extinfo, DumpOptions *dopt)
  {
  	/*
! 	 * Use DUMP_COMPONENT_ACL for built-in extensions, to allow users to
! 	 * change permissions on their member objects, if they wish to, and have
! 	 * those changes preserved.
  	 */
! 	if (extinfo->dobj.catId.oid <= (Oid) g_last_builtin_oid)
  		extinfo->dobj.dump = extinfo->dobj.dump_contains = DUMP_COMPONENT_ACL;
  	else
  		extinfo->dobj.dump = extinfo->dobj.dump_contains =
*************** getNamespaces(Archive *fout, int *numNam
*** 4435,4463 ****
  						  init_acl_subquery->data,
  						  init_racl_subquery->data);
  
- 		/*
- 		 * When we are doing a 'clean' run, we will be dropping and recreating
- 		 * the 'public' schema (the only object which has that kind of
- 		 * treatment in the backend and which has an entry in pg_init_privs)
- 		 * and therefore we should not consider any initial privileges in
- 		 * pg_init_privs in that case.
- 		 *
- 		 * See pg_backup_archiver.c:_printTocEntry() for the details on why
- 		 * the public schema is special in this regard.
- 		 *
- 		 * Note that if the public schema is dropped and re-created, this is
- 		 * essentially a no-op because the new public schema won't have an
- 		 * entry in pg_init_privs anyway, as the entry will be removed when
- 		 * the public schema is dropped.
- 		 *
- 		 * Further, we have to handle the case where the public schema does
- 		 * not exist at all.
- 		 */
- 		if (dopt->outputClean)
- 			appendPQExpBuffer(query, " AND pip.objoid <> "
- 							  "coalesce((select oid from pg_namespace "
- 							  "where nspname = 'public'),0)");
- 
  		appendPQExpBuffer(query, ") ");
  
  		destroyPQExpBuffer(acl_subquery);
--- 4448,4453 ----
diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl
index 74730bf..3e9b4d9 100644
*** a/src/bin/pg_dump/t/002_pg_dump.pl
--- b/src/bin/pg_dump/t/002_pg_dump.pl
*************** qr/^ALTER (?!EVENT TRIGGER|LARGE OBJECT|
*** 1548,1577 ****
  		all_runs  => 1,
  		catch_all => 'COMMENT commands',
  		regexp    => qr/^COMMENT ON EXTENSION plpgsql IS .*;/m,
! 		like      => {
  			clean                    => 1,
  			clean_if_exists          => 1,
  			createdb                 => 1,
  			defaults                 => 1,
  			exclude_dump_test_schema => 1,
  			exclude_test_table       => 1,
  			exclude_test_table_data  => 1,
  			no_blobs                 => 1,
- 			no_privs                 => 1,
  			no_owner                 => 1,
  			pg_dumpall_dbprivs       => 1,
  			schema_only              => 1,
  			section_pre_data         => 1,
! 			with_oids                => 1, },
! 		unlike => {
! 			binary_upgrade         => 1,
! 			column_inserts         => 1,
! 			data_only              => 1,
! 			only_dump_test_schema  => 1,
! 			only_dump_test_table   => 1,
! 			role                   => 1,
! 			section_post_data      => 1,
! 			test_schema_plus_blobs => 1, }, },
  
  	'COMMENT ON TABLE dump_test.test_table' => {
  		all_runs     => 1,
--- 1548,1578 ----
  		all_runs  => 1,
  		catch_all => 'COMMENT commands',
  		regexp    => qr/^COMMENT ON EXTENSION plpgsql IS .*;/m,
! 		# this shouldn't ever get emitted anymore
! 		like      => {},
! 		unlike => {
! 			binary_upgrade           => 1,
  			clean                    => 1,
  			clean_if_exists          => 1,
+ 			column_inserts           => 1,
  			createdb                 => 1,
+ 			data_only                => 1,
  			defaults                 => 1,
  			exclude_dump_test_schema => 1,
  			exclude_test_table       => 1,
  			exclude_test_table_data  => 1,
  			no_blobs                 => 1,
  			no_owner                 => 1,
+ 			no_privs                 => 1,
+ 			only_dump_test_schema    => 1,
+ 			only_dump_test_table     => 1,
  			pg_dumpall_dbprivs       => 1,
+ 			role                     => 1,
  			schema_only              => 1,
+ 			section_post_data        => 1,
  			section_pre_data         => 1,
! 			test_schema_plus_blobs   => 1,
! 			with_oids                => 1, }, },
  
  	'COMMENT ON TABLE dump_test.test_table' => {
  		all_runs     => 1,
*************** qr/CREATE CAST \(timestamp with time zon
*** 2751,2783 ****
  		regexp   => qr/^
  			\QCREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;\E
  			/xm,
! 		like => {
  			clean                    => 1,
  			clean_if_exists          => 1,
  			createdb                 => 1,
  			defaults                 => 1,
  			exclude_dump_test_schema => 1,
  			exclude_test_table       => 1,
  			exclude_test_table_data  => 1,
  			no_blobs                 => 1,
- 			no_privs                 => 1,
  			no_owner                 => 1,
! 			pg_dumpall_dbprivs       => 1,
! 			schema_only              => 1,
! 			section_pre_data         => 1,
! 			with_oids                => 1, },
! 		unlike => {
! 			binary_upgrade           => 1,
! 			column_inserts           => 1,
! 			data_only                => 1,
  			only_dump_test_schema    => 1,
  			only_dump_test_table     => 1,
  			pg_dumpall_globals       => 1,
  			pg_dumpall_globals_clean => 1,
  			role                     => 1,
  			section_data             => 1,
  			section_post_data        => 1,
! 			test_schema_plus_blobs   => 1, }, },
  
  	'CREATE AGGREGATE dump_test.newavg' => {
  		all_runs     => 1,
--- 2752,2785 ----
  		regexp   => qr/^
  			\QCREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;\E
  			/xm,
! 		# this shouldn't ever get emitted anymore
! 		like => {},
! 		unlike => {
! 			binary_upgrade           => 1,
  			clean                    => 1,
  			clean_if_exists          => 1,
+ 			column_inserts           => 1,
  			createdb                 => 1,
+ 			data_only                => 1,
  			defaults                 => 1,
  			exclude_dump_test_schema => 1,
  			exclude_test_table       => 1,
  			exclude_test_table_data  => 1,
  			no_blobs                 => 1,
  			no_owner                 => 1,
! 			no_privs                 => 1,
  			only_dump_test_schema    => 1,
  			only_dump_test_table     => 1,
+ 			pg_dumpall_dbprivs       => 1,
  			pg_dumpall_globals       => 1,
  			pg_dumpall_globals_clean => 1,
  			role                     => 1,
+ 			schema_only              => 1,
  			section_data             => 1,
  			section_post_data        => 1,
! 			section_pre_data         => 1,
! 			test_schema_plus_blobs   => 1,
! 			with_oids                => 1, }, },
  
  	'CREATE AGGREGATE dump_test.newavg' => {
  		all_runs     => 1,
*************** qr/CREATE TRANSFORM FOR integer LANGUAGE
*** 4565,4575 ****
  		all_runs  => 1,
  		catch_all => 'CREATE ... commands',
  		regexp    => qr/^CREATE SCHEMA public;/m,
! 		like      => {
! 			clean           => 1,
! 			clean_if_exists => 1, },
  		unlike => {
  			binary_upgrade           => 1,
  			createdb                 => 1,
  			defaults                 => 1,
  			exclude_test_table       => 1,
--- 4567,4578 ----
  		all_runs  => 1,
  		catch_all => 'CREATE ... commands',
  		regexp    => qr/^CREATE SCHEMA public;/m,
! 		# this shouldn't ever get emitted anymore
! 		like      => {},
  		unlike => {
  			binary_upgrade           => 1,
+ 			clean                    => 1,
+ 			clean_if_exists          => 1,
  			createdb                 => 1,
  			defaults                 => 1,
  			exclude_test_table       => 1,
*************** qr/CREATE TRANSFORM FOR integer LANGUAGE
*** 5395,5402 ****
  		all_runs  => 1,
  		catch_all => 'DROP ... commands',
  		regexp    => qr/^DROP SCHEMA public;/m,
! 		like      => { clean => 1 },
  		unlike    => {
  			clean_if_exists          => 1,
  			pg_dumpall_globals_clean => 1, }, },
  
--- 5398,5407 ----
  		all_runs  => 1,
  		catch_all => 'DROP ... commands',
  		regexp    => qr/^DROP SCHEMA public;/m,
! 		# this shouldn't ever get emitted anymore
! 		like      => {},
  		unlike    => {
+ 			clean                    => 1,
  			clean_if_exists          => 1,
  			pg_dumpall_globals_clean => 1, }, },
  
*************** qr/CREATE TRANSFORM FOR integer LANGUAGE
*** 5404,5420 ****
  		all_runs  => 1,
  		catch_all => 'DROP ... commands',
  		regexp    => qr/^DROP SCHEMA IF EXISTS public;/m,
! 		like      => { clean_if_exists => 1 },
  		unlike    => {
  			clean                    => 1,
  			pg_dumpall_globals_clean => 1, }, },
  
  	'DROP EXTENSION plpgsql' => {
  		all_runs  => 1,
  		catch_all => 'DROP ... commands',
  		regexp    => qr/^DROP EXTENSION plpgsql;/m,
! 		like      => { clean => 1, },
  		unlike    => {
  			clean_if_exists          => 1,
  			pg_dumpall_globals_clean => 1, }, },
  
--- 5409,5429 ----
  		all_runs  => 1,
  		catch_all => 'DROP ... commands',
  		regexp    => qr/^DROP SCHEMA IF EXISTS public;/m,
! 		# this shouldn't ever get emitted anymore
! 		like      => {},
  		unlike    => {
  			clean                    => 1,
+ 			clean_if_exists          => 1,
  			pg_dumpall_globals_clean => 1, }, },
  
  	'DROP EXTENSION plpgsql' => {
  		all_runs  => 1,
  		catch_all => 'DROP ... commands',
  		regexp    => qr/^DROP EXTENSION plpgsql;/m,
! 		# this shouldn't ever get emitted anymore
! 		like      => {},
  		unlike    => {
+ 			clean => 1,
  			clean_if_exists          => 1,
  			pg_dumpall_globals_clean => 1, }, },
  
*************** qr/CREATE TRANSFORM FOR integer LANGUAGE
*** 5494,5502 ****
  		all_runs  => 1,
  		catch_all => 'DROP ... commands',
  		regexp    => qr/^DROP EXTENSION IF EXISTS plpgsql;/m,
! 		like      => { clean_if_exists => 1, },
  		unlike    => {
  			clean                    => 1,
  			pg_dumpall_globals_clean => 1, }, },
  
  	'DROP FUNCTION IF EXISTS dump_test.pltestlang_call_handler()' => {
--- 5503,5513 ----
  		all_runs  => 1,
  		catch_all => 'DROP ... commands',
  		regexp    => qr/^DROP EXTENSION IF EXISTS plpgsql;/m,
! 		# this shouldn't ever get emitted anymore
! 		like      => {},
  		unlike    => {
  			clean                    => 1,
+ 			clean_if_exists          => 1,
  			pg_dumpall_globals_clean => 1, }, },
  
  	'DROP FUNCTION IF EXISTS dump_test.pltestlang_call_handler()' => {
*************** qr/^GRANT SELECT ON TABLE measurement_y2
*** 6264,6274 ****
  			\Q--\E\n\n
  			\QGRANT USAGE ON SCHEMA public TO PUBLIC;\E
  			/xm,
! 		like => {
! 			clean           => 1,
! 			clean_if_exists => 1, },
  		unlike => {
  			binary_upgrade           => 1,
  			createdb                 => 1,
  			defaults                 => 1,
  			exclude_dump_test_schema => 1,
--- 6275,6286 ----
  			\Q--\E\n\n
  			\QGRANT USAGE ON SCHEMA public TO PUBLIC;\E
  			/xm,
! 		# this shouldn't ever get emitted anymore
! 		like => {},
  		unlike => {
  			binary_upgrade           => 1,
+ 			clean                    => 1,
+ 			clean_if_exists          => 1,
  			createdb                 => 1,
  			defaults                 => 1,
  			exclude_dump_test_schema => 1,
*************** qr/^GRANT SELECT ON TABLE measurement_y2
*** 6537,6542 ****
--- 6549,6556 ----
  			/xm,
  		like => {
  			binary_upgrade           => 1,
+ 			clean                    => 1,
+ 			clean_if_exists          => 1,
  			createdb                 => 1,
  			defaults                 => 1,
  			exclude_dump_test_schema => 1,
*************** qr/^GRANT SELECT ON TABLE measurement_y2
*** 6549,6556 ****
  			section_pre_data         => 1,
  			with_oids                => 1, },
  		unlike => {
- 			clean                    => 1,
- 			clean_if_exists          => 1,
  			only_dump_test_schema    => 1,
  			only_dump_test_table     => 1,
  			pg_dumpall_globals_clean => 1,
--- 6563,6568 ----
*************** qr/^GRANT SELECT ON TABLE measurement_y2
*** 6576,6593 ****
  			exclude_test_table_data  => 1,
  			no_blobs                 => 1,
  			no_owner                 => 1,
  			pg_dumpall_dbprivs       => 1,
  			schema_only              => 1,
  			section_pre_data         => 1,
  			with_oids                => 1, },
  		unlike => {
- 			only_dump_test_schema    => 1,
- 			only_dump_test_table     => 1,
  			pg_dumpall_globals_clean => 1,
- 			role                     => 1,
  			section_data             => 1,
! 			section_post_data        => 1,
! 			test_schema_plus_blobs   => 1, }, },
  
  	'REVOKE commands' => {    # catch-all for REVOKE commands
  		all_runs => 0,               # catch-all
--- 6588,6605 ----
  			exclude_test_table_data  => 1,
  			no_blobs                 => 1,
  			no_owner                 => 1,
+ 			only_dump_test_schema    => 1,
+ 			only_dump_test_table     => 1,
  			pg_dumpall_dbprivs       => 1,
+ 			role                     => 1,
  			schema_only              => 1,
  			section_pre_data         => 1,
+ 			test_schema_plus_blobs   => 1,
  			with_oids                => 1, },
  		unlike => {
  			pg_dumpall_globals_clean => 1,
  			section_data             => 1,
! 			section_post_data        => 1, }, },
  
  	'REVOKE commands' => {    # catch-all for REVOKE commands
  		all_runs => 0,               # catch-all
