Skip to content

Commit f092de0

Browse files
committed
Add --exclude-database option to pg_dumpall
This option functions similarly to pg_dump's --exclude-table option, but for database names. The option can be given once, and the argument can be a pattern including wildcard characters. Author: Andrew Dunstan. Reviewd-by: Fabien Coelho and Michael Paquier Discussion: https://postgr.es/m/43a54a47-4aa7-c70e-9ca6-648f436dd6e6@2ndQuadrant.com
1 parent 9c32e4c commit f092de0

File tree

5 files changed

+124
-2
lines changed

5 files changed

+124
-2
lines changed

doc/src/sgml/ref/pg_dumpall.sgml

+21
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,27 @@ PostgreSQL documentation
311311
</listitem>
312312
</varlistentry>
313313

314+
315+
<varlistentry>
316+
<term><option>--exclude-database=<replaceable class="parameter">pattern</replaceable></option></term>
317+
<listitem>
318+
<para>
319+
Do not dump databases whose name matches
320+
<replaceable class="parameter">pattern</replaceable>.
321+
Multiple patterns can be excluded by writing multiple
322+
<option>--exclude-database</option> switches. The
323+
<replaceable class="parameter">pattern</replaceable> parameter is
324+
interpreted as a pattern according to the same rules used by
325+
<application>psql</application>'s <literal>\d</literal>
326+
commands (see <xref
327+
linkend="app-psql-patterns" endterm="app-psql-patterns-title"/>),
328+
so multiple databases can also be excluded by writing wildcard
329+
characters in the pattern. When using wildcards, be careful to
330+
quote the pattern if needed to prevent shell wildcard expansion.
331+
</para>
332+
</listitem>
333+
</varlistentry>
334+
314335
<varlistentry>
315336
<term><option>--if-exists</option></term>
316337
<listitem>

src/bin/pg_dump/pg_dump.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,8 @@ expand_schema_name_patterns(Archive *fout,
13011301

13021302
/*
13031303
* Find the OIDs of all tables matching the given list of patterns,
1304-
* and append them to the given OID list.
1304+
* and append them to the given OID list. See also expand_dbname_patterns()
1305+
* in pg_dumpall.c
13051306
*/
13061307
static void
13071308
expand_table_name_patterns(Archive *fout,

src/bin/pg_dump/pg_dumpall.c

+78
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ static PGconn *connectDatabase(const char *dbname, const char *connstr, const ch
5252
static char *constructConnStr(const char **keywords, const char **values);
5353
static PGresult *executeQuery(PGconn *conn, const char *query);
5454
static void executeCommand(PGconn *conn, const char *query);
55+
static void expand_dbname_patterns(PGconn *conn, SimpleStringList *patterns,
56+
SimpleStringList *names);
5557

5658
static char pg_dump_bin[MAXPGPATH];
5759
static const char *progname;
@@ -87,6 +89,9 @@ static char role_catalog[10];
8789
static FILE *OPF;
8890
static char *filename = NULL;
8991

92+
static SimpleStringList database_exclude_patterns = {NULL, NULL};
93+
static SimpleStringList database_exclude_names = {NULL, NULL};
94+
9095
#define exit_nicely(code) exit(code)
9196

9297
int
@@ -123,6 +128,7 @@ main(int argc, char *argv[])
123128
{"column-inserts", no_argument, &column_inserts, 1},
124129
{"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
125130
{"disable-triggers", no_argument, &disable_triggers, 1},
131+
{"exclude-database", required_argument, NULL, 6},
126132
{"extra-float-digits", required_argument, NULL, 5},
127133
{"if-exists", no_argument, &if_exists, 1},
128134
{"inserts", no_argument, &inserts, 1},
@@ -324,6 +330,10 @@ main(int argc, char *argv[])
324330
appendShellString(pgdumpopts, optarg);
325331
break;
326332

333+
case 6:
334+
simple_string_list_append(&database_exclude_patterns, optarg);
335+
break;
336+
327337
default:
328338
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
329339
exit_nicely(1);
@@ -340,6 +350,16 @@ main(int argc, char *argv[])
340350
exit_nicely(1);
341351
}
342352

353+
if (database_exclude_patterns.head != NULL &&
354+
(globals_only || roles_only || tablespaces_only))
355+
{
356+
fprintf(stderr, _("%s: option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only or -t/--tablespaces-only\n"),
357+
progname);
358+
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
359+
progname);
360+
exit_nicely(1);
361+
}
362+
343363
/* Make sure the user hasn't specified a mix of globals-only options */
344364
if (globals_only && roles_only)
345365
{
@@ -454,6 +474,12 @@ main(int argc, char *argv[])
454474
}
455475
}
456476

477+
/*
478+
* Get a list of database names that match the exclude patterns
479+
*/
480+
expand_dbname_patterns(conn, &database_exclude_patterns,
481+
&database_exclude_names);
482+
457483
/*
458484
* Open the output file if required, otherwise use stdout
459485
*/
@@ -620,6 +646,7 @@ help(void)
620646
printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
621647
printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
622648
printf(_(" --disable-triggers disable triggers during data-only restore\n"));
649+
printf(_(" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n"));
623650
printf(_(" --extra-float-digits=NUM override default setting for extra_float_digits\n"));
624651
printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
625652
printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
@@ -1358,6 +1385,48 @@ dumpUserConfig(PGconn *conn, const char *username)
13581385
destroyPQExpBuffer(buf);
13591386
}
13601387

