diff --git a/src/bin/pg_dump/Makefile b/src/bin/pg_dump/Makefile
index 95967893d8226cbc1fde3266d1d1fc972b623c14..260804b5a7e555acc90844e5e58771ae3b4525cc 100644
--- a/src/bin/pg_dump/Makefile
+++ b/src/bin/pg_dump/Makefile
@@ -42,6 +42,9 @@ install: all installdirs
 installdirs:
 	$(MKDIR_P) '$(DESTDIR)$(bindir)'
 
+check:
+	$(prove_check)
+
 uninstall:
 	rm -f $(addprefix '$(DESTDIR)$(bindir)'/, pg_dump$(X) pg_restore$(X) pg_dumpall$(X))
 
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 6e2610fa3ffe1787f6f779aad7619f7600f55fe9..1267afbce9a7c62488ab28b231b600e1952ccfd6 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -1564,7 +1564,7 @@ selectDumpableExtension(ExtensionInfo *extinfo, DumpOptions *dopt)
 	 * those changes preserved.
 	 */
 	if (dopt->binary_upgrade && extinfo->dobj.catId.oid < (Oid) FirstNormalObjectId)
-		extinfo->dobj.dump = DUMP_COMPONENT_ACL;
+		extinfo->dobj.dump = extinfo->dobj.dump_contains = DUMP_COMPONENT_ACL;
 	else
 		extinfo->dobj.dump = extinfo->dobj.dump_contains =
 			dopt->include_everything ?  DUMP_COMPONENT_ALL :
