From 4c110bd7a28d9e231fa8ccea715bbf11f9c7b384 Mon Sep 17 00:00:00 2001 From: jian he Date: Mon, 2 Mar 2026 15:17:52 +0800 Subject: [PATCH v8 1/1] pg_dumpall error out conflict options --roles-only --tablespaces-only --statistics-only --schema-only --globals-only --data-only --statistics The only permitted combination is `--statistics --statistics-only`, since pg_dump supports it as well and the semantics(meaning) of "only" are preserved. These 4 combinations should fail immediately: --schema-only --no-schema --data-only --no-data --statistics-only --no-statistics --statistics --no-statistics discussion: https://postgr.es/m/CACJufxFf5=wSv2MsuO8iZOvpLZQ1-meAMwhw7JX5gNvWo5PDug@mail.gmail.com commitfest entry: https://commitfest.postgresql.org/patch/6459 --- src/bin/pg_dump/dumputils.c | 21 ++++ src/bin/pg_dump/dumputils.h | 1 + src/bin/pg_dump/pg_dumpall.c | 80 ++++++------ src/bin/pg_dump/t/001_basic.pl | 128 +++++++++++++++++++- src/bin/pg_dump/t/002_pg_dump.pl | 2 - src/bin/pg_dump/t/005_pg_dump_filterfile.pl | 2 +- 6 files changed, 190 insertions(+), 44 deletions(-) diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index 5bc77fed974..21c7a20b310 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -1000,3 +1000,24 @@ valid_restrict_key(const char *restrict_key) restrict_key[0] != '\0' && strspn(restrict_key, restrict_chars) == strlen(restrict_key); } + +void +CheckMutuallyExclusiveOpts(int n,...) +{ + char *first = NULL; + va_list args; + + va_start(args, n); + for (int i = 0; i < n; i += 2) + { + bool set = va_arg(args, int); + char *opt = va_arg(args, char *); + + if (set && !first) + first = opt; + else if (set) + pg_fatal("options %s and %s cannot be used together", + first, opt); + } + va_end(args); +} diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h index d231ce1d654..c386558049c 100644 --- a/src/bin/pg_dump/dumputils.h +++ b/src/bin/pg_dump/dumputils.h @@ -68,5 +68,6 @@ extern void create_or_open_dir(const char *dirname); extern char *generate_restrict_key(void); extern bool valid_restrict_key(const char *restrict_key); +extern void CheckMutuallyExclusiveOpts(int n,...); #endif /* DUMPUTILS_H */ diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 1165a0f4afe..f30e7cecfaa 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -217,6 +217,7 @@ main(int argc, char *argv[]) const char *format_name = "p"; trivalue prompt_password = TRI_DEFAULT; bool data_only = false; + bool schema_only = false; bool globals_only = false; bool roles_only = false; bool tablespaces_only = false; @@ -226,6 +227,9 @@ main(int argc, char *argv[]) ret; int optindex; DumpOptions dopt; + bool dump_DBs; + bool dump_roles; + bool dump_tablespaces; pg_logging_init(argv[0]); pg_logging_set_level(PG_LOG_WARNING); @@ -321,6 +325,7 @@ main(int argc, char *argv[]) break; case 's': + schema_only = true; appendPQExpBufferStr(pgdumpopts, " -s"); break; @@ -418,45 +423,36 @@ main(int argc, char *argv[]) exit_nicely(1); } - if (database_exclude_patterns.head != NULL && - (globals_only || roles_only || tablespaces_only)) - { - pg_log_error("option %s cannot be used together with %s, %s, or %s", - "--exclude-database", - "-g/--globals-only", "-r/--roles-only", "-t/--tablespaces-only"); - pg_log_error_hint("Try \"%s --help\" for more information.", progname); - exit_nicely(1); - } - - /* Make sure the user hasn't specified a mix of globals-only options */ - if (globals_only && roles_only) - { - pg_log_error("options %s and %s cannot be used together", - "-g/--globals-only", "-r/--roles-only"); - pg_log_error_hint("Try \"%s --help\" for more information.", progname); - exit_nicely(1); - } - - if (globals_only && tablespaces_only) - { - pg_log_error("options %s and %s cannot be used together", - "-g/--globals-only", "-t/--tablespaces-only"); - pg_log_error_hint("Try \"%s --help\" for more information.", progname); - exit_nicely(1); - } + CheckMutuallyExclusiveOpts(4, data_only, "-a/--data-only", + no_data, "--no-data"); + CheckMutuallyExclusiveOpts(4, schema_only, "-s/--schema-only", + no_schema, "--no-schema"); + CheckMutuallyExclusiveOpts(4, statistics_only, "--statistics-only", + no_statistics, "--no-statistics"); + CheckMutuallyExclusiveOpts(4, with_statistics, "--statistics", + no_statistics, "--no-statistics"); + CheckMutuallyExclusiveOpts(12, globals_only, "-g/--globals-only", + roles_only, "-r/--roles-only", + tablespaces_only, "-t/--tablespaces-only", + data_only, "-a/--data-only", + schema_only, "-s/--schema-only", + statistics_only, "--statistics-only"); + CheckMutuallyExclusiveOpts(12, + globals_only, "-g/--globals-only", + roles_only, "-r/--roles-only", + tablespaces_only, "-t/--tablespaces-only", + schema_only, "-s/--schema-only", + data_only, "-a/--data-only", + with_statistics, "--statistics"); + CheckMutuallyExclusiveOpts(8, database_exclude_patterns.head != NULL, "--exclude-database", + globals_only, "-g/--globals-only", + roles_only, "-r/--roles-only", + tablespaces_only, "-t/--tablespaces-only"); if (if_exists && !output_clean) pg_fatal("option %s requires option %s", "--if-exists", "-c/--clean"); - if (roles_only && tablespaces_only) - { - pg_log_error("options %s and %s cannot be used together", - "-r/--roles-only", "-t/--tablespaces-only"); - pg_log_error_hint("Try \"%s --help\" for more information.", progname); - exit_nicely(1); - } - /* Get format for dump. */ archDumpFormat = parseDumpFormat(format_name); @@ -766,6 +762,10 @@ main(int argc, char *argv[]) fprintf(OPF, "\n"); } + dump_DBs = !globals_only && !roles_only && !tablespaces_only; + dump_tablespaces = !roles_only && !no_tablespaces; + dump_roles = !tablespaces_only; + if (!data_only && !statistics_only && !no_schema) { /* @@ -782,13 +782,13 @@ main(int argc, char *argv[]) */ if (output_clean || archDumpFormat != archNull) { - if (!globals_only && !roles_only && !tablespaces_only) + if (dump_DBs) dropDBs(conn); - if (!roles_only && !no_tablespaces) + if (dump_tablespaces) dropTablespaces(conn); - if (!tablespaces_only) + if (dump_roles) dropRoles(conn); } @@ -796,7 +796,7 @@ main(int argc, char *argv[]) * Now create objects as requested. Be careful that option logic here * is the same as for drops above. */ - if (!tablespaces_only) + if (dump_roles) { /* Dump roles (users) */ dumpRoles(conn); @@ -810,7 +810,7 @@ main(int argc, char *argv[]) } /* Dump tablespaces */ - if (!roles_only && !no_tablespaces) + if (dump_tablespaces) dumpTablespaces(conn); } @@ -823,7 +823,7 @@ main(int argc, char *argv[]) fprintf(OPF, "\\unrestrict %s\n\n", restrict_key); } - if (!globals_only && !roles_only && !tablespaces_only) + if (dump_DBs) dumpDatabases(conn); if (archDumpFormat == archNull) diff --git a/src/bin/pg_dump/t/001_basic.pl b/src/bin/pg_dump/t/001_basic.pl index a895bc314b0..abb75ba5746 100644 --- a/src/bin/pg_dump/t/001_basic.pl +++ b/src/bin/pg_dump/t/001_basic.pl @@ -220,12 +220,138 @@ command_fails_like( 'pg_dumpall: options -g/--globals-only and -t/--tablespaces-only cannot be used together' ); +command_fails_like( + [ 'pg_dumpall', '--data-only', '--no-data'], + qr/\Qpg_dumpall: error: options -a\/--data-only and --no-data cannot be used together\E/, + 'pg_dumpall: error: options --no-data and -a/--data-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '--schema-only', '--no-schema'], + qr/\Qpg_dumpall: error: options -s\/--schema-only and --no-schema cannot be used together\E/, + 'pg_dumpall: error: options -s/--schema-only and --no-schema cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '--statistics-only', '--no-statistics'], + qr/\Qpg_dumpall: error: options --statistics-only and --no-statistics cannot be used together\E/, + 'pg_dumpall: error: options --statistics-only and --no-statistics cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '--statistics', '--no-statistics'], + qr/\Qpg_dumpall: error: options --statistics and --no-statistics cannot be used together\E/, + 'pg_dumpall: error: options --statistics and --no-statistics cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-g', '--statistics' ], + qr/\Qpg_dumpall: error: options -g\/--globals-only and --statistics cannot be used together\E/, + 'pg_dumpall: error: options -g/--globals-only and --statistics cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-g', '--statistics-only' ], + qr/\Qpg_dumpall: error: options -g\/--globals-only and --statistics-only cannot be used together\E/, + 'pg_dumpall: error: options -g/--globals-only and --statistics-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-g', '-s' ], + qr/\Qpg_dumpall: error: options -g\/--globals-only and -s\/--schema-only cannot be used together\E/, + 'pg_dumpall: error: options -g/--globals-only and -s/--schema-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-g', '-a' ], + qr/\Qpg_dumpall: error: options -g\/--globals-only and -a\/--data-only cannot be used together\E/, + 'pg_dumpall: error: options -g/--globals-only and -a/--data-only cannot be used together' +); + command_fails_like( [ 'pg_dumpall', '-r', '-t' ], qr/\Qpg_dumpall: error: options -r\/--roles-only and -t\/--tablespaces-only cannot be used together\E/, 'pg_dumpall: options -r/--roles-only and -t/--tablespaces-only cannot be used together' ); +command_fails_like( + [ 'pg_dumpall', '-r', '-s' ], + qr/\Qpg_dumpall: error: options -r\/--roles-only and -s\/--schema-only cannot be used together\E/, + 'pg_dumpall: error: options -r/--roles-only and -s/--schema-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-r', '--statistics' ], + qr/\Qpg_dumpall: error: options -r\/--roles-only and --statistics cannot be used together\E/, + 'pg_dumpall: error: options -r/--roles-only and --statistics cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-r', '--statistics-only' ], + qr/\Qpg_dumpall: error: options -r\/--roles-only and --statistics-only cannot be used together\E/, + 'pg_dumpall: error: options -r/--roles-only and --statistics-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-r', '-a' ], + qr/\Qpg_dumpall: error: options -r\/--roles-only and -a\/--data-only cannot be used together\E/, + 'pg_dumpall: error: options -r/--roles-only and -a/--data-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-t', '-s' ], + qr/\Qpg_dumpall: error: options -t\/--tablespaces-only and -s\/--schema-only cannot be used together\E/, + 'pg_dumpall: error: options -t/--tablespaces-only and -s/--schema-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-t', '--statistics' ], + qr/\Qpg_dumpall: error: options -t\/--tablespaces-only and --statistics cannot be used together\E/, + 'pg_dumpall: error: options -t/--tablespaces-only and --statistics cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-t', '--statistics-only'], + qr/\Qpg_dumpall: error: options -t\/--tablespaces-only and --statistics-only cannot be used together\E/, + 'pg_dumpall: error: options -t/--tablespaces-only and --statistics-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-t', '-a'], + qr/\Qpg_dumpall: error: options -t\/--tablespaces-only and -a\/--data-only cannot be used together\E/, + 'pg_dumpall: error: options -t/--tablespaces-only and -a/--data-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-a', '-s' ], + qr/\Qpg_dumpall: error: options -a\/--data-only and -s\/--schema-only cannot be used together\E/, + 'pg_dumpall: error: options -a/--data-only and -s/--schema-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-a', '--statistics' ], + qr/\Qpg_dumpall: error: options -a\/--data-only and --statistics cannot be used together\E/, + 'pg_dumpall: error: options -a/--data-only and --statistics cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-a', '--statistics-only' ], + qr/\Qpg_dumpall: error: options -a\/--data-only and --statistics-only cannot be used together\E/, + 'pg_dumpall: error: options -a/--data-only and --statistics-only cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-s', '--statistics' ], + qr/\Qpg_dumpall: error: options -s\/--schema-only and --statistics cannot be used together\E/, + 'pg_dumpall: error: options -s/--schema-only and --statistics cannot be used together' +); + +command_fails_like( + [ 'pg_dumpall', '-s', '--statistics-only' ], + qr/\Qpg_dumpall: error: options -s\/--schema-only and --statistics-only cannot be used together\E/, + 'pg_dumpall: error: options /-s\/--schema-only and --statistics-only cannot be used together' +); + command_fails_like( [ 'pg_dumpall', '--if-exists' ], qr/\Qpg_dumpall: error: option --if-exists requires option -c\/--clean\E/, @@ -240,7 +366,7 @@ command_fails_like( # also fails for -r and -t, but it seems pointless to add more tests for those. command_fails_like( [ 'pg_dumpall', '--exclude-database=foo', '--globals-only' ], - qr/\Qpg_dumpall: error: option --exclude-database cannot be used together with -g\/--globals-only\E/, + qr/\Qpg_dumpall: error: options --exclude-database and -g\/--globals-only cannot be used together\E/, 'pg_dumpall: option --exclude-database cannot be used together with -g/--globals-only' ); diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl index f15bd06adcc..b06941f7088 100644 --- a/src/bin/pg_dump/t/002_pg_dump.pl +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -322,7 +322,6 @@ my %pgdump_runs = ( '--file' => "$tempdir/pg_dumpall_globals.sql", '--globals-only', '--no-sync', - '--statistics', ], }, pg_dumpall_globals_clean => { @@ -332,7 +331,6 @@ my %pgdump_runs = ( '--globals-only', '--clean', '--no-sync', - '--statistics', ], }, pg_dumpall_dbprivs => { diff --git a/src/bin/pg_dump/t/005_pg_dump_filterfile.pl b/src/bin/pg_dump/t/005_pg_dump_filterfile.pl index 9c9f2baa733..9cc88247037 100644 --- a/src/bin/pg_dump/t/005_pg_dump_filterfile.pl +++ b/src/bin/pg_dump/t/005_pg_dump_filterfile.pl @@ -571,7 +571,7 @@ command_fails_like( '--filter' => "$tempdir/inputfile.txt", '--globals-only' ], - qr/\Qpg_dumpall: error: option --exclude-database cannot be used together with -g\/--globals-only\E/, + qr/\Qpg_dumpall: error: options --exclude-database and -g\/--globals-only cannot be used together\E/, 'pg_dumpall: option --exclude-database cannot be used together with -g/--globals-only' ); -- 2.50.1 (Apple Git-155)