diff --git a/src/bin/pg_dump/Makefile b/src/bin/pg_dump/Makefile index 95967893d8..260804b5a7 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 6e2610fa3f..1267afbce9 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 0000000000..1411ef7a27 --- /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 0000000000..4270042250 --- /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 9b935521f4..892662755a 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 0000000000..5dcb3ff972 --- /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 0000000000..0eb3b5f988 --- /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 0000000000..e6c78b822c --- /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 0000000000..360caa2cb3 --- /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 0000000000..e0ac49d1ec --- /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 0000000000..9a65da1d6a --- /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 0000000000..d1ec58d023 --- /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 0000000000..fe3450db76 --- /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