diff --git a/src/bin/pg_dump/t/001_basic.pl b/src/bin/pg_dump/t/001_basic.pl
new file mode 100644
index 0000000000000000000000000000000000000000..1411ef7a271535d44d4f26e17eb56b59c26af45c
--- /dev/null
+++ b/src/bin/pg_dump/t/001_basic.pl
@@ -0,0 +1,42 @@
+use strict;
+use warnings;
+
+use Config;
+use PostgresNode;
+use TestLib;
+use Test::More tests => 15;
+
+my $tempdir       = TestLib::tempdir;
+my $tempdir_short = TestLib::tempdir_short;
+
+#########################################
+# Basic checks
+
+program_help_ok('pg_dump');
+program_version_ok('pg_dump');
+program_options_handling_ok('pg_dump');
+
+#########################################
+# Test various invalid options and disallowed combinations
+# Doesn't require a PG instance to be set up, so do this first.
+
+command_exit_is([ 'pg_dump', 'qqq', 'abc' ],
+	1, 'pg_dump: too many command-line arguments (first is "asd")');
+
+command_exit_is([ 'pg_dump', '-s', '-a' ],
+	1, 'pg_dump: options -s/--schema-only and -a/--data-only cannot be used together');
+
+command_exit_is([ 'pg_dump', '-c', '-a' ],
+	1, 'pg_dump: options -c/--clean and -a/--data-only cannot be used together');
+
+command_exit_is([ 'pg_dump', '--inserts', '-o' ],
+	1, 'pg_dump: options --inserts/--column-inserts and -o/--oids cannot be used together');
+
+command_exit_is([ 'pg_dump', '--if-exists' ],
+	1, 'pg_dump: option --if-exists requires option -c/--clean');
+
+command_exit_is([ 'pg_dump', '-j' ],
+	1, 'pg_dump: option requires an argument -- \'j\'');
+
+command_exit_is([ 'pg_dump', '-j3' ],
+	1, 'pg_dump: parallel backup only supported by the directory format');
diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl
new file mode 100644
index 0000000000000000000000000000000000000000..4270042250b864dafe091d142950e0af0a27d1ec
--- /dev/null
+++ b/src/bin/pg_dump/t/002_pg_dump.pl
@@ -0,0 +1,2859 @@
+use strict;
+use warnings;
+
+use Config;
+use PostgresNode;
+use TestLib;
+use Test::More;
+
+my $tempdir       = TestLib::tempdir;
+my $tempdir_short = TestLib::tempdir_short;
+
+###############################################################
+# Definition of the pg_dump runs to make.
+#
+# Each of these runs are named and those names are used below
+# to define how each test should (or shouldn't) treat a result
+# from a given run.
+#
+# test_key indicates that a given run should simply use the same
+# set of like/unlike tests as another run, and which run that is.
+#
+# dump_cmd is the pg_dump command to run, which is an array of
+# the full command and arguments to run.  Note that this is run
+# using $node->command_ok(), so the port does not need to be
+# specified and is pulled from $PGPORT, which is set by the
+# PostgresNode system.
+#
+# restore_cmd is the pg_restore command to run, if any.  Note
+# that this should generally be used when the pg_dump goes to
+# a non-text file and that the restore can then be used to
+# generate a text file to run through the tests from the
+# non-text file generated by pg_dump.
+#
+# TODO: Have pg_restore actually restore to an independent
+# database and then pg_dump *that* database (or something along
+# those lines) to validate that part of the process.
+
+my %pgdump_runs = (
+	binary_upgrade => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/binary_upgrade.sql",
+			'--schema-only',
+			'--binary-upgrade',
+			'-d', 'postgres', # alternative way to specify database
+		],
+	},
+	clean => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/clean.sql",
+			'-c',
+			'-d', 'postgres', # alternative way to specify database
+		],
+	},
+	clean_if_exists => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/clean_if_exists.sql",
+			'-c',
+			'--if-exists',
+			'-E', 'UTF8', # no-op, just tests that option is accepted
+			'postgres',
+		],
+	},
+	column_inserts => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/column_inserts.sql",
+			'-a',
+			'--column-inserts',
+			'postgres',
+		],
+	},
+	createdb => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/createdb.sql",
+			'-C',
+			'-R', # no-op, just for testing
+			'postgres',
+		],
+	},
+	data_only => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/data_only.sql",
+			'-a',
+			'-v', # no-op, just make sure it works
+			'postgres',
+		],
+	},
+	defaults => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/defaults.sql",
+			'postgres',
+		],
+	},
+	defaults_custom_format => {
+		test_key => 'defaults',
+		dump_cmd => [
+			'pg_dump',
+			'-Fc',
+			'-Z6',
+			'-f', "$tempdir/defaults_custom_format.dump",
+			'postgres',
+		],
+		restore_cmd => [
+			'pg_restore',
+			'-f', "$tempdir/defaults_custom_format.sql",
+			"$tempdir/defaults_custom_format.dump",
+		],
+	},
+	defaults_dir_format => {
+		test_key => 'defaults',
+		dump_cmd => [
+			'pg_dump',
+			'-Fd',
+			'-f', "$tempdir/defaults_dir_format",
+			'postgres',
+		],
+		restore_cmd => [
+			'pg_restore',
+			'-f', "$tempdir/defaults_dir_format.sql",
+			"$tempdir/defaults_dir_format",
+		],
+	},
+	defaults_parallel => {
+		test_key => 'defaults',
+		dump_cmd => [
+			'pg_dump',
+			'-Fd',
+			'-j2',
+			'-f', "$tempdir/defaults_parallel",
+			'postgres',
+		],
+		restore_cmd => [
+			'pg_restore',
+			'-f', "$tempdir/defaults_parallel.sql",
+			"$tempdir/defaults_parallel",
+		],
+	},
+	defaults_tar_format => {
+		test_key => 'defaults',
+		dump_cmd => [
+			'pg_dump',
+			'-Ft',
+			'-f', "$tempdir/defaults_tar_format.tar",
+			'postgres',
+		],
+		restore_cmd => [
+			'pg_restore',
+			'-f', "$tempdir/defaults_tar_format.sql",
+			"$tempdir/defaults_tar_format.tar",
+		],
+	},
+	exclude_dump_test_schema => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/exclude_dump_test_schema.sql",
+			'-N', 'dump_test',
+			'postgres',
+		],
+	},
+	exclude_test_table => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/exclude_test_table.sql",
+			'-T', 'dump_test.test_table',
+			'postgres',
+		],
+	},
+	exclude_test_table_data => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/exclude_test_table_data.sql",
+			'--exclude-table-data=dump_test.test_table',
+			'postgres',
+		],
+	},
+	pg_dumpall_globals => {
+		dump_cmd => [
+			'pg_dumpall',
+			'-f', "$tempdir/pg_dumpall_globals.sql",
+			'-g',
+		],
+	},
+	no_privs => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/no_privs.sql",
+			'-x',
+			'postgres',
+		],
+	},
+	no_owner => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/no_owner.sql",
+			'-O',
+			'postgres',
+		],
+	},
+	only_dump_test_schema => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/only_dump_test_schema.sql",
+			'-n', 'dump_test',
+			'postgres',
+		],
+	},
+	only_dump_test_table => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/only_dump_test_table.sql",
+			'-t', 'dump_test.test_table',
+			'--lock-wait-timeout=1000000',
+			'postgres',
+		],
+	},
+	role => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/role.sql",
+			'--role=dump_test',
+			'--schema=dump_test_second_schema',
+			'postgres',
+		],
+	},
+	schema_only => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/schema_only.sql",
+			'-s',
+			'postgres',
+		],
+	},
+	section_pre_data => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/section_pre_data.sql",
+			'--section=pre-data',
+			'postgres',
+		],
+	},
+	section_data => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/section_data.sql",
+			'--section=data',
+			'postgres',
+		],
+	},
+	section_post_data => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/section_post_data.sql",
+			'--section=post-data',
+			'postgres',
+		],
+	},
+	test_schema_plus_blobs => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/test_schema_plus_blobs.sql",
+			'-n', 'dump_test',
+			'-b',
+			'postgres',
+		],
+	},
+);
+
+###############################################################
+# Definition of the tests to run.
+#
+# Each test is defined using the log message that will be used.
+#
+# A regexp should be defined for each test which provides the
+# basis for the test.  That regexp will be run against the output
+# file of each of the runs which the test is to be run against
+# and the success of the result will depend on if the regexp
+# result matches the expected 'like' or 'unlike' case.
+#
+# For each test, there are two sets of runs defined, one for
+# the 'like' tests and one for the 'unlike' tests.  'like'
+# essentially means "the regexp for this test must match the
+# output file".  'unlike' is the opposite.
+#
+# There are a few 'catch-all' tests which can be used to have
+# a single, simple, test to over a range of other tests.  For
+# example, there is a '^CREATE ' test, which is used for the
+# 'data-only' test as there should never be any kind of CREATE
+# statement in a 'data-only' run.  Without the catch-all, we
+# would have to list the 'data-only' run in each and every
+# 'CREATE xxxx' test, which would be a lot of additional tests.
+#
+# Note that it makes no sense for the same run to ever be listed
+# in both 'like' and 'unlike' categories.
+#
+# There can then be a 'create_sql' and 'create_order' for a
+# given test.  The 'create_sql' commands are collected up in
+# 'create_order' and then run against the database prior to any
+# of the pg_dump runs happening.  This is what "seeds" the
+# system with objects to be dumped out.
+#
+# Building of this hash takes a bit of time as all of the regexps
+# included in it are compiled.  This greatly improves performance
+# as the regexps are used for each run the test applies to.
+
+my %tests = (
+	'ALTER DEFAULT PRIVILEGES FOR ROLE dump_test' => {
+		create_order => 14,
+		create_sql => 'ALTER DEFAULT PRIVILEGES
+					   FOR ROLE dump_test IN SCHEMA dump_test
+					   GRANT SELECT ON TABLES TO dump_test;',
+		regexp => qr/^
+			\QALTER DEFAULT PRIVILEGES \E
+			\QFOR ROLE dump_test IN SCHEMA dump_test \E
+			\QGRANT SELECT ON TABLES  TO dump_test;\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			no_privs => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_pre_data => 1,
+			section_data => 1,
+		},
+	},
+	'ALTER ROLE dump_test' => {
+		regexp => qr/^
+			\QALTER ROLE dump_test WITH \E
+			\QNOSUPERUSER INHERIT NOCREATEROLE NOCREATEDB NOLOGIN \E
+			\QNOREPLICATION NOBYPASSRLS;\E
+			$/xm,
+		like => {
+			pg_dumpall_globals => 1,
+		},
+		unlike => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'ALTER FUNCTION dump_test.pltestlang_call_handler() OWNER TO' => {
+		regexp => qr/^
+			\QALTER FUNCTION dump_test.pltestlang_call_handler() \E
+			\QOWNER TO \E
+			.*;$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+		},
+	},
+	'ALTER PROCEDURAL LANGUAGE pltestlang OWNER TO' => {
+		regexp => qr/^ALTER PROCEDURAL LANGUAGE pltestlang OWNER TO .*;$/m,
+		like => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'ALTER SCHEMA dump_test OWNER TO' => {
+		regexp => qr/^ALTER SCHEMA dump_test OWNER TO .*;$/m,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+		},
+	},
+	'ALTER SCHEMA dump_test_second_schema OWNER TO' => {
+		regexp => qr/^ALTER SCHEMA dump_test_second_schema OWNER TO .*;$/m,
+		like => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'ALTER TABLE ONLY test_table ADD CONSTRAINT ... PRIMARY KEY' => {
+		regexp => qr/^
+			\QALTER TABLE ONLY test_table\E \n^\s+
+			\QADD CONSTRAINT test_table_pkey PRIMARY KEY (col1);\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_pre_data => 1,
+			section_data => 1,
+		},
+	},
+	'ALTER TABLE test_table OWNER TO' => {
+		regexp => qr/^ALTER TABLE test_table OWNER TO .*;$/m,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+		},
+	},
+	'ALTER TABLE test_table ENABLE ROW LEVEL SECURITY' => {
+		create_order => 23,
+		create_sql => 'ALTER TABLE dump_test.test_table
+					   ENABLE ROW LEVEL SECURITY;',
+		regexp => qr/^ALTER TABLE test_table ENABLE ROW LEVEL SECURITY;$/m,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			section_pre_data => 1,
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+		},
+	},
+	'ALTER TABLE test_second_table OWNER TO' => {
+		regexp => qr/^ALTER TABLE test_second_table OWNER TO .*;$/m,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+		},
+	},
+	'ALTER TABLE test_third_table OWNER TO' => {
+		regexp => qr/^ALTER TABLE test_third_table OWNER TO .*;$/m,
+		like => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	# catch-all for ALTER ... OWNER (except LARGE OBJECTs)
+	'ALTER ... OWNER commands (except LARGE OBJECTs)' => {
+		regexp => qr/^ALTER (?!LARGE OBJECT)(.*) OWNER TO .*;$/m,
+		like => { }, # use more-specific options above
+		unlike => {
+			column_inserts => 1,
+			data_only => 1,
+			section_data => 1,
+		},
+	},
+	# catch-all for ALTER ... OWNER
+	'ALTER ... OWNER commands' => {
+		regexp => qr/^ALTER .* OWNER TO .*;$/m,
+		like => { }, # use more-specific options above
+		unlike => {
+			no_owner => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'BLOB load (contents are of test_table)' => {
+		create_order => 14,
+		create_sql =>
+		    "\\o '$tempdir/large_object_test.sql'\n"
+		  . "table dump_test.test_table;\n"
+		  . "\\o\n"
+		  . "\\lo_import '$tempdir/large_object_test.sql'\n",
+		regexp => qr/^
+			\QSELECT pg_catalog.lo_open\E \('\d+',\ \d+\);\n
+			\QSELECT pg_catalog.lowrite(0, \E
+			\Q'\x310a320a330a340a350a360a370a380a390a');\E\n
+			\QSELECT pg_catalog.lo_close(0);\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_privs => 1,
+			section_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			binary_upgrade => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			schema_only => 1,
+			section_post_data => 1,
+		},
+	},
+	'COMMENT ON DATABASE postgres' => {
+		regexp => qr/^COMMENT ON DATABASE postgres IS .*;$/m,
+		like => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+		},
+	},
+	'COMMENT ON EXTENSION plpgsql' => {
+		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_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			binary_upgrade => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+		},
+	},
+	'COMMENT ON TABLE dump_test.test_table' => {
+		create_order => 36,
+		create_sql => 'COMMENT ON TABLE dump_test.test_table
+					   IS \'comment on table\';',
+		regexp => qr/^COMMENT ON TABLE test_table IS 'comment on table';$/m,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+		},
+	},
+	'COMMENT ON COLUMN dump_test.test_table.col1' => {
+		create_order => 36,
+		create_sql => 'COMMENT ON COLUMN dump_test.test_table.col1
+					   IS \'comment on column\';',
+		regexp => qr/^
+			\QCOMMENT ON COLUMN test_table.col1 IS 'comment on column';\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+		},
+	},
+	'COMMENT ON COLUMN dump_test.composite.f1' => {
+		create_order => 44,
+		create_sql => 'COMMENT ON COLUMN dump_test.composite.f1
+					   IS \'comment on column of type\';',
+		regexp => qr/^
+			\QCOMMENT ON COLUMN composite.f1 IS 'comment on column of type';\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+		},
+	},
+	# catch-all for COMMENTs
+	'COMMENT commands' => {
+		regexp => qr/^COMMENT ON /m,
+		like => { }, # use more-specific options above
+		unlike => {
+			column_inserts => 1,
+			data_only => 1,
+			pg_dumpall_globals => 1,
+			section_data => 1,
+			section_post_data => 1,
+		},
+	},
+	'COPY test_table' => {
+		create_order => 4,
+		create_sql =>
+		    'INSERT INTO dump_test.test_table (col1) '
+		  . 'SELECT generate_series FROM generate_series(1,9);',
+		regexp => qr/^
+			\QCOPY test_table (col1) FROM stdin;\E
+			\n(?:\d\n){9}\\\.\n
+			$/xm,
+		like => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			data_only => 1,
+			defaults => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			section_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+		},
+	},
+	'COPY fk_reference_test_table' => {
+		create_order => 22,
+		create_sql =>
+		    'INSERT INTO dump_test.fk_reference_test_table (col1) '
+		  . 'SELECT generate_series FROM generate_series(1,5);',
+		regexp => qr/^
+			\QCOPY fk_reference_test_table (col1) FROM stdin;\E
+			\n(?:\d\n){5}\\\.\n
+			$/xm,
+		like => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			data_only => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			section_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+		},
+	},
+	'COPY fk_reference_test_table second' => {
+		regexp => qr/^
+			\QCOPY test_table (col1) FROM stdin;\E
+			\n(?:\d\n){9}\\\.\n.*
+			\QCOPY fk_reference_test_table (col1) FROM stdin;\E
+			\n(?:\d\n){5}\\\.\n
+			$/xms,
+		like => {
+			data_only => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+		},
+	},
+	'COPY test_second_table' => {
+		create_order => 7,
+		create_sql =>
+		    'INSERT INTO dump_test.test_second_table (col1, col2) '
+		  . 'SELECT generate_series, generate_series::text '
+		  . 'FROM generate_series(1,9);',
+		regexp => qr/^
+			\QCOPY test_second_table (col1, col2) FROM stdin;\E
+			\n(?:\d\t\d\n){9}\\\.\n
+			$/xm,
+		like => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			data_only => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			section_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+		},
+	},
+	'COPY test_third_table' => {
+		create_order => 12,
+		create_sql =>
+			'INSERT INTO dump_test_second_schema.test_third_table (col1) '
+		  . 'SELECT generate_series FROM generate_series(1,9);',
+		regexp => qr/^
+			\QCOPY test_third_table (col1) FROM stdin;\E
+			\n(?:\d\n){9}\\\.\n
+			$/xm,
+		like => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			data_only => 1,
+			defaults => 1,
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			section_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'INSERT INTO test_table' => {
+		regexp => qr/^
+			(?:INSERT\ INTO\ test_table\ \(col1\)\ VALUES\ \(\d\);\n){9}
+			$/xm,
+		like => {
+			column_inserts => 1,
+		},
+		unlike => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			data_only => 1,
+			defaults => 1,
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			section_data => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'INSERT INTO test_second_table' => {
+		regexp => qr/^
+			(?:INSERT\ INTO\ test_second_table\ \(col1,\ col2\)
+			   \ VALUES\ \(\d,\ '\d'\);\n){9}$/xm,
+		like => {
+			column_inserts => 1,
+		},
+		unlike => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			data_only => 1,
+			defaults => 1,
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			section_data => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'INSERT INTO test_third_table' => {
+		regexp => qr/^
+			(?:INSERT\ INTO\ test_third_table\ \(col1\)
+			   \ VALUES\ \(\d\);\n){9}$/xm,
+		like => {
+			column_inserts => 1,
+		},
+		unlike => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			data_only => 1,
+			defaults => 1,
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			section_data => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'COPY ... commands' => { # catch-all for COPY
+		regexp => qr/^COPY /m,
+		like => { }, # use more-specific options above
+		unlike => {
+			binary_upgrade => 1,
+			column_inserts => 1,
+			pg_dumpall_globals => 1,
+			schema_only => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE ROLE dump_test' => {
+		create_order => 1,
+		create_sql => 'CREATE ROLE dump_test;',
+		regexp => qr/^CREATE ROLE dump_test;$/m,
+		like => {
+			pg_dumpall_globals => 1,
+		},
+		unlike => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'CREATE DATABASE postgres' => {
+		regexp => qr/^
+			\QCREATE DATABASE postgres WITH TEMPLATE = template0 \E
+			.*;$/xm,
+		like => {
+			createdb => 1,
+		},
+		unlike => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			defaults => 1,
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'CREATE EXTENSION ... plpgsql' => {
+		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_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			binary_upgrade => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'CREATE AGGREGATE dump_test.newavg' => {
+		create_order => 25,
+		create_sql => 'CREATE AGGREGATE dump_test.newavg (
+						  sfunc = int4_avg_accum,
+						  basetype = int4,
+						  stype = _int8,
+						  finalfunc = int8_avg,
+						  initcond1 = \'{0,0}\'
+					   );',
+		regexp => qr/^
+			\QCREATE AGGREGATE newavg(integer) (\E
+			\n\s+\QSFUNC = int4_avg_accum,\E
+			\n\s+\QSTYPE = bigint[],\E
+			\n\s+\QINITCOND = '{0,0}',\E
+			\n\s+\QFINALFUNC = int8_avg\E
+			\n\);$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE DOMAIN dump_test.us_postal_code' => {
+		create_order => 29,
+		create_sql => 'CREATE DOMAIN dump_test.us_postal_code AS TEXT
+					   CHECK(VALUE ~ \'^\d{5}$\' OR
+							 VALUE ~ \'^\d{5}-\d{4}$\');',
+		regexp => qr/^
+			\QCREATE DOMAIN us_postal_code AS text\E
+			\n\s+
+			\QCONSTRAINT us_postal_code_check CHECK \E
+			\Q(((VALUE ~ '^\d{5}\E
+			\$\Q'::text) OR (VALUE ~ '^\d{5}-\d{4}\E\$
+			\Q'::text)));\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE FUNCTION dump_test.pltestlang_call_handler' => {
+		create_order => 17,
+		create_sql => 'CREATE FUNCTION dump_test.pltestlang_call_handler()
+					   RETURNS LANGUAGE_HANDLER AS \'$libdir/plpgsql\',
+					   \'plpgsql_call_handler\' LANGUAGE C;',
+		regexp => qr/^
+			\QCREATE FUNCTION pltestlang_call_handler() \E
+			\QRETURNS language_handler\E
+			\n\s+\QLANGUAGE c\E
+			\n\s+AS\ \'\$
+			\Qlibdir\/plpgsql', 'plpgsql_call_handler';\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE FUNCTION dump_test.trigger_func' => {
+		create_order => 30,
+		create_sql => 'CREATE FUNCTION dump_test.trigger_func()
+					   RETURNS trigger LANGUAGE plpgsql
+					   AS $$ BEGIN RETURN NULL; END;$$;',
+		regexp => qr/^
+			\QCREATE FUNCTION trigger_func() RETURNS trigger\E
+			\n\s+\QLANGUAGE plpgsql\E
+			\n\s+AS\ \$\$
+			\Q BEGIN RETURN NULL; END;\E
+			\$\$;$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE FUNCTION dump_test.event_trigger_func' => {
+		create_order => 32,
+		create_sql => 'CREATE FUNCTION dump_test.event_trigger_func()
+					   RETURNS event_trigger LANGUAGE plpgsql
+					   AS $$ BEGIN RETURN; END;$$;',
+		regexp => qr/^
+			\QCREATE FUNCTION event_trigger_func() RETURNS event_trigger\E
+			\n\s+\QLANGUAGE plpgsql\E
+			\n\s+AS\ \$\$
+			\Q BEGIN RETURN; END;\E
+			\$\$;$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE EVENT TRIGGER test_event_trigger' => {
+		create_order => 33,
+		create_sql => 'CREATE EVENT TRIGGER test_event_trigger
+					   ON ddl_command_start
+					   EXECUTE PROCEDURE dump_test.event_trigger_func();',
+		regexp => qr/^
+			\QCREATE EVENT TRIGGER test_event_trigger \E
+			\QON ddl_command_start\E
+			\n\s+\QEXECUTE PROCEDURE dump_test.event_trigger_func();\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_post_data => 1,
+		},
+		unlike => {
+			section_pre_data => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'CREATE TRIGGER test_trigger' => {
+		create_order => 31,
+		create_sql => 'CREATE TRIGGER test_trigger
+					   BEFORE INSERT ON dump_test.test_table
+					   FOR EACH ROW WHEN (NEW.col1 > 10)
+					   EXECUTE PROCEDURE dump_test.trigger_func();',
+		regexp => qr/^
+			\QCREATE TRIGGER test_trigger BEFORE INSERT ON test_table \E
+			\QFOR EACH ROW WHEN ((new.col1 > 10)) \E
+			\QEXECUTE PROCEDURE trigger_func();\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			section_pre_data => 1,
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			pg_dumpall_globals => 1,
+		},
+	},
+	'CREATE TYPE dump_test.planets AS ENUM' => {
+		create_order => 37,
+		create_sql => 'CREATE TYPE dump_test.planets
+					   AS ENUM ( \'venus\', \'earth\', \'mars\' );',
+		regexp => qr/^
+			\QCREATE TYPE planets AS ENUM (\E
+			\n\s+'venus',
+			\n\s+'earth',
+			\n\s+'mars'
+			\n\);$/xm,
+		like => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE TYPE dump_test.planets AS ENUM pg_upgrade' => {
+		regexp => qr/^
+			\QCREATE TYPE planets AS ENUM (\E
+			\n\);.*^
+			\QALTER TYPE dump_test.planets ADD VALUE 'venus';\E
+			\n.*^
+			\QALTER TYPE dump_test.planets ADD VALUE 'earth';\E
+			\n.*^
+			\QALTER TYPE dump_test.planets ADD VALUE 'mars';\E
+			\n$/xms,
+		like => {
+			binary_upgrade => 1,
+		},
+		unlike => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE TYPE dump_test.textrange AS RANGE' => {
+		create_order => 38,
+		create_sql => 'CREATE TYPE dump_test.textrange
+					   AS RANGE (subtype=text, collation="C");',
+		regexp => qr/^
+			\QCREATE TYPE textrange AS RANGE (\E
+			\n\s+\Qsubtype = text,\E
+			\n\s+\Qcollation = pg_catalog."C"\E
+			\n\);/xm,
+		like => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE TYPE dump_test.int42' => {
+		create_order => 39,
+		create_sql => 'CREATE TYPE dump_test.int42;',
+		regexp => qr/^CREATE TYPE int42;/m,
+		like => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE FUNCTION dump_test.int42_in' => {
+		create_order => 40,
+		create_sql => 'CREATE FUNCTION dump_test.int42_in(cstring)
+					   RETURNS dump_test.int42 AS \'int4in\'
+					   LANGUAGE internal STRICT IMMUTABLE;',
+		regexp => qr/^
+			\QCREATE FUNCTION int42_in(cstring) RETURNS int42\E
+			\n\s+\QLANGUAGE internal IMMUTABLE STRICT\E
+			\n\s+AS\ \$\$int4in\$\$;
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE FUNCTION dump_test.int42_out' => {
+		create_order => 41,
+		create_sql => 'CREATE FUNCTION dump_test.int42_out(dump_test.int42)
+					   RETURNS cstring AS \'int4out\'
+					   LANGUAGE internal STRICT IMMUTABLE;',
+		regexp => qr/^
+			\QCREATE FUNCTION int42_out(int42) RETURNS cstring\E
+			\n\s+\QLANGUAGE internal IMMUTABLE STRICT\E
+			\n\s+AS\ \$\$int4out\$\$;
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE TYPE dump_test.int42 populated' => {
+		create_order => 42,
+		create_sql => 'CREATE TYPE dump_test.int42 (
+						   internallength = 4,
+						   input = dump_test.int42_in,
+						   output = dump_test.int42_out,
+						   alignment = int4,
+						   default = 42,
+						   passedbyvalue);',
+		regexp => qr/^
+			\QCREATE TYPE int42 (\E
+			\n\s+\QINTERNALLENGTH = 4,\E
+			\n\s+\QINPUT = int42_in,\E
+			\n\s+\QOUTPUT = int42_out,\E
+			\n\s+\QDEFAULT = '42',\E
+			\n\s+\QALIGNMENT = int4,\E
+			\n\s+\QSTORAGE = plain,\E
+			\n\s+PASSEDBYVALUE\n\);
+			$/xm,
+		like => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE TYPE dump_test.composite' => {
+		create_order => 43,
+		create_sql => 'CREATE TYPE dump_test.composite AS (
+						   f1 int,
+						   f2 dump_test.int42
+					   );',
+		regexp => qr/^
+			\QCREATE TYPE composite AS (\E
+			\n\s+\Qf1 integer,\E
+			\n\s+\Qf2 int42\E
+			\n\);
+			$/xm,
+		like => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE FOREIGN DATA WRAPPER dummy' => {
+		create_order => 35,
+		create_sql => 'CREATE FOREIGN DATA WRAPPER dummy;',
+		regexp => qr/CREATE FOREIGN DATA WRAPPER dummy;/m,
+		like => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'CREATE SERVER s1 FOREIGN DATA WRAPPER dummy' => {
+		create_order => 36,
+		create_sql => 'CREATE SERVER s1 FOREIGN DATA WRAPPER dummy;',
+		regexp => qr/CREATE SERVER s1 FOREIGN DATA WRAPPER dummy;/m,
+		like => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+#######################################
+# Currently broken.
+#######################################
+#
+#	'CREATE TRANSFORM FOR int' => {
+#		create_order => 34,
+#		create_sql => 'CREATE TRANSFORM FOR int LANGUAGE SQL (FROM SQL WITH FUNCTION varchar_transform(internal), TO SQL WITH FUNCTION int4recv(internal));',
+#		regexp => qr/CREATE TRANSFORM FOR int LANGUAGE SQL \(FROM SQL WITH FUNCTION varchar_transform\(internal\), TO SQL WITH FUNCTION int4recv\(internal\)\);/m,
+#		like => {
+#			binary_upgrade => 1,
+#			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_privs => 1,
+#			no_owner => 1,
+#			schema_only => 1,
+#			section_post_data => 1,
+#		},
+#		unlike => {
+#			section_pre_data => 1,
+#			only_dump_test_schema => 1,
+#			only_dump_test_table => 1,
+#			pg_dumpall_globals => 1,
+#			test_schema_plus_blobs => 1,
+#		},
+#	},
+	'CREATE LANGUAGE pltestlang' => {
+		create_order => 18,
+		create_sql => 'CREATE LANGUAGE pltestlang
+					   HANDLER dump_test.pltestlang_call_handler;',
+		regexp => qr/^
+			\QCREATE PROCEDURAL LANGUAGE pltestlang \E
+			\QHANDLER pltestlang_call_handler;\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+			only_dump_test_schema => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'CREATE MATERIALIZED VIEW matview' => {
+		create_order => 20,
+		create_sql => 'CREATE MATERIALIZED VIEW dump_test.matview (col1) AS
+					   SELECT * FROM dump_test.test_table;',
+		regexp => qr/^
+			\QCREATE MATERIALIZED VIEW matview AS\E
+			\n\s+\QSELECT test_table.col1\E
+			\n\s+\QFROM test_table\E
+			\n\s+\QWITH NO DATA;\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE MATERIALIZED VIEW matview_second' => {
+		create_order => 21,
+		create_sql => 'CREATE MATERIALIZED VIEW
+						   dump_test.matview_second (col1) AS
+						   SELECT * FROM dump_test.matview;',
+		regexp => qr/^
+			\QCREATE MATERIALIZED VIEW matview_second AS\E
+			\n\s+\QSELECT matview.col1\E
+			\n\s+\QFROM matview\E
+			\n\s+\QWITH NO DATA;\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE POLICY p1 ON test_table' => {
+		create_order => 22,
+		create_sql => 'CREATE POLICY p1 ON dump_test.test_table
+						   USING (true)
+						   WITH CHECK (true);',
+		regexp => qr/^
+			\QCREATE POLICY p1 ON test_table FOR ALL TO PUBLIC \E
+			\QUSING (true) WITH CHECK (true);\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			section_pre_data => 1,
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			pg_dumpall_globals => 1,
+		},
+	},
+	'CREATE POLICY p2 ON test_table FOR SELECT' => {
+		create_order => 24,
+		create_sql => 'CREATE POLICY p2 ON dump_test.test_table
+						   FOR SELECT TO dump_test USING (true);',
+		regexp => qr/^
+			\QCREATE POLICY p2 ON test_table FOR SELECT TO dump_test \E
+			\QUSING (true);\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			section_pre_data => 1,
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			pg_dumpall_globals => 1,
+		},
+	},
+	'CREATE POLICY p3 ON test_table FOR INSERT' => {
+		create_order => 25,
+		create_sql => 'CREATE POLICY p3 ON dump_test.test_table
+						   FOR INSERT TO dump_test WITH CHECK (true);',
+		regexp => qr/^
+			\QCREATE POLICY p3 ON test_table FOR INSERT \E
+			\QTO dump_test WITH CHECK (true);\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			section_pre_data => 1,
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			pg_dumpall_globals => 1,
+		},
+	},
+	'CREATE POLICY p4 ON test_table FOR UPDATE' => {
+		create_order => 26,
+		create_sql => 'CREATE POLICY p4 ON dump_test.test_table FOR UPDATE
+						   TO dump_test USING (true) WITH CHECK (true);',
+		regexp => qr/^
+			\QCREATE POLICY p4 ON test_table FOR UPDATE TO dump_test \E
+			\QUSING (true) WITH CHECK (true);\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			section_pre_data => 1,
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			pg_dumpall_globals => 1,
+		},
+	},
+	'CREATE POLICY p5 ON test_table FOR DELETE' => {
+		create_order => 27,
+		create_sql => 'CREATE POLICY p5 ON dump_test.test_table
+						   FOR DELETE TO dump_test USING (true);',
+		regexp => qr/^
+			\QCREATE POLICY p5 ON test_table FOR DELETE \E
+			\QTO dump_test USING (true);\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			section_pre_data => 1,
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			pg_dumpall_globals => 1,
+		},
+	},
+	'CREATE SCHEMA dump_test' => {
+		create_order => 2,
+		create_sql => 'CREATE SCHEMA dump_test;',
+		regexp => qr/^CREATE SCHEMA dump_test;$/m,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE SCHEMA dump_test_second_schema' => {
+		create_order => 9,
+		create_sql => 'CREATE SCHEMA dump_test_second_schema;',
+		regexp => qr/^CREATE SCHEMA dump_test_second_schema;$/m,
+		like => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'CREATE TABLE test_table' => {
+		create_order => 3,
+		create_sql => 'CREATE TABLE dump_test.test_table (
+						   col1 serial primary key,
+						   CHECK (col1 <= 1000)
+					   );',
+		regexp => qr/^
+			\QCREATE TABLE test_table (\E
+			\n\s+\Qcol1 integer NOT NULL,\E
+			\n\s+\QCONSTRAINT test_table_col1_check CHECK \E
+			\Q((col1 <= 1000))\E
+			\n\);$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE TABLE fk_reference_test_table' => {
+		create_order => 21,
+		create_sql => 'CREATE TABLE dump_test.fk_reference_test_table (
+						   col1 int primary key references dump_test.test_table
+					   );',
+		regexp => qr/^
+			\QCREATE TABLE fk_reference_test_table (\E
+			\n\s+\Qcol1 integer NOT NULL\E
+			\n\);
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE TABLE test_second_table' => {
+		create_order => 6,
+		create_sql => 'CREATE TABLE dump_test.test_second_table (
+						   col1 int,
+						   col2 text
+					   );',
+		regexp => qr/^
+			\QCREATE TABLE test_second_table (\E
+			\n\s+\Qcol1 integer,\E
+			\n\s+\Qcol2 text\E
+			\n\);
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE TABLE test_third_table' => {
+		create_order => 11,
+		create_sql => 'CREATE TABLE dump_test_second_schema.test_third_table (
+						   col1 serial
+					   );',
+		regexp => qr/^
+			\QCREATE TABLE test_third_table (\E
+			\n\s+\Qcol1 integer NOT NULL\E
+			\n\);
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'CREATE SEQUENCE test_table_col1_seq' => {
+		regexp => qr/^
+			\QCREATE SEQUENCE test_table_col1_seq\E
+			\n\s+\QSTART WITH 1\E
+			\n\s+\QINCREMENT BY 1\E
+			\n\s+\QNO MINVALUE\E
+			\n\s+\QNO MAXVALUE\E
+			\n\s+\QCACHE 1;\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE SEQUENCE test_third_table_col1_seq' => {
+		regexp => qr/^
+			\QCREATE SEQUENCE test_third_table_col1_seq\E
+			\n\s+\QSTART WITH 1\E
+			\n\s+\QINCREMENT BY 1\E
+			\n\s+\QNO MINVALUE\E
+			\n\s+\QNO MAXVALUE\E
+			\n\s+\QCACHE 1;\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'CREATE UNIQUE INDEX test_third_table_idx ON test_third_table' => {
+		create_order => 13,
+		create_sql => 'CREATE UNIQUE INDEX test_third_table_idx
+					   ON dump_test_second_schema.test_third_table (col1);',
+		regexp => qr/^
+			\QCREATE UNIQUE INDEX test_third_table_idx \E
+			\QON test_third_table USING btree (col1);\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			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_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_post_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'CREATE ... commands' => { # catch-all for CREATE
+		regexp => qr/^CREATE /m,
+		like => { }, # use more-specific options above
+		unlike => {
+			column_inserts => 1,
+			data_only => 1,
+			section_data => 1,
+		},
+	},
+	'DROP EXTENSION plpgsql' => {
+		regexp => qr/^DROP EXTENSION plpgsql;$/m,
+		like => {
+			clean => 1,
+		},
+		unlike => {
+			clean_if_exists => 1,
+		},
+	},
+	'DROP FUNCTION dump_test.pltestlang_call_handler()' => {
+		regexp => qr/^DROP FUNCTION dump_test\.pltestlang_call_handler\(\);$/m,
+		like => {
+			clean => 1,
+		},
+		unlike => {
+			clean_if_exists => 1,
+		},
+	},
+	'DROP LANGUAGE pltestlang' => {
+		regexp => qr/^DROP PROCEDURAL LANGUAGE pltestlang;$/m,
+		like => {
+			clean => 1,
+		},
+		unlike => {
+			clean_if_exists => 1,
+		},
+	},
+	'DROP SCHEMA dump_test' => {
+		regexp => qr/^DROP SCHEMA dump_test;$/m,
+		like => {
+			clean => 1,
+		},
+		unlike => {
+			clean_if_exists => 1,
+		},
+	},
+	'DROP SCHEMA dump_test_second_schema' => {
+		regexp => qr/^DROP SCHEMA dump_test_second_schema;$/m,
+		like => {
+			clean => 1,
+		},
+		unlike => {
+			clean_if_exists => 1,
+		},
+	},
+	'DROP TABLE test_table' => {
+		regexp => qr/^DROP TABLE dump_test\.test_table;$/m,
+		like => {
+			clean => 1,
+		},
+		unlike => {
+			clean_if_exists => 1,
+		},
+	},
+	'DROP TABLE fk_reference_test_table' => {
+		regexp => qr/^DROP TABLE dump_test\.fk_reference_test_table;$/m,
+		like => {
+			clean => 1,
+		},
+		unlike => {
+			clean_if_exists => 1,
+		},
+	},
+	'DROP TABLE test_second_table' => {
+		regexp => qr/^DROP TABLE dump_test\.test_second_table;$/m,
+		like => {
+			clean => 1,
+		},
+		unlike => {
+			clean_if_exists => 1,
+		},
+	},
+	'DROP TABLE test_third_table' => {
+		regexp => qr/^DROP TABLE dump_test_second_schema\.test_third_table;$/m,
+		like => {
+			clean => 1,
+		},
+		unlike => {
+			clean_if_exists => 1,
+		},
+	},
+	'DROP EXTENSION IF EXISTS plpgsql' => {
+		regexp => qr/^DROP EXTENSION IF EXISTS plpgsql;$/m,
+		like => {
+			clean_if_exists => 1,
+		},
+		unlike => {
+			clean => 1,
+		},
+	},
+	'DROP FUNCTION IF EXISTS dump_test.pltestlang_call_handler()' => {
+		regexp => qr/^
+			\QDROP FUNCTION IF EXISTS dump_test.pltestlang_call_handler();\E
+			$/xm,
+		like => {
+			clean_if_exists => 1,
+		},
+		unlike => {
+			clean => 1,
+		},
+	},
+	'DROP LANGUAGE IF EXISTS pltestlang' => {
+		regexp => qr/^DROP PROCEDURAL LANGUAGE IF EXISTS pltestlang;$/m,
+		like => {
+			clean_if_exists => 1,
+		},
+		unlike => {
+			clean => 1,
+		},
+	},
+	'DROP SCHEMA IF EXISTS dump_test' => {
+		regexp => qr/^DROP SCHEMA IF EXISTS dump_test;$/m,
+		like => {
+			clean_if_exists => 1,
+		},
+		unlike => {
+			clean => 1,
+		},
+	},
+	'DROP SCHEMA IF EXISTS dump_test_second_schema' => {
+		regexp => qr/^DROP SCHEMA IF EXISTS dump_test_second_schema;$/m,
+		like => {
+			clean_if_exists => 1,
+		},
+		unlike => {
+			clean => 1,
+		},
+	},
+	'DROP TABLE IF EXISTS test_table' => {
+		regexp => qr/^DROP TABLE IF EXISTS dump_test\.test_table;$/m,
+		like => {
+			clean_if_exists => 1,
+		},
+		unlike => {
+			clean => 1,
+		},
+	},
+	'DROP TABLE IF EXISTS test_second_table' => {
+		regexp => qr/^DROP TABLE IF EXISTS dump_test\.test_second_table;$/m,
+		like => {
+			clean_if_exists => 1,
+		},
+		unlike => {
+			clean => 1,
+		},
+	},
+	'DROP TABLE IF EXISTS test_third_table' => {
+		regexp => qr/^
+			\QDROP TABLE IF EXISTS dump_test_second_schema.test_third_table;\E
+			$/xm,
+		like => {
+			clean_if_exists => 1,
+		},
+		unlike => {
+			clean => 1,
+		},
+	},
+	'DROP ... commands' => { # catch-all for DROP
+		regexp => qr/^DROP /m,
+		like => { }, # use more-specific options above
+		unlike => {
+			binary_upgrade => 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_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			schema_only => 1,
+		},
+	},
+	'GRANT USAGE ON SCHEMA dump_test_second_schema' => {
+		create_order => 10,
+		create_sql => 'GRANT USAGE ON SCHEMA dump_test_second_schema
+						   TO dump_test;',
+		regexp => qr/^
+			\QGRANT USAGE ON SCHEMA dump_test_second_schema TO dump_test;\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			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_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'GRANT SELECT ON TABLE test_table' => {
+		create_order => 5,
+		create_sql => 'GRANT SELECT ON TABLE dump_test.test_table
+						   TO dump_test;',
+		regexp => qr/^GRANT SELECT ON TABLE test_table TO dump_test;$/m,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table_data => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			exclude_test_table => 1,
+			pg_dumpall_globals => 1,
+		},
+	},
+	'GRANT SELECT ON TABLE test_third_table' => {
+		create_order => 19,
+		create_sql => 'GRANT SELECT ON
+						   TABLE dump_test_second_schema.test_third_table
+						   TO dump_test;',
+		regexp => qr/^GRANT SELECT ON TABLE test_third_table TO dump_test;$/m,
+		like => {
+			binary_upgrade => 1,
+			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_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'GRANT ALL ON SEQUENCE test_third_table_col1_seq' => {
+		create_order => 28,
+		create_sql => 'GRANT ALL ON SEQUENCE
+						   dump_test_second_schema.test_third_table_col1_seq
+						   TO dump_test;',
+		regexp => qr/^
+			\QGRANT ALL ON SEQUENCE test_third_table_col1_seq TO dump_test;\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			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_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'GRANT INSERT(col1) ON TABLE test_second_table' => {
+		create_order => 8,
+		create_sql => 'GRANT INSERT (col1) ON TABLE dump_test.test_second_table
+						   TO dump_test;',
+		regexp => qr/^
+			\QGRANT INSERT(col1) ON TABLE test_second_table TO dump_test;\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			test_schema_plus_blobs => 1,
+		},
+		unlike => {
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+		},
+	},
+	'GRANT EXECUTE ON FUNCTION pg_sleep() TO dump_test' => {
+		create_order => 16,
+		create_sql => 'GRANT EXECUTE ON FUNCTION pg_sleep(float8)
+						   TO dump_test;',
+		regexp => qr/^
+			\QGRANT ALL ON FUNCTION pg_sleep(double precision) TO dump_test;\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			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_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'GRANT SELECT (proname ...) ON TABLE pg_proc TO public' => {
+		create_order => 46,
+		create_sql => 'GRANT SELECT (
+						   tableoid,
+						   oid,
+						   proname,
+						   pronamespace,
+						   proowner,
+						   prolang,
+						   procost,
+						   prorows,
+						   provariadic,
+						   protransform,
+						   proisagg,
+						   proiswindow,
+						   prosecdef,
+						   proleakproof,
+						   proisstrict,
+						   proretset,
+						   provolatile,
+						   proparallel,
+						   pronargs,
+						   pronargdefaults,
+						   prorettype,
+						   proargtypes,
+						   proallargtypes,
+						   proargmodes,
+						   proargnames,
+						   proargdefaults,
+						   protrftypes,
+						   prosrc,
+						   probin,
+						   proconfig,
+						   proacl
+						) ON TABLE pg_proc TO public;',
+		regexp => qr/
+		\QGRANT SELECT(tableoid) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(oid) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proname) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(pronamespace) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proowner) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(prolang) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(procost) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(prorows) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(provariadic) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(protransform) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proisagg) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proiswindow) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(prosecdef) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proleakproof) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proisstrict) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proretset) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(provolatile) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proparallel) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(pronargs) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(pronargdefaults) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(prorettype) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proargtypes) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proallargtypes) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proargmodes) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proargnames) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proargdefaults) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(protrftypes) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(prosrc) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(probin) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proconfig) ON TABLE pg_proc TO PUBLIC;\E\n.*
+		\QGRANT SELECT(proacl) ON TABLE pg_proc TO PUBLIC;\E$/xms,
+		like => {
+			binary_upgrade => 1,
+			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_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'GRANT commands' => { # catch-all for GRANT commands
+		regexp => qr/^GRANT /m,
+		like => { }, # use more-specific options above
+		unlike => {
+			column_inserts => 1,
+			data_only => 1,
+			no_privs => 1,
+			section_data => 1,
+		},
+	},
+	'REFRESH MATERIALIZED VIEW matview' => {
+		regexp => qr/^REFRESH MATERIALIZED VIEW matview;$/m,
+		like => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			test_schema_plus_blobs => 1,
+			section_post_data => 1,
+		},
+		unlike => {
+			binary_upgrade => 1,
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+	},
+	'REFRESH MATERIALIZED VIEW matview_second' => {
+		regexp => qr/^
+			\QREFRESH MATERIALIZED VIEW matview;\E
+			\n.*
+			\QREFRESH MATERIALIZED VIEW matview_second;\E
+			$/xms,
+		like => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			exclude_test_table => 1,
+			exclude_test_table_data => 1,
+			no_privs => 1,
+			no_owner => 1,
+			only_dump_test_schema => 1,
+			test_schema_plus_blobs => 1,
+			section_post_data => 1,
+		},
+		unlike => {
+			binary_upgrade => 1,
+			exclude_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			pg_dumpall_globals => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+	},
+	'REVOKE EXECUTE ON FUNCTION pg_sleep() FROM public' => {
+		create_order => 15,
+		create_sql => 'REVOKE EXECUTE ON FUNCTION pg_sleep(float8)
+						   FROM public;',
+		regexp => qr/^
+			\QREVOKE ALL ON FUNCTION pg_sleep(double precision) FROM PUBLIC;\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			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_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'REVOKE SELECT ON TABLE pg_proc FROM public' => {
+		create_order => 45,
+		create_sql => 'REVOKE SELECT ON TABLE pg_proc FROM public;',
+		regexp => qr/^REVOKE SELECT ON TABLE pg_proc FROM PUBLIC;$/m,
+		like => {
+			binary_upgrade => 1,
+			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_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'REVOKE CREATE ON SCHEMA public FROM public' => {
+		create_order => 16,
+		create_sql => 'REVOKE CREATE ON SCHEMA public FROM public;',
+		regexp => qr/^
+			\QREVOKE ALL ON SCHEMA public FROM PUBLIC;\E
+			\n\QGRANT USAGE ON SCHEMA public TO PUBLIC;\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			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_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'REVOKE USAGE ON LANGUAGE plpgsql FROM public' => {
+		create_order => 16,
+		create_sql => 'REVOKE USAGE ON LANGUAGE plpgsql FROM public;',
+		regexp => qr/^REVOKE ALL ON LANGUAGE plpgsql FROM PUBLIC;$/m,
+		like => {
+			binary_upgrade => 1,
+			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_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			only_dump_test_schema => 1,
+			only_dump_test_table => 1,
+			test_schema_plus_blobs => 1,
+		},
+	},
+	'REVOKE commands' => { # catch-all for REVOKE commands
+		regexp => qr/^REVOKE /m,
+		like => { }, # use more-specific options above
+		unlike => {
+			column_inserts => 1,
+			data_only => 1,
+			no_privs => 1,
+			pg_dumpall_globals => 1,
+		},
+	},
+);
+
+#########################################
+# Create a PG instance to test actually dumping from
+
+my $node = get_new_node('main');
+$node->init;
+$node->start;
+
+my $port = $node->port;
+
+# Start with 2 because of command_exit_is() tests below
+my $num_tests = 2;
+
+foreach my $run (sort keys %pgdump_runs) {
+	my $test_key = $run;
+
+	# Each run of pg_dump is a test itself
+	$num_tests++;
+
+	# If there is a restore cmd, that's another test
+	if ($pgdump_runs{$run}->{restore_cmd}) {
+		$num_tests++;
+	}
+
+	if ($pgdump_runs{$run}->{test_key}) {
+		$test_key = $pgdump_runs{$run}->{test_key};
+	}
+
+	# Then count all the tests run against each run
+	foreach my $test (sort keys %tests) {
+		if ($tests{$test}->{like}->{$test_key}) {
+			$num_tests++;
+		}
+
+		if ($tests{$test}->{unlike}->{$test_key}) {
+			$num_tests++;
+		}
+	}
+}
+plan tests => $num_tests;
+
+#########################################
+# Set up schemas, tables, etc, to be dumped.
+
+# Build up the create statements
+my $create_sql = '';
+
+foreach my $test (
+	sort {
+		if ($tests{$a}->{create_order} and $tests{$b}->{create_order}) {
+			$tests{$a}->{create_order} <=> $tests{$b}->{create_order};
+		} elsif ($tests{$a}->{create_order}) {
+			-1;
+		} elsif ($tests{$b}->{create_order}) {
+			1;
+		} else {
+			0;
+		}
+	} keys %tests) {
+	if ($tests{$test}->{create_sql}) {
+		$create_sql .= $tests{$test}->{create_sql};
+	}
+}
+
+# Send the combined set of commands to psql
+$node->safe_psql('postgres', $create_sql);
+
+#########################################
+# Test connecting to a non-existent database
+
+command_exit_is([ 'pg_dump', '-p', "$port", 'qqq' ],
+	1, 'pg_dump: [archiver (db)] connection to database "qqq" failed: FATAL:  database "qqq" does not exist');
+
+command_exit_is([ 'pg_dump', '-p', "$port", '--role=dump_test' ],
+	1, 'pg_dump: [archiver (db)] query failed: ERROR:  permission denied for');
+
+#########################################
+# Run all runs
+
+foreach my $run (sort keys %pgdump_runs) {
+
+	my $test_key = $run;
+
+	$node->command_ok(\@{ $pgdump_runs{$run}->{dump_cmd} }, "$run: pg_dump runs");
+
+	if ($pgdump_runs{$run}->{restore_cmd}) {
+		$node->command_ok(\@{ $pgdump_runs{$run}->{restore_cmd} }, "$run: pg_restore runs");
+	}
+
+	if ($pgdump_runs{$run}->{test_key}) {
+		$test_key = $pgdump_runs{$run}->{test_key};
+	}
+
+	my $output_file = slurp_file("$tempdir/${run}.sql");
+
+	#########################################
+	# Run all tests where this run is included
+	# as either a 'like' or 'unlike' test.
+
+	foreach my $test (sort keys %tests) {
+		if ($tests{$test}->{like}->{$test_key}) {
+			like($output_file, $tests{$test}->{regexp}, "$run: dumps $test");
+		}
+
+		if ($tests{$test}->{unlike}->{$test_key}) {
+			unlike($output_file, $tests{$test}->{regexp}, "$run: does not dump $test");
+		}
+	}
+}
+
+#########################################
+# Stop the database instance, which will be removed at the end of the tests.
+
+$node->stop('fast');
diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index 9b935521f47cd512cd37135e6fbf63513a27afb4..892662755a8c5d23b30067e56b60089676cb01c6 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -12,6 +12,7 @@ SUBDIRS = \
 		  test_ddl_deparse \
 		  test_extensions \
 		  test_parser \
+		  test_pg_dump \
 		  test_rls_hooks \
 		  test_shm_mq \
 		  worker_spi
diff --git a/src/test/modules/test_pg_dump/.gitignore b/src/test/modules/test_pg_dump/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..5dcb3ff9723501c3fe639bee1c1435e47a580a6f
--- /dev/null
+++ b/src/test/modules/test_pg_dump/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/src/test/modules/test_pg_dump/Makefile b/src/test/modules/test_pg_dump/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..0eb3b5f988e56e4418fb6d6d4b5872d52f924709
--- /dev/null
+++ b/src/test/modules/test_pg_dump/Makefile
@@ -0,0 +1,25 @@
+# src/test/modules/test_rls_hooks/Makefile
+
+MODULE_big = test_pg_dump
+PGFILEDESC = "test_pg_dump - Test pg_dump with an extension"
+
+EXTENSION = test_pg_dump
+DATA = test_pg_dump--1.0.sql
+
+REGRESS = test_pg_dump
+
+check: prove-check
+
+prove-check:
+	$(prove_check)
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_pg_dump
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_pg_dump/README b/src/test/modules/test_pg_dump/README
new file mode 100644
index 0000000000000000000000000000000000000000..e6c78b822c3e38e94c9ec79a4e1009a3b7e691ca
--- /dev/null
+++ b/src/test/modules/test_pg_dump/README
@@ -0,0 +1,2 @@
+test_pg_dump is an extension explicitly to test pg_dump when
+extensions are present in the system.
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
new file mode 100644
index 0000000000000000000000000000000000000000..360caa2cb30d57ac3fa151f45897ecfe6d69ab85
--- /dev/null
+++ b/src/test/modules/test_pg_dump/expected/test_pg_dump.out
@@ -0,0 +1,6 @@
+SELECT 1;
+ ?column? 
+----------
+        1
+(1 row)
+
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
new file mode 100644
index 0000000000000000000000000000000000000000..e0ac49d1ecfb8f96f2418b1a87e1d20e587d9d0f
--- /dev/null
+++ b/src/test/modules/test_pg_dump/sql/test_pg_dump.sql
@@ -0,0 +1 @@
+SELECT 1;
diff --git a/src/test/modules/test_pg_dump/t/001_base.pl b/src/test/modules/test_pg_dump/t/001_base.pl
new file mode 100644
index 0000000000000000000000000000000000000000..9a65da1d6aeb0b4ecdab68be61fe4835bb22db1c
--- /dev/null
+++ b/src/test/modules/test_pg_dump/t/001_base.pl
@@ -0,0 +1,535 @@
+use strict;
+use warnings;
+
+use Config;
+use PostgresNode;
+use TestLib;
+use Test::More;
+
+my $tempdir       = TestLib::tempdir;
+my $tempdir_short = TestLib::tempdir_short;
+
+###############################################################
+# This structure is based off of the src/bin/pg_dump/t test
+# suite.
+###############################################################
+# Definition of the pg_dump runs to make.
+#
+# Each of these runs are named and those names are used below
+# to define how each test should (or shouldn't) treat a result
+# from a given run.
+#
+# test_key indicates that a given run should simply use the same
+# set of like/unlike tests as another run, and which run that is.
+#
+# dump_cmd is the pg_dump command to run, which is an array of
+# the full command and arguments to run.  Note that this is run
+# using $node->command_ok(), so the port does not need to be
+# specified and is pulled from $PGPORT, which is set by the
+# PostgresNode system.
+#
+# restore_cmd is the pg_restore command to run, if any.  Note
+# that this should generally be used when the pg_dump goes to
+# a non-text file and that the restore can then be used to
+# generate a text file to run through the tests from the
+# non-text file generated by pg_dump.
+#
+# TODO: Have pg_restore actually restore to an independent
+# database and then pg_dump *that* database (or something along
+# those lines) to validate that part of the process.
+
+my %pgdump_runs = (
+	binary_upgrade => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/binary_upgrade.sql",
+			'--schema-only',
+			'--binary-upgrade',
+			'-d', 'postgres', # alternative way to specify database
+		],
+	},
+	clean => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/clean.sql",
+			'-c',
+			'-d', 'postgres', # alternative way to specify database
+		],
+	},
+	clean_if_exists => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/clean_if_exists.sql",
+			'-c',
+			'--if-exists',
+			'-E', 'UTF8', # no-op, just tests that option is accepted
+			'postgres',
+		],
+	},
+	column_inserts => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/column_inserts.sql",
+			'-a',
+			'--column-inserts',
+			'postgres',
+		],
+	},
+	createdb => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/createdb.sql",
+			'-C',
+			'-R', # no-op, just for testing
+			'postgres',
+		],
+	},
+	data_only => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/data_only.sql",
+			'-a',
+			'-v', # no-op, just make sure it works
+			'postgres',
+		],
+	},
+	defaults => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/defaults.sql",
+			'postgres',
+		],
+	},
+	defaults_custom_format => {
+		test_key => 'defaults',
+		dump_cmd => [
+			'pg_dump',
+			'-Fc',
+			'-Z6',
+			'-f', "$tempdir/defaults_custom_format.dump",
+			'postgres',
+		],
+		restore_cmd => [
+			'pg_restore',
+			'-f', "$tempdir/defaults_custom_format.sql",
+			"$tempdir/defaults_custom_format.dump",
+		],
+	},
+	defaults_dir_format => {
+		test_key => 'defaults',
+		dump_cmd => [
+			'pg_dump',
+			'-Fd',
+			'-f', "$tempdir/defaults_dir_format",
+			'postgres',
+		],
+		restore_cmd => [
+			'pg_restore',
+			'-f', "$tempdir/defaults_dir_format.sql",
+			"$tempdir/defaults_dir_format",
+		],
+	},
+	defaults_parallel => {
+		test_key => 'defaults',
+		dump_cmd => [
+			'pg_dump',
+			'-Fd',
+			'-j2',
+			'-f', "$tempdir/defaults_parallel",
+			'postgres',
+		],
+		restore_cmd => [
+			'pg_restore',
+			'-f', "$tempdir/defaults_parallel.sql",
+			"$tempdir/defaults_parallel",
+		],
+	},
+	defaults_tar_format => {
+		test_key => 'defaults',
+		dump_cmd => [
+			'pg_dump',
+			'-Ft',
+			'-f', "$tempdir/defaults_tar_format.tar",
+			'postgres',
+		],
+		restore_cmd => [
+			'pg_restore',
+			'-f', "$tempdir/defaults_tar_format.sql",
+			"$tempdir/defaults_tar_format.tar",
+		],
+	},
+	pg_dumpall_globals => {
+		dump_cmd => [
+			'pg_dumpall',
+			'-f', "$tempdir/pg_dumpall_globals.sql",
+			'-g',
+		],
+	},
+	no_privs => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/no_privs.sql",
+			'-x',
+			'postgres',
+		],
+	},
+	no_owner => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/no_owner.sql",
+			'-O',
+			'postgres',
+		],
+	},
+	schema_only => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/schema_only.sql",
+			'-s',
+			'postgres',
+		],
+	},
+	section_pre_data => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/section_pre_data.sql",
+			'--section=pre-data',
+			'postgres',
+		],
+	},
+	section_data => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/section_data.sql",
+			'--section=data',
+			'postgres',
+		],
+	},
+	section_post_data => {
+		dump_cmd => [
+			'pg_dump',
+			'-f', "$tempdir/section_post_data.sql",
+			'--section=post-data',
+			'postgres',
+		],
+	},
+);
+
+###############################################################
+# Definition of the tests to run.
+#
+# Each test is defined using the log message that will be used.
+#
+# A regexp should be defined for each test which provides the
+# basis for the test.  That regexp will be run against the output
+# file of each of the runs which the test is to be run against
+# and the success of the result will depend on if the regexp
+# result matches the expected 'like' or 'unlike' case.
+#
+# For each test, there are two sets of runs defined, one for
+# the 'like' tests and one for the 'unlike' tests.  'like'
+# essentially means "the regexp for this test must match the
+# output file".  'unlike' is the opposite.
+#
+# There are a few 'catch-all' tests which can be used to have
+# a single, simple, test to over a range of other tests.  For
+# example, there is a '^CREATE ' test, which is used for the
+# 'data-only' test as there should never be any kind of CREATE
+# statement in a 'data-only' run.  Without the catch-all, we
+# would have to list the 'data-only' run in each and every
+# 'CREATE xxxx' test, which would be a lot of additional tests.
+#
+# Note that it makes no sense for the same run to ever be listed
+# in both 'like' and 'unlike' categories.
+#
+# There can then be a 'create_sql' and 'create_order' for a
+# given test.  The 'create_sql' commands are collected up in
+# 'create_order' and then run against the database prior to any
+# of the pg_dump runs happening.  This is what "seeds" the
+# system with objects to be dumped out.
+#
+# Building of this hash takes a bit of time as all of the regexps
+# included in it are compiled.  This greatly improves performance
+# as the regexps are used for each run the test applies to.
+
+my %tests = (
+	'CREATE EXTENSION test_pg_dump' => {
+		create_order => 2,
+		create_sql => 'CREATE EXTENSION test_pg_dump;',
+		regexp => qr/^
+			\QCREATE EXTENSION IF NOT EXISTS test_pg_dump WITH SCHEMA public;\E
+			$/xm,
+		like => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			no_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			binary_upgrade => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE ROLE dump_test' => {
+		create_order => 1,
+		create_sql => 'CREATE ROLE dump_test;',
+		regexp => qr/^CREATE ROLE dump_test;$/m,
+		like => {
+			pg_dumpall_globals => 1,
+		},
+		unlike => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			no_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			section_post_data => 1,
+		},
+	},
+	'CREATE TABLE regress_pg_dump_table' => {
+		regexp => qr/^
+			\QCREATE TABLE regress_pg_dump_table (\E
+			\n\s+\Qcol1 integer,\E
+			\n\s+\Qcol2 integer\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,
+		},
+	},
+	'COMMENT ON EXTENSION test_pg_dump' => {
+		regexp => qr/^
+			\QCOMMENT ON EXTENSION test_pg_dump \E
+			\QIS 'Test pg_dump with an extension';\E
+			$/xm,
+		like => {
+			binary_upgrade => 1,
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			no_privs => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+		},
+		unlike => {
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'GRANT SELECT ON TABLE regress_pg_dump_table' => {
+		regexp => qr/^
+			\QSELECT binary_upgrade_set_record_init_privs(true);\E\n
+			\QGRANT SELECT ON TABLE regress_pg_dump_table TO dump_test;\E\n
+			\QSELECT binary_upgrade_set_record_init_privs(false);\E
+			$/xms,
+		like => {
+			binary_upgrade => 1,
+		},
+		unlike => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			no_privs => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'GRANT SELECT(col1) ON regress_pg_dump_table' => {
+		regexp => qr/^
+			\QSELECT binary_upgrade_set_record_init_privs(true);\E\n
+			\QGRANT SELECT(col1) ON TABLE regress_pg_dump_table TO PUBLIC;\E\n
+			\QSELECT binary_upgrade_set_record_init_privs(false);\E
+			$/xms,
+		like => {
+			binary_upgrade => 1,
+		},
+		unlike => {
+			clean => 1,
+			clean_if_exists => 1,
+			createdb => 1,
+			defaults => 1,
+			no_owner => 1,
+			schema_only => 1,
+			section_pre_data => 1,
+			no_privs => 1,
+			pg_dumpall_globals => 1,
+			section_post_data => 1,
+		},
+	},
+	'GRANT SELECT(col2) ON regress_pg_dump_table TO dump_test' => {
+		create_order => 4,
+		create_sql => 'GRANT SELECT(col2) ON regress_pg_dump_table
+						   TO dump_test;',
+		regexp => qr/^
+			\QGRANT SELECT(col2) ON TABLE regress_pg_dump_table TO dump_test;\E
+			$/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,
+		},
+	},
+	'REVOKE SELECT(col1) ON regress_pg_dump_table' => {
+		create_order => 3,
+		create_sql => 'REVOKE SELECT(col1) ON regress_pg_dump_table
+						   FROM PUBLIC;',
+		regexp => qr/^
+			\QREVOKE SELECT(col1) ON TABLE regress_pg_dump_table FROM PUBLIC;\E
+			$/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,
+		},
+	},
+);
+
+#########################################
+# Create a PG instance to test actually dumping from
+
+my $node = get_new_node('main');
+$node->init;
+$node->start;
+
+my $port = $node->port;
+
+my $num_tests = 0;
+
+foreach my $run (sort keys %pgdump_runs) {
+	my $test_key = $run;
+
+	# Each run of pg_dump is a test itself
+	$num_tests++;
+
+	# If there is a restore cmd, that's another test
+	if ($pgdump_runs{$run}->{restore_cmd}) {
+		$num_tests++;
+	}
+
+	if ($pgdump_runs{$run}->{test_key}) {
+		$test_key = $pgdump_runs{$run}->{test_key};
+	}
+
+	# Then count all the tests run against each run
+	foreach my $test (sort keys %tests) {
+		if ($tests{$test}->{like}->{$test_key}) {
+			$num_tests++;
+		}
+
+		if ($tests{$test}->{unlike}->{$test_key}) {
+			$num_tests++;
+		}
+	}
+}
+plan tests => $num_tests;
+
+#########################################
+# Set up schemas, tables, etc, to be dumped.
+
+# Build up the create statements
+my $create_sql = '';
+
+foreach my $test (
+	sort {
+		if ($tests{$a}->{create_order} and $tests{$b}->{create_order}) {
+			$tests{$a}->{create_order} <=> $tests{$b}->{create_order};
+		} elsif ($tests{$a}->{create_order}) {
+			-1;
+		} elsif ($tests{$b}->{create_order}) {
+			1;
+		} else {
+			0;
+		}
+	} keys %tests) {
+	if ($tests{$test}->{create_sql}) {
+		$create_sql .= $tests{$test}->{create_sql};
+	}
+}
+
+# Send the combined set of commands to psql
+$node->safe_psql('postgres', $create_sql);
+
+#########################################
+# Run all runs
+
+foreach my $run (sort keys %pgdump_runs) {
+
+	my $test_key = $run;
+
+	$node->command_ok(\@{ $pgdump_runs{$run}->{dump_cmd} }, "$run: pg_dump runs");
+
+	if ($pgdump_runs{$run}->{restore_cmd}) {
+		$node->command_ok(\@{ $pgdump_runs{$run}->{restore_cmd} }, "$run: pg_restore runs");
+	}
+
+	if ($pgdump_runs{$run}->{test_key}) {
+		$test_key = $pgdump_runs{$run}->{test_key};
+	}
+
+	my $output_file = slurp_file("$tempdir/${run}.sql");
+
+	#########################################
+	# Run all tests where this run is included
+	# as either a 'like' or 'unlike' test.
+
+	foreach my $test (sort keys %tests) {
+		if ($tests{$test}->{like}->{$test_key}) {
+			like($output_file, $tests{$test}->{regexp}, "$run: dumps $test");
+		}
+
+		if ($tests{$test}->{unlike}->{$test_key}) {
+			unlike($output_file, $tests{$test}->{regexp}, "$run: does not dump $test");
+		}
+	}
+}
+
+#########################################
+# Stop the database instance, which will be removed at the end of the tests.
+
+$node->stop('fast');
diff --git a/src/test/modules/test_pg_dump/test_pg_dump--1.0.sql b/src/test/modules/test_pg_dump/test_pg_dump--1.0.sql
new file mode 100644
index 0000000000000000000000000000000000000000..d1ec58d023f06065b15752c6a24e78518ea4b96a
--- /dev/null
+++ b/src/test/modules/test_pg_dump/test_pg_dump--1.0.sql
@@ -0,0 +1,15 @@
+/* src/test/modules/test_pg_dump/test_pg_dump--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION test_pg_dump" to load this file. \quit
+
+CREATE TABLE regress_pg_dump_table (
+	col1 int,
+	col2 int
+);
+
+GRANT SELECT ON regress_pg_dump_table TO dump_test;
+GRANT SELECT(col1) ON regress_pg_dump_table TO public;
+
+GRANT SELECT(col2) ON regress_pg_dump_table TO dump_test;
+REVOKE SELECT(col2) ON regress_pg_dump_table FROM dump_test;
diff --git a/src/test/modules/test_pg_dump/test_pg_dump.control b/src/test/modules/test_pg_dump/test_pg_dump.control
new file mode 100644
index 0000000000000000000000000000000000000000..fe3450db76c567464aab6017ffd291ae50d2daf7
--- /dev/null
+++ b/src/test/modules/test_pg_dump/test_pg_dump.control
@@ -0,0 +1,3 @@
+comment = 'Test pg_dump with an extension'
+default_version = '1.0'
+relocatable = true