Pre-beta mechanical code beautification.
[pgsql.git] / src / test / modules / test_pg_dump / t / 001_base.pl
blobe2579e29cd8664c344b03f78d2209cce948b044a
2 # Copyright (c) 2021-2024, PostgreSQL Global Development Group
4 use strict;
5 use warnings FATAL => 'all';
7 use PostgreSQL::Test::Cluster;
8 use PostgreSQL::Test::Utils;
9 use Test::More;
11 my $tempdir = PostgreSQL::Test::Utils::tempdir;
13 ###############################################################
14 # This structure is based off of the src/bin/pg_dump/t test
15 # suite.
16 ###############################################################
17 # Definition of the pg_dump runs to make.
19 # Each of these runs are named and those names are used below
20 # to define how each test should (or shouldn't) treat a result
21 # from a given run.
23 # compile_option indicates if the commands run depend on a compilation
24 # option, if any. This can be used to control if tests should be
25 # skipped when a build dependency is not satisfied.
27 # test_key indicates that a given run should simply use the same
28 # set of like/unlike tests as another run, and which run that is.
30 # dump_cmd is the pg_dump command to run, which is an array of
31 # the full command and arguments to run. Note that this is run
32 # using $node->command_ok(), so the port does not need to be
33 # specified and is pulled from $PGPORT, which is set by the
34 # PostgreSQL::Test::Cluster system.
36 # restore_cmd is the pg_restore command to run, if any. Note
37 # that this should generally be used when the pg_dump goes to
38 # a non-text file and that the restore can then be used to
39 # generate a text file to run through the tests from the
40 # non-text file generated by pg_dump.
42 # TODO: Have pg_restore actually restore to an independent
43 # database and then pg_dump *that* database (or something along
44 # those lines) to validate that part of the process.
46 my %pgdump_runs = (
47 binary_upgrade => {
48 dump_cmd => [
49 'pg_dump', '--no-sync',
50 "--file=$tempdir/binary_upgrade.sql", '--schema-only',
51 '--binary-upgrade', '--dbname=postgres',
54 clean => {
55 dump_cmd => [
56 'pg_dump', "--file=$tempdir/clean.sql",
57 '-c', '--no-sync',
58 '--dbname=postgres',
61 clean_if_exists => {
62 dump_cmd => [
63 'pg_dump',
64 '--no-sync',
65 "--file=$tempdir/clean_if_exists.sql",
66 '-c',
67 '--if-exists',
68 '--encoding=UTF8', # no-op, just tests that option is accepted
69 'postgres',
72 createdb => {
73 dump_cmd => [
74 'pg_dump',
75 '--no-sync',
76 "--file=$tempdir/createdb.sql",
77 '-C',
78 '-R', # no-op, just for testing
79 'postgres',
82 data_only => {
83 dump_cmd => [
84 'pg_dump',
85 '--no-sync',
86 "--file=$tempdir/data_only.sql",
87 '-a',
88 '-v', # no-op, just make sure it works
89 'postgres',
92 defaults => {
93 dump_cmd => [ 'pg_dump', '-f', "$tempdir/defaults.sql", 'postgres', ],
95 defaults_custom_format => {
96 test_key => 'defaults',
97 compile_option => 'gzip',
98 dump_cmd => [
99 'pg_dump', '--no-sync', '-Fc', '-Z6',
100 "--file=$tempdir/defaults_custom_format.dump", 'postgres',
102 restore_cmd => [
103 'pg_restore',
104 "--file=$tempdir/defaults_custom_format.sql",
105 "$tempdir/defaults_custom_format.dump",
108 defaults_dir_format => {
109 test_key => 'defaults',
110 dump_cmd => [
111 'pg_dump', '--no-sync', '-Fd',
112 "--file=$tempdir/defaults_dir_format", 'postgres',
114 restore_cmd => [
115 'pg_restore',
116 "--file=$tempdir/defaults_dir_format.sql",
117 "$tempdir/defaults_dir_format",
120 defaults_parallel => {
121 test_key => 'defaults',
122 dump_cmd => [
123 'pg_dump', '--no-sync', '-Fd', '-j2',
124 "--file=$tempdir/defaults_parallel", 'postgres',
126 restore_cmd => [
127 'pg_restore',
128 "--file=$tempdir/defaults_parallel.sql",
129 "$tempdir/defaults_parallel",
132 defaults_tar_format => {
133 test_key => 'defaults',
134 dump_cmd => [
135 'pg_dump', '--no-sync', '-Ft',
136 "--file=$tempdir/defaults_tar_format.tar", 'postgres',
138 restore_cmd => [
139 'pg_restore',
140 "--file=$tempdir/defaults_tar_format.sql",
141 "$tempdir/defaults_tar_format.tar",
144 exclude_table => {
145 dump_cmd => [
146 'pg_dump',
147 '--exclude-table=regress_table_dumpable',
148 "--file=$tempdir/exclude_table.sql",
149 'postgres',
152 extension_schema => {
153 dump_cmd => [
154 'pg_dump', '--schema=public',
155 "--file=$tempdir/extension_schema.sql", 'postgres',
158 pg_dumpall_globals => {
159 dump_cmd => [
160 'pg_dumpall', '--no-sync',
161 "--file=$tempdir/pg_dumpall_globals.sql", '-g',
164 no_privs => {
165 dump_cmd => [
166 'pg_dump', '--no-sync',
167 "--file=$tempdir/no_privs.sql", '-x',
168 'postgres',
171 no_owner => {
172 dump_cmd => [
173 'pg_dump', '--no-sync',
174 "--file=$tempdir/no_owner.sql", '-O',
175 'postgres',
179 # regress_dump_login_role shouldn't need SELECT rights on internal
180 # (undumped) extension tables
181 privileged_internals => {
182 dump_cmd => [
183 'pg_dump', '--no-sync',
184 "--file=$tempdir/privileged_internals.sql",
185 # these two tables are irrelevant to the test case
186 '--exclude-table=regress_pg_dump_schema.external_tab',
187 '--exclude-table=regress_pg_dump_schema.extdependtab',
188 '--username=regress_dump_login_role', 'postgres',
192 schema_only => {
193 dump_cmd => [
194 'pg_dump', '--no-sync', "--file=$tempdir/schema_only.sql",
195 '-s', 'postgres',
198 section_pre_data => {
199 dump_cmd => [
200 'pg_dump', '--no-sync',
201 "--file=$tempdir/section_pre_data.sql", '--section=pre-data',
202 'postgres',
205 section_data => {
206 dump_cmd => [
207 'pg_dump', '--no-sync',
208 "--file=$tempdir/section_data.sql", '--section=data',
209 'postgres',
212 section_post_data => {
213 dump_cmd => [
214 'pg_dump', '--no-sync', "--file=$tempdir/section_post_data.sql",
215 '--section=post-data', 'postgres',
218 with_extension => {
219 dump_cmd => [
220 'pg_dump', '--no-sync', "--file=$tempdir/with_extension.sql",
221 '--extension=test_pg_dump', 'postgres',
224 exclude_extension => {
225 dump_cmd => [
226 'pg_dump', '--no-sync',
227 "--file=$tempdir/exclude_extension.sql",
228 '--exclude-extension=test_pg_dump', 'postgres',
231 exclude_extension_filter => {
232 dump_cmd => [
233 'pg_dump',
234 '--no-sync',
235 "--file=$tempdir/exclude_extension_filter.sql",
236 "--filter=$tempdir/exclude_extension_filter.txt",
237 'postgres',
241 # plpgsql in the list blocks the dump of extension test_pg_dump
242 without_extension => {
243 dump_cmd => [
244 'pg_dump', '--no-sync', "--file=$tempdir/without_extension.sql",
245 '--extension=plpgsql', 'postgres',
249 # plpgsql in the list of extensions blocks the dump of extension
250 # test_pg_dump. "public" is the schema used by the extension
251 # test_pg_dump, but none of its objects should be dumped.
252 without_extension_explicit_schema => {
253 dump_cmd => [
254 'pg_dump',
255 '--no-sync',
256 "--file=$tempdir/without_extension_explicit_schema.sql",
257 '--extension=plpgsql',
258 '--schema=public',
259 'postgres',
263 # plpgsql in the list of extensions blocks the dump of extension
264 # test_pg_dump, but not the dump of objects not dependent on the
265 # extension located on a schema maintained by the extension.
266 without_extension_internal_schema => {
267 dump_cmd => [
268 'pg_dump',
269 '--no-sync',
270 "--file=$tempdir/without_extension_internal_schema.sql",
271 '--extension=plpgsql',
272 '--schema=regress_pg_dump_schema',
273 'postgres',
275 },);
277 ###############################################################
278 # Definition of the tests to run.
280 # Each test is defined using the log message that will be used.
282 # A regexp should be defined for each test which provides the
283 # basis for the test. That regexp will be run against the output
284 # file of each of the runs which the test is to be run against
285 # and the success of the result will depend on if the regexp
286 # result matches the expected 'like' or 'unlike' case.
287 # The runs listed as 'like' will be checked if they match the
288 # regexp and, if so, the test passes. All runs which are not
289 # listed as 'like' will be checked to ensure they don't match
290 # the regexp; if they do, the test will fail.
292 # The below hashes provide convenience sets of runs. Individual
293 # runs can be excluded from a general hash by placing that run
294 # into the 'unlike' section.
296 # There can then be a 'create_sql' and 'create_order' for a
297 # given test. The 'create_sql' commands are collected up in
298 # 'create_order' and then run against the database prior to any
299 # of the pg_dump runs happening. This is what "seeds" the
300 # system with objects to be dumped out.
302 # Building of this hash takes a bit of time as all of the regexps
303 # included in it are compiled. This greatly improves performance
304 # as the regexps are used for each run the test applies to.
306 # Tests which are considered 'full' dumps by pg_dump, but there
307 # are flags used to exclude specific items (ACLs, LOs, etc).
308 my %full_runs = (
309 binary_upgrade => 1,
310 clean => 1,
311 clean_if_exists => 1,
312 createdb => 1,
313 defaults => 1,
314 exclude_table => 1,
315 no_privs => 1,
316 no_owner => 1,
317 privileged_internals => 1,
318 with_extension => 1,
319 exclude_extension => 1,
320 exclude_extension_filter => 1,
321 without_extension => 1);
323 my %tests = (
324 'ALTER EXTENSION test_pg_dump' => {
325 create_order => 9,
326 create_sql =>
327 'ALTER EXTENSION test_pg_dump ADD TABLE regress_pg_dump_table_added;',
328 regexp => qr/^
329 \QCREATE TABLE public.regress_pg_dump_table_added (\E
330 \n\s+\Qcol1 integer NOT NULL,\E
331 \n\s+\Qcol2 integer\E
332 \n\);\n/xm,
333 like => { binary_upgrade => 1, },
336 'CREATE EXTENSION test_pg_dump' => {
337 create_order => 2,
338 create_sql => 'CREATE EXTENSION test_pg_dump;',
339 regexp => qr/^
340 \QCREATE EXTENSION IF NOT EXISTS test_pg_dump WITH SCHEMA public;\E
341 \n/xm,
342 like => {
343 %full_runs,
344 schema_only => 1,
345 section_pre_data => 1,
347 unlike => {
348 binary_upgrade => 1,
349 exclude_extension => 1,
350 exclude_extension_filter => 1,
351 without_extension => 1
355 'CREATE ROLE regress_dump_test_role' => {
356 create_order => 1,
357 create_sql => 'CREATE ROLE regress_dump_test_role;',
358 regexp => qr/^CREATE ROLE regress_dump_test_role;\n/m,
359 like => { pg_dumpall_globals => 1, },
362 'CREATE ROLE regress_dump_login_role' => {
363 create_order => 1,
364 create_sql => 'CREATE ROLE regress_dump_login_role LOGIN;',
365 regexp => qr/^
366 \QCREATE ROLE regress_dump_login_role;\E
367 \n\QALTER ROLE regress_dump_login_role WITH \E.*\Q LOGIN \E.*;
368 \n/xm,
369 like => { pg_dumpall_globals => 1, },
372 'GRANT ALTER SYSTEM ON PARAMETER full_page_writes TO regress_dump_test_role'
373 => {
374 create_order => 2,
375 create_sql =>
376 'GRANT ALTER SYSTEM ON PARAMETER full_page_writes TO regress_dump_test_role;',
377 regexp =>
379 qr/^GRANT ALTER SYSTEM ON PARAMETER full_page_writes TO regress_dump_test_role;/m,
380 like => { pg_dumpall_globals => 1, },
383 'GRANT ALL ON PARAMETER Custom.Knob TO regress_dump_test_role WITH GRANT OPTION'
384 => {
385 create_order => 2,
386 create_sql =>
387 'GRANT SET, ALTER SYSTEM ON PARAMETER Custom.Knob TO regress_dump_test_role WITH GRANT OPTION;',
388 regexp =>
389 # "set" plus "alter system" is "all" privileges on parameters
390 qr/^GRANT ALL ON PARAMETER "custom.knob" TO regress_dump_test_role WITH GRANT OPTION;/m,
391 like => { pg_dumpall_globals => 1, },
394 'GRANT ALL ON PARAMETER DateStyle TO regress_dump_test_role' => {
395 create_order => 2,
396 create_sql =>
397 'GRANT ALL ON PARAMETER "DateStyle" TO regress_dump_test_role WITH GRANT OPTION; REVOKE GRANT OPTION FOR ALL ON PARAMETER DateStyle FROM regress_dump_test_role;',
398 regexp =>
399 # The revoke simplifies the ultimate grant so as to not include "with grant option"
400 qr/^GRANT ALL ON PARAMETER datestyle TO regress_dump_test_role;/m,
401 like => { pg_dumpall_globals => 1, },
404 'CREATE SCHEMA public' => {
405 regexp => qr/^CREATE SCHEMA public;/m,
406 like => {
407 extension_schema => 1,
408 without_extension_explicit_schema => 1,
412 'CREATE SEQUENCE regress_pg_dump_table_col1_seq' => {
413 regexp => qr/^
414 \QCREATE SEQUENCE public.regress_pg_dump_table_col1_seq\E
415 \n\s+\QAS integer\E
416 \n\s+\QSTART WITH 1\E
417 \n\s+\QINCREMENT BY 1\E
418 \n\s+\QNO MINVALUE\E
419 \n\s+\QNO MAXVALUE\E
420 \n\s+\QCACHE 1;\E
421 \n/xm,
422 like => { binary_upgrade => 1, },
425 'CREATE TABLE regress_pg_dump_table_added' => {
426 create_order => 7,
427 create_sql =>
428 'CREATE TABLE regress_pg_dump_table_added (col1 int not null, col2 int);',
429 regexp => qr/^
430 \QCREATE TABLE public.regress_pg_dump_table_added (\E
431 \n\s+\Qcol1 integer NOT NULL,\E
432 \n\s+\Qcol2 integer\E
433 \n\);\n/xm,
434 like => { binary_upgrade => 1, },
437 'CREATE SEQUENCE regress_pg_dump_seq' => {
438 regexp => qr/^
439 \QCREATE SEQUENCE public.regress_pg_dump_seq\E
440 \n\s+\QSTART WITH 1\E
441 \n\s+\QINCREMENT BY 1\E
442 \n\s+\QNO MINVALUE\E
443 \n\s+\QNO MAXVALUE\E
444 \n\s+\QCACHE 1;\E
445 \n/xm,
446 like => { binary_upgrade => 1, },
449 'SETVAL SEQUENCE regress_seq_dumpable' => {
450 create_order => 6,
451 create_sql => qq{SELECT nextval('regress_seq_dumpable');},
452 regexp => qr/^
453 \QSELECT pg_catalog.setval('public.regress_seq_dumpable', 1, true);\E
454 \n/xm,
455 like => {
456 %full_runs,
457 data_only => 1,
458 section_data => 1,
459 extension_schema => 1,
461 unlike => {
462 exclude_extension => 1,
463 exclude_extension_filter => 1,
464 without_extension => 1,
468 'CREATE TABLE regress_pg_dump_table' => {
469 regexp => qr/^
470 \QCREATE TABLE public.regress_pg_dump_table (\E
471 \n\s+\Qcol1 integer NOT NULL,\E
472 \n\s+\Qcol2 integer,\E
473 \n\s+\QCONSTRAINT regress_pg_dump_table_col2_check CHECK ((col2 > 0))\E
474 \n\);\n/xm,
475 like => { binary_upgrade => 1, },
478 'COPY public.regress_table_dumpable (col1)' => {
479 regexp => qr/^
480 \QCOPY public.regress_table_dumpable (col1) FROM stdin;\E
481 \n/xm,
482 like => {
483 %full_runs,
484 data_only => 1,
485 section_data => 1,
486 extension_schema => 1,
488 unlike => {
489 binary_upgrade => 1,
490 exclude_table => 1,
491 exclude_extension => 1,
492 exclude_extension_filter => 1,
493 without_extension => 1,
497 'REVOKE ALL ON FUNCTION wgo_then_no_access' => {
498 create_order => 3,
499 create_sql => q{
500 DO $$BEGIN EXECUTE format(
501 'REVOKE ALL ON FUNCTION wgo_then_no_access()
502 FROM pg_signal_backend, public, %I',
503 (SELECT usename
504 FROM pg_user JOIN pg_proc ON proowner = usesysid
505 WHERE proname = 'wgo_then_no_access')); END$$;},
506 regexp => qr/^
507 \QREVOKE ALL ON FUNCTION public.wgo_then_no_access() FROM PUBLIC;\E
508 \n\QREVOKE ALL ON FUNCTION public.wgo_then_no_access() FROM \E.*;
509 \n\QREVOKE ALL ON FUNCTION public.wgo_then_no_access() FROM pg_signal_backend;\E
510 /xm,
511 like => {
512 %full_runs,
513 schema_only => 1,
514 section_pre_data => 1,
516 unlike => {
517 no_privs => 1,
518 exclude_extension => 1,
519 exclude_extension_filter => 1,
520 without_extension => 1,
524 'REVOKE GRANT OPTION FOR UPDATE ON SEQUENCE wgo_then_regular' => {
525 create_order => 3,
526 create_sql => 'REVOKE GRANT OPTION FOR UPDATE ON SEQUENCE
527 wgo_then_regular FROM pg_signal_backend;',
528 regexp => qr/^
529 \QREVOKE ALL ON SEQUENCE public.wgo_then_regular FROM pg_signal_backend;\E
530 \n\QGRANT SELECT,UPDATE ON SEQUENCE public.wgo_then_regular TO pg_signal_backend;\E
531 \n\QGRANT USAGE ON SEQUENCE public.wgo_then_regular TO pg_signal_backend WITH GRANT OPTION;\E
532 /xm,
533 like => {
534 %full_runs,
535 schema_only => 1,
536 section_pre_data => 1,
538 unlike => {
539 no_privs => 1,
540 exclude_extension => 1,
541 exclude_extension_filter => 1,
542 without_extension => 1,
546 'CREATE ACCESS METHOD regress_test_am' => {
547 regexp => qr/^
548 \QCREATE ACCESS METHOD regress_test_am TYPE INDEX HANDLER bthandler;\E
549 \n/xm,
550 like => { binary_upgrade => 1, },
553 'COMMENT ON EXTENSION test_pg_dump' => {
554 regexp => qr/^
555 \QCOMMENT ON EXTENSION test_pg_dump \E
556 \QIS 'Test pg_dump with an extension';\E
557 \n/xm,
558 like => {
559 %full_runs,
560 schema_only => 1,
561 section_pre_data => 1,
563 unlike => {
564 exclude_extension => 1,
565 exclude_extension_filter => 1,
566 without_extension => 1,
570 'GRANT SELECT regress_pg_dump_table_added pre-ALTER EXTENSION' => {
571 create_order => 8,
572 create_sql =>
573 'GRANT SELECT ON regress_pg_dump_table_added TO regress_dump_test_role;',
574 regexp => qr/^
575 \QGRANT SELECT ON TABLE public.regress_pg_dump_table_added TO regress_dump_test_role;\E
576 \n/xm,
577 like => { binary_upgrade => 1, },
580 'REVOKE SELECT regress_pg_dump_table_added post-ALTER EXTENSION' => {
581 create_order => 10,
582 create_sql =>
583 'REVOKE SELECT ON regress_pg_dump_table_added FROM regress_dump_test_role;',
584 regexp => qr/^
585 \QREVOKE SELECT ON TABLE public.regress_pg_dump_table_added FROM regress_dump_test_role;\E
586 \n/xm,
587 like => {
588 %full_runs,
589 schema_only => 1,
590 section_pre_data => 1,
592 unlike => {
593 no_privs => 1,
594 exclude_extension => 1,
595 exclude_extension_filter => 1,
596 without_extension => 1,
600 'GRANT SELECT ON TABLE regress_pg_dump_table' => {
601 regexp => qr/^
602 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\E\n
603 \QGRANT SELECT ON TABLE public.regress_pg_dump_table TO regress_dump_test_role;\E\n
604 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
605 \n/xms,
606 like => { binary_upgrade => 1, },
609 'GRANT SELECT(col1) ON regress_pg_dump_table' => {
610 regexp => qr/^
611 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\E\n
612 \QGRANT SELECT(col1) ON TABLE public.regress_pg_dump_table TO PUBLIC;\E\n
613 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
614 \n/xms,
615 like => { binary_upgrade => 1, },
618 'GRANT SELECT(col2) ON regress_pg_dump_table TO regress_dump_test_role'
619 => {
620 create_order => 4,
621 create_sql => 'GRANT SELECT(col2) ON regress_pg_dump_table
622 TO regress_dump_test_role;',
623 regexp => qr/^
624 \QGRANT SELECT(col2) ON TABLE public.regress_pg_dump_table TO regress_dump_test_role;\E
625 \n/xm,
626 like => {
627 %full_runs,
628 schema_only => 1,
629 section_pre_data => 1,
631 unlike => {
632 no_privs => 1,
633 exclude_extension => 1,
634 exclude_extension_filter => 1,
635 without_extension => 1
639 'GRANT USAGE ON regress_pg_dump_table_col1_seq TO regress_dump_test_role'
640 => {
641 create_order => 5,
642 create_sql => 'GRANT USAGE ON SEQUENCE regress_pg_dump_table_col1_seq
643 TO regress_dump_test_role;',
644 regexp => qr/^
645 \QGRANT USAGE ON SEQUENCE public.regress_pg_dump_table_col1_seq TO regress_dump_test_role;\E
646 \n/xm,
647 like => {
648 %full_runs,
649 schema_only => 1,
650 section_pre_data => 1,
652 unlike => {
653 no_privs => 1,
654 exclude_extension => 1,
655 exclude_extension_filter => 1,
656 without_extension => 1,
660 'GRANT USAGE ON regress_pg_dump_seq TO regress_dump_test_role' => {
661 regexp => qr/^
662 \QGRANT USAGE ON SEQUENCE public.regress_pg_dump_seq TO regress_dump_test_role;\E
663 \n/xm,
664 like => { binary_upgrade => 1, },
667 'REVOKE SELECT(col1) ON regress_pg_dump_table' => {
668 create_order => 3,
669 create_sql => 'REVOKE SELECT(col1) ON regress_pg_dump_table
670 FROM PUBLIC;',
671 regexp => qr/^
672 \QREVOKE SELECT(col1) ON TABLE public.regress_pg_dump_table FROM PUBLIC;\E
673 \n/xm,
674 like => {
675 %full_runs,
676 schema_only => 1,
677 section_pre_data => 1,
679 unlike => {
680 no_privs => 1,
681 exclude_extension => 1,
682 exclude_extension_filter => 1,
683 without_extension => 1,
687 # Objects included in extension part of a schema created by this extension */
688 'CREATE TABLE regress_pg_dump_schema.test_table' => {
689 regexp => qr/^
690 \QCREATE TABLE regress_pg_dump_schema.test_table (\E
691 \n\s+\Qcol1 integer,\E
692 \n\s+\Qcol2 integer,\E
693 \n\s+\QCONSTRAINT test_table_col2_check CHECK ((col2 > 0))\E
694 \n\);\n/xm,
695 like => { binary_upgrade => 1, },
698 'GRANT SELECT ON regress_pg_dump_schema.test_table' => {
699 regexp => qr/^
700 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\E\n
701 \QGRANT SELECT ON TABLE regress_pg_dump_schema.test_table TO regress_dump_test_role;\E\n
702 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
703 \n/xms,
704 like => { binary_upgrade => 1, },
707 'CREATE SEQUENCE regress_pg_dump_schema.test_seq' => {
708 regexp => qr/^
709 \QCREATE SEQUENCE regress_pg_dump_schema.test_seq\E
710 \n\s+\QSTART WITH 1\E
711 \n\s+\QINCREMENT BY 1\E
712 \n\s+\QNO MINVALUE\E
713 \n\s+\QNO MAXVALUE\E
714 \n\s+\QCACHE 1;\E
715 \n/xm,
716 like => { binary_upgrade => 1, },
719 'GRANT USAGE ON regress_pg_dump_schema.test_seq' => {
720 regexp => qr/^
721 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\E\n
722 \QGRANT USAGE ON SEQUENCE regress_pg_dump_schema.test_seq TO regress_dump_test_role;\E\n
723 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
724 \n/xms,
725 like => { binary_upgrade => 1, },
728 'CREATE TYPE regress_pg_dump_schema.test_type' => {
729 regexp => qr/^
730 \QCREATE TYPE regress_pg_dump_schema.test_type AS (\E
731 \n\s+\Qcol1 integer\E
732 \n\);\n/xm,
733 like => { binary_upgrade => 1, },
736 'GRANT USAGE ON regress_pg_dump_schema.test_type' => {
737 regexp => qr/^
738 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\E\n
739 \QGRANT ALL ON TYPE regress_pg_dump_schema.test_type TO regress_dump_test_role;\E\n
740 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
741 \n/xms,
742 like => { binary_upgrade => 1, },
745 'CREATE FUNCTION regress_pg_dump_schema.test_func' => {
746 regexp => qr/^
747 \QCREATE FUNCTION regress_pg_dump_schema.test_func() RETURNS integer\E
748 \n\s+\QLANGUAGE sql\E
749 \n/xm,
750 like => { binary_upgrade => 1, },
753 'GRANT ALL ON regress_pg_dump_schema.test_func' => {
754 regexp => qr/^
755 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\E\n
756 \QGRANT ALL ON FUNCTION regress_pg_dump_schema.test_func() TO regress_dump_test_role;\E\n
757 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
758 \n/xms,
759 like => { binary_upgrade => 1, },
762 'CREATE AGGREGATE regress_pg_dump_schema.test_agg' => {
763 regexp => qr/^
764 \QCREATE AGGREGATE regress_pg_dump_schema.test_agg(smallint) (\E
765 \n\s+\QSFUNC = int2_sum,\E
766 \n\s+\QSTYPE = bigint\E
767 \n\);\n/xm,
768 like => { binary_upgrade => 1, },
771 'GRANT ALL ON regress_pg_dump_schema.test_agg' => {
772 regexp => qr/^
773 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(true);\E\n
774 \QGRANT ALL ON FUNCTION regress_pg_dump_schema.test_agg(smallint) TO regress_dump_test_role;\E\n
775 \QSELECT pg_catalog.binary_upgrade_set_record_init_privs(false);\E
776 \n/xms,
777 like => { binary_upgrade => 1, },
780 'ALTER INDEX pkey DEPENDS ON extension' => {
781 create_order => 11,
782 create_sql =>
783 'CREATE TABLE regress_pg_dump_schema.extdependtab (col1 integer primary key, col2 int);
784 CREATE INDEX ON regress_pg_dump_schema.extdependtab (col2);
785 ALTER INDEX regress_pg_dump_schema.extdependtab_col2_idx DEPENDS ON EXTENSION test_pg_dump;
786 ALTER INDEX regress_pg_dump_schema.extdependtab_pkey DEPENDS ON EXTENSION test_pg_dump;',
787 regexp => qr/^
788 \QALTER INDEX regress_pg_dump_schema.extdependtab_pkey DEPENDS ON EXTENSION test_pg_dump;\E\n
789 /xms,
790 like => {%pgdump_runs},
791 unlike => {
792 data_only => 1,
793 extension_schema => 1,
794 pg_dumpall_globals => 1,
795 privileged_internals => 1,
796 section_data => 1,
797 section_pre_data => 1,
798 # Excludes this schema as extension is not listed.
799 without_extension_explicit_schema => 1,
803 'ALTER INDEX idx DEPENDS ON extension' => {
804 regexp => qr/^
805 \QALTER INDEX regress_pg_dump_schema.extdependtab_col2_idx DEPENDS ON EXTENSION test_pg_dump;\E\n
806 /xms,
807 like => {%pgdump_runs},
808 unlike => {
809 data_only => 1,
810 extension_schema => 1,
811 pg_dumpall_globals => 1,
812 privileged_internals => 1,
813 section_data => 1,
814 section_pre_data => 1,
815 # Excludes this schema as extension is not listed.
816 without_extension_explicit_schema => 1,
820 # Objects not included in extension, part of schema created by extension
821 'CREATE TABLE regress_pg_dump_schema.external_tab' => {
822 create_order => 4,
823 create_sql => 'CREATE TABLE regress_pg_dump_schema.external_tab
824 (col1 int);',
825 regexp => qr/^
826 \QCREATE TABLE regress_pg_dump_schema.external_tab (\E
827 \n\s+\Qcol1 integer\E
828 \n\);\n/xm,
829 like => {
830 %full_runs,
831 schema_only => 1,
832 section_pre_data => 1,
833 # Excludes the extension and keeps the schema's data.
834 without_extension_internal_schema => 1,
836 unlike => { privileged_internals => 1 },
837 },);
839 #########################################
840 # Create a PG instance to test actually dumping from
842 my $node = PostgreSQL::Test::Cluster->new('main');
843 $node->init('auth_extra' => [ '--create-role', 'regress_dump_login_role' ]);
844 $node->start;
846 my $port = $node->port;
848 my $supports_gzip = check_pg_config("#define HAVE_LIBZ 1");
850 #########################################
851 # Set up schemas, tables, etc, to be dumped.
853 # Build up the create statements
854 my $create_sql = '';
856 foreach my $test (
857 sort {
858 if ($tests{$a}->{create_order} and $tests{$b}->{create_order})
860 $tests{$a}->{create_order} <=> $tests{$b}->{create_order};
862 elsif ($tests{$a}->{create_order})
866 elsif ($tests{$b}->{create_order})
870 else
874 } keys %tests)
876 if ($tests{$test}->{create_sql})
878 $create_sql .= $tests{$test}->{create_sql};
882 # Send the combined set of commands to psql
883 $node->safe_psql('postgres', $create_sql);
885 #########################################
886 # Create filter file for exclude_extension_filter test
888 my $filterfile;
890 open $filterfile, '>', "$tempdir/exclude_extension_filter.txt"
891 or die "unable to open filter file for writing";
892 print $filterfile "exclude extension test_pg_dump\n";
893 close $filterfile;
895 #########################################
896 # Run all runs
898 foreach my $run (sort keys %pgdump_runs)
901 my $test_key = $run;
903 # Skip command-level tests for gzip if there is no support for it.
904 if ( defined($pgdump_runs{$run}->{compile_option})
905 && $pgdump_runs{$run}->{compile_option} eq 'gzip'
906 && !$supports_gzip)
908 note "$run: skipped due to no gzip support";
909 next;
912 $node->command_ok(\@{ $pgdump_runs{$run}->{dump_cmd} },
913 "$run: pg_dump runs");
915 if ($pgdump_runs{$run}->{restore_cmd})
917 $node->command_ok(\@{ $pgdump_runs{$run}->{restore_cmd} },
918 "$run: pg_restore runs");
921 if ($pgdump_runs{$run}->{test_key})
923 $test_key = $pgdump_runs{$run}->{test_key};
926 my $output_file = slurp_file("$tempdir/${run}.sql");
928 #########################################
929 # Run all tests where this run is included
930 # as either a 'like' or 'unlike' test.
932 foreach my $test (sort keys %tests)
934 # Check for proper test definitions
936 # There should be a "like" list, even if it is empty. (This
937 # makes the test more self-documenting.)
938 if (!defined($tests{$test}->{like}))
940 die "missing \"like\" in test \"$test\"";
942 # Check for useless entries in "unlike" list. Runs that are
943 # not listed in "like" don't need to be excluded in "unlike".
944 if ($tests{$test}->{unlike}->{$test_key}
945 && !defined($tests{$test}->{like}->{$test_key}))
947 die "useless \"unlike\" entry \"$test_key\" in test \"$test\"";
950 # Run the test listed as a like, unless it is specifically noted
951 # as an unlike (generally due to an explicit exclusion or similar).
952 if ($tests{$test}->{like}->{$test_key}
953 && !defined($tests{$test}->{unlike}->{$test_key}))
955 if (!ok($output_file =~ $tests{$test}->{regexp},
956 "$run: should dump $test"))
958 diag("Review $run results in $tempdir");
961 else
963 if (!ok($output_file !~ $tests{$test}->{regexp},
964 "$run: should not dump $test"))
966 diag("Review $run results in $tempdir");
972 #########################################
973 # Stop the database instance, which will be removed at the end of the tests.
975 $node->stop('fast');
977 done_testing();