1388+
/*
1389+
* Find a list of database names that match the given patterns.
1390+
* See also expand_table_name_patterns() in pg_dump.c
1391+
*/
1392+
static void
1393+
expand_dbname_patterns(PGconn *conn,
1394+
SimpleStringList *patterns,
1395+
SimpleStringList *names)
1396+
{
1397+
PQExpBuffer query;
1398+
PGresult *res;
1399+
1400+
if (patterns->head == NULL)
1401+
return; /* nothing to do */
1402+
1403+
query = createPQExpBuffer();
1404+
1405+
/*
1406+
* The loop below runs multiple SELECTs, which might sometimes result in
1407+
* duplicate entries in the name list, but we don't care, since all
1408+
* we're going to do is test membership of the list.
1409+
*/
1410+
1411+
for (SimpleStringListCell *cell = patterns->head; cell; cell = cell->next)
1412+
{
1413+
appendPQExpBuffer(query,
1414+
"SELECT datname FROM pg_catalog.pg_database n\n");
1415+
processSQLNamePattern(conn, query, cell->val, false,
1416+
false, NULL, "datname", NULL, NULL);
1417+
1418+
res = executeQuery(conn, query->data);
1419+
for (int i = 0; i < PQntuples(res); i++)
1420+
{
1421+
simple_string_list_append(names, PQgetvalue(res, i, 0));
1422+
}
1423+
1424+
PQclear(res);
1425+
resetPQExpBuffer(query);
1426+
}
1427+
1428+
destroyPQExpBuffer(query);
1429+
}
13611430

13621431
/*
13631432
* Dump contents of databases.
@@ -1395,6 +1464,15 @@ dumpDatabases(PGconn *conn)
13951464
if (strcmp(dbname, "template0") == 0)
13961465
continue;
13971466

1467+
/* Skip any explicitly excluded database */
1468+
if (simple_string_list_member(&database_exclude_names, dbname))
1469+
{
1470+
if (verbose)
1471+
fprintf(stderr, _("%s: excluding database \"%s\"...\n"),
1472+
progname, dbname);
1473+
continue;
1474+
}
1475+
13981476
if (verbose)
13991477
fprintf(stderr, _("%s: dumping database \"%s\"...\n"), progname, dbname);
14001478

src/bin/pg_dump/t/001_basic.pl

+12-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use Config;
55
use PostgresNode;
66
use TestLib;
7-
use Test::More tests => 70;
7+
use Test::More tests => 74;
88

99
my $tempdir = TestLib::tempdir;
1010
my $tempdir_short = TestLib::tempdir_short;
@@ -150,3 +150,14 @@
150150
qr/\Qpg_restore: options -C\/--create and -1\/--single-transaction cannot be used together\E/,
151151
'pg_restore: options -C\/--create and -1\/--single-transaction cannot be used together'
152152
);
153+
154+
command_fails_like(
155+
[ 'pg_dumpall', '--exclude-database' ],
156+
qr/\Qpg_dumpall: option '--exclude-database' requires an argument\E/,
157+
'pg_dumpall: option --exclude-database requires an argument');
158+
159+
# also fails for -r and -t, but it seems pointless to add more tests for those.
160+
command_fails_like(
161+
[ 'pg_dumpall', '--exclude-database=foo', '--globals-only' ],
162+
qr/\Qpg_dumpall: option --exclude-database cannot be used together with -g\/--globals-only\E/,
163+
'pg_dumpall: option --exclude-database cannot be used together with -g/--globals-only');

src/bin/pg_dump/t/002_pg_dump.pl

+11
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@
224224
"--file=$tempdir/pg_dumpall_dbprivs.sql",
225225
],
226226
},
227+
pg_dumpall_exclude => {
228+
dump_cmd => [
229+
'pg_dumpall', '-v', "--file=$tempdir/pg_dumpall_exclude.sql",
230+
'--exclude-database', '*dump*', '--no-sync',
231+
],
232+
},
227233
no_blobs => {
228234
dump_cmd => [
229235
'pg_dump', '--no-sync',
@@ -380,6 +386,7 @@
380386
no_owner => 1,
381387
no_privs => 1,
382388
pg_dumpall_dbprivs => 1,
389+
pg_dumpall_exclude => 1,
383390
schema_only => 1,);
384391

385392
# This is where the actual tests are defined.
@@ -444,6 +451,7 @@
444451
pg_dumpall_dbprivs => 1,
445452
pg_dumpall_globals => 1,
446453
pg_dumpall_globals_clean => 1,
454+
pg_dumpall_exclude => 1,
447455
},
448456
},
449457

@@ -1318,6 +1326,7 @@
13181326
regexp => qr/^CREATE ROLE regress_dump_test_role;/m,
13191327
like => {
13201328
pg_dumpall_dbprivs => 1,
1329+
pg_dumpall_exclude => 1,
13211330
pg_dumpall_globals => 1,
13221331
pg_dumpall_globals_clean => 1,
13231332
},
@@ -2442,6 +2451,7 @@
24422451
no_owner => 1,
24432452
only_dump_test_schema => 1,
24442453
pg_dumpall_dbprivs => 1,
2454+
pg_dumpall_exclude => 1,
24452455
schema_only => 1,
24462456
section_post_data => 1,
24472457
test_schema_plus_blobs => 1,
@@ -2512,6 +2522,7 @@
25122522
no_privs => 1,
25132523
no_owner => 1,
25142524
pg_dumpall_dbprivs => 1,
2525+
pg_dumpall_exclude => 1,
25152526
role => 1,
25162527
schema_only => 1,
25172528
section_post_data => 1,

0 commit comments

Comments
 (0)