PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_dumpall.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_dumpall.c
4 *
5 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
7 *
8 * pg_dumpall forces all pg_dump output to be text, since it also outputs
9 * text into the same output stream.
10 *
11 * src/bin/pg_dump/pg_dumpall.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#include "postgres_fe.h"
17
18#include <time.h>
19#include <unistd.h>
20
21#include "catalog/pg_authid_d.h"
22#include "common/connect.h"
23#include "common/file_perm.h"
24#include "common/file_utils.h"
26#include "common/logging.h"
27#include "common/string.h"
28#include "connectdb.h"
29#include "dumputils.h"
31#include "filter.h"
32#include "getopt_long.h"
33
34/* version string we expect back from pg_dump */
35#define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
36
37typedef struct
38{
41 char *rolename;
43
44#define SH_PREFIX rolename
45#define SH_ELEMENT_TYPE RoleNameEntry
46#define SH_KEY_TYPE char *
47#define SH_KEY rolename
48#define SH_HASH_KEY(tb, key) hash_string(key)
49#define SH_EQUAL(tb, a, b) (strcmp(a, b) == 0)
50#define SH_STORE_HASH
51#define SH_GET_HASH(tb, a) (a)->hashval
52#define SH_SCOPE static inline
53#define SH_RAW_ALLOCATOR pg_malloc0
54#define SH_DECLARE
55#define SH_DEFINE
56#include "lib/simplehash.h"
57
58static void help(void);
59
60static void dropRoles(PGconn *conn);
61static void dumpRoles(PGconn *conn);
62static void dumpRoleMembership(PGconn *conn);
63static void dumpRoleGUCPrivs(PGconn *conn);
64static void dropTablespaces(PGconn *conn);
65static void dumpTablespaces(PGconn *conn);
66static void dropDBs(PGconn *conn);
67static void dumpUserConfig(PGconn *conn, const char *username);
68static void dumpDatabases(PGconn *conn);
69static void dumpTimestamp(const char *msg);
70static int runPgDump(const char *dbname, const char *create_opts);
71static void buildShSecLabels(PGconn *conn,
72 const char *catalog_name, Oid objectId,
73 const char *objtype, const char *objname,
74 PQExpBuffer buffer);
75static void executeCommand(PGconn *conn, const char *query);
77 SimpleStringList *names);
78static void read_dumpall_filters(const char *filename, SimpleStringList *pattern);
79
82static const char *connstr = "";
83static bool output_clean = false;
84static bool skip_acls = false;
85static bool verbose = false;
86static bool dosync = true;
87
88static int binary_upgrade = 0;
89static int column_inserts = 0;
91static int disable_triggers = 0;
92static int if_exists = 0;
93static int inserts = 0;
95static int no_tablespaces = 0;
96static int use_setsessauth = 0;
97static int no_comments = 0;
98static int no_policies = 0;
99static int no_publications = 0;
100static int no_security_labels = 0;
101static int no_data = 0;
102static int no_schema = 0;
103static int no_statistics = 0;
104static int no_subscriptions = 0;
105static int no_toast_compression = 0;
107static int no_role_passwords = 0;
108static int with_statistics = 0;
109static int server_version;
112static int statistics_only = 0;
113static int sequence_data = 0;
114
115static char role_catalog[10];
116#define PG_AUTHID "pg_authid"
117#define PG_ROLES "pg_roles "
118
119static FILE *OPF;
120static char *filename = NULL;
121
124
125static char *restrict_key;
126
127int
128main(int argc, char *argv[])
129{
130 static struct option long_options[] = {
131 {"data-only", no_argument, NULL, 'a'},
132 {"clean", no_argument, NULL, 'c'},
133 {"encoding", required_argument, NULL, 'E'},
134 {"file", required_argument, NULL, 'f'},
135 {"globals-only", no_argument, NULL, 'g'},
136 {"host", required_argument, NULL, 'h'},
137 {"dbname", required_argument, NULL, 'd'},
138 {"database", required_argument, NULL, 'l'},
139 {"no-owner", no_argument, NULL, 'O'},
140 {"port", required_argument, NULL, 'p'},
141 {"roles-only", no_argument, NULL, 'r'},
142 {"schema-only", no_argument, NULL, 's'},
143 {"superuser", required_argument, NULL, 'S'},
144 {"tablespaces-only", no_argument, NULL, 't'},
145 {"username", required_argument, NULL, 'U'},
146 {"verbose", no_argument, NULL, 'v'},
147 {"no-password", no_argument, NULL, 'w'},
148 {"password", no_argument, NULL, 'W'},
149 {"no-privileges", no_argument, NULL, 'x'},
150 {"no-acl", no_argument, NULL, 'x'},
151
152 /*
153 * the following options don't have an equivalent short option letter
154 */
155 {"attribute-inserts", no_argument, &column_inserts, 1},
156 {"binary-upgrade", no_argument, &binary_upgrade, 1},
157 {"column-inserts", no_argument, &column_inserts, 1},
158 {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
159 {"disable-triggers", no_argument, &disable_triggers, 1},
160 {"exclude-database", required_argument, NULL, 6},
161 {"extra-float-digits", required_argument, NULL, 5},
162 {"if-exists", no_argument, &if_exists, 1},
163 {"inserts", no_argument, &inserts, 1},
164 {"lock-wait-timeout", required_argument, NULL, 2},
165 {"no-table-access-method", no_argument, &no_table_access_method, 1},
166 {"no-tablespaces", no_argument, &no_tablespaces, 1},
167 {"quote-all-identifiers", no_argument, &quote_all_identifiers, 1},
168 {"load-via-partition-root", no_argument, &load_via_partition_root, 1},
169 {"role", required_argument, NULL, 3},
170 {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
171 {"no-comments", no_argument, &no_comments, 1},
172 {"no-data", no_argument, &no_data, 1},
173 {"no-policies", no_argument, &no_policies, 1},
174 {"no-publications", no_argument, &no_publications, 1},
175 {"no-role-passwords", no_argument, &no_role_passwords, 1},
176 {"no-schema", no_argument, &no_schema, 1},
177 {"no-security-labels", no_argument, &no_security_labels, 1},
178 {"no-subscriptions", no_argument, &no_subscriptions, 1},
179 {"no-statistics", no_argument, &no_statistics, 1},
180 {"no-sync", no_argument, NULL, 4},
181 {"no-toast-compression", no_argument, &no_toast_compression, 1},
182 {"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
183 {"on-conflict-do-nothing", no_argument, &on_conflict_do_nothing, 1},
184 {"rows-per-insert", required_argument, NULL, 7},
185 {"statistics", no_argument, &with_statistics, 1},
186 {"statistics-only", no_argument, &statistics_only, 1},
187 {"filter", required_argument, NULL, 8},
188 {"sequence-data", no_argument, &sequence_data, 1},
189 {"restrict-key", required_argument, NULL, 9},
190
191 {NULL, 0, NULL, 0}
192 };
193
194 char *pghost = NULL;
195 char *pgport = NULL;
196 char *pguser = NULL;
197 char *pgdb = NULL;
198 char *use_role = NULL;
199 const char *dumpencoding = NULL;
200 trivalue prompt_password = TRI_DEFAULT;
201 bool data_only = false;
202 bool globals_only = false;
203 bool roles_only = false;
204 bool tablespaces_only = false;
205 PGconn *conn;
206 int encoding;
207 int c,
208 ret;
209 int optindex;
210
211 pg_logging_init(argv[0]);
213 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
214 progname = get_progname(argv[0]);
215
216 if (argc > 1)
217 {
218 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
219 {
220 help();
221 exit_nicely(0);
222 }
223 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
224 {
225 puts("pg_dumpall (PostgreSQL) " PG_VERSION);
226 exit_nicely(0);
227 }
228 }
229
230 if ((ret = find_other_exec(argv[0], "pg_dump", PGDUMP_VERSIONSTR,
231 pg_dump_bin)) < 0)
232 {
233 char full_path[MAXPGPATH];
234
235 if (find_my_exec(argv[0], full_path) < 0)
237
238 if (ret == -1)
239 pg_fatal("program \"%s\" is needed by %s but was not found in the same directory as \"%s\"",
240 "pg_dump", progname, full_path);
241 else
242 pg_fatal("program \"%s\" was found by \"%s\" but was not the same version as %s",
243 "pg_dump", full_path, progname);
244 }
245
247
248 while ((c = getopt_long(argc, argv, "acd:E:f:gh:l:Op:rsS:tU:vwWx", long_options, &optindex)) != -1)
249 {
250 switch (c)
251 {
252 case 'a':
253 data_only = true;
255 break;
256
257 case 'c':
258 output_clean = true;
259 break;
260
261 case 'd':
263 break;
264
265 case 'E':
269 break;
270
271 case 'f':
275 break;
276
277 case 'g':
278 globals_only = true;
279 break;
280
281 case 'h':
283 break;
284
285 case 'l':
287 break;
288
289 case 'O':
291 break;
292
293 case 'p':
295 break;
296
297 case 'r':
298 roles_only = true;
299 break;
300
301 case 's':
303 break;
304
305 case 'S':
308 break;
309
310 case 't':
311 tablespaces_only = true;
312 break;
313
314 case 'U':
315 pguser = pg_strdup(optarg);
316 break;
317
318 case 'v':
319 verbose = true;
322 break;
323
324 case 'w':
325 prompt_password = TRI_NO;
327 break;
328
329 case 'W':
330 prompt_password = TRI_YES;
332 break;
333
334 case 'x':
335 skip_acls = true;
337 break;
338
339 case 0:
340 break;
341
342 case 2:
343 appendPQExpBufferStr(pgdumpopts, " --lock-wait-timeout ");
345 break;
346
347 case 3:
348 use_role = pg_strdup(optarg);
349 appendPQExpBufferStr(pgdumpopts, " --role ");
350 appendShellString(pgdumpopts, use_role);
351 break;
352
353 case 4:
354 dosync = false;
355 appendPQExpBufferStr(pgdumpopts, " --no-sync");
356 break;
357
358 case 5:
359 appendPQExpBufferStr(pgdumpopts, " --extra-float-digits ");
361 break;
362
363 case 6:
365 break;
366
367 case 7:
368 appendPQExpBufferStr(pgdumpopts, " --rows-per-insert ");
370 break;
371
372 case 8:
374 break;
375
376 case 9:
378 appendPQExpBufferStr(pgdumpopts, " --restrict-key ");
380 break;
381
382 default:
383 /* getopt_long already emitted a complaint */
384 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
385 exit_nicely(1);
386 }
387 }
388
389 /* Complain if any arguments remain */
390 if (optind < argc)
391 {
392 pg_log_error("too many command-line arguments (first is \"%s\")",
393 argv[optind]);
394 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
395 exit_nicely(1);
396 }
397
400 {
401 pg_log_error("option %s cannot be used together with %s, %s, or %s",
402 "--exclude-database",
403 "-g/--globals-only", "-r/--roles-only", "-t/--tablespaces-only");
404 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
405 exit_nicely(1);
406 }
407
408 /* Make sure the user hasn't specified a mix of globals-only options */
410 {
411 pg_log_error("options %s and %s cannot be used together",
412 "-g/--globals-only", "-r/--roles-only");
413 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
414 exit_nicely(1);
415 }
416
418 {
419 pg_log_error("options %s and %s cannot be used together",
420 "-g/--globals-only", "-t/--tablespaces-only");
421 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
422 exit_nicely(1);
423 }
424
425 if (if_exists && !output_clean)
426 pg_fatal("option %s requires option %s",
427 "--if-exists", "-c/--clean");
428
429 /* --clean and --data-only are incompatible */
430 if (output_clean && data_only)
431 pg_fatal("options %s and %s cannot be used together",
432 "-c/--clean", "-a/--data-only");
433
435 {
436 pg_log_error("options %s and %s cannot be used together",
437 "-r/--roles-only", "-t/--tablespaces-only");
438 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
439 exit_nicely(1);
440 }
441
442 /*
443 * If password values are not required in the dump, switch to using
444 * pg_roles which is equally useful, just more likely to have unrestricted
445 * access than pg_authid.
446 */
449 else
451
452 /* Add long options to the pg_dump argument list */
453 if (binary_upgrade)
454 appendPQExpBufferStr(pgdumpopts, " --binary-upgrade");
455 if (column_inserts)
456 appendPQExpBufferStr(pgdumpopts, " --column-inserts");
458 appendPQExpBufferStr(pgdumpopts, " --disable-dollar-quoting");
460 appendPQExpBufferStr(pgdumpopts, " --disable-triggers");
461 if (inserts)
462 appendPQExpBufferStr(pgdumpopts, " --inserts");
464 appendPQExpBufferStr(pgdumpopts, " --no-table-access-method");
465 if (no_tablespaces)
466 appendPQExpBufferStr(pgdumpopts, " --no-tablespaces");
468 appendPQExpBufferStr(pgdumpopts, " --quote-all-identifiers");
470 appendPQExpBufferStr(pgdumpopts, " --load-via-partition-root");
471 if (use_setsessauth)
472 appendPQExpBufferStr(pgdumpopts, " --use-set-session-authorization");
473 if (no_comments)
474 appendPQExpBufferStr(pgdumpopts, " --no-comments");
475 if (no_data)
476 appendPQExpBufferStr(pgdumpopts, " --no-data");
477 if (no_policies)
478 appendPQExpBufferStr(pgdumpopts, " --no-policies");
479 if (no_publications)
480 appendPQExpBufferStr(pgdumpopts, " --no-publications");
482 appendPQExpBufferStr(pgdumpopts, " --no-security-labels");
483 if (no_schema)
484 appendPQExpBufferStr(pgdumpopts, " --no-schema");
485 if (no_statistics)
486 appendPQExpBufferStr(pgdumpopts, " --no-statistics");
488 appendPQExpBufferStr(pgdumpopts, " --no-subscriptions");
490 appendPQExpBufferStr(pgdumpopts, " --no-toast-compression");
492 appendPQExpBufferStr(pgdumpopts, " --no-unlogged-table-data");
493 if (with_statistics)
494 appendPQExpBufferStr(pgdumpopts, " --statistics");
496 appendPQExpBufferStr(pgdumpopts, " --on-conflict-do-nothing");
497 if (statistics_only)
498 appendPQExpBufferStr(pgdumpopts, " --statistics-only");
499 if (sequence_data)
500 appendPQExpBufferStr(pgdumpopts, " --sequence-data");
501
502 /*
503 * If you don't provide a restrict key, one will be appointed for you.
504 */
505 if (!restrict_key)
507 if (!restrict_key)
508 pg_fatal("could not generate restrict key");
510 pg_fatal("invalid restrict key");
511
512 /*
513 * If there was a database specified on the command line, use that,
514 * otherwise try to connect to database "postgres", and failing that
515 * "template1".
516 */
517 if (pgdb)
518 {
520 prompt_password, false,
522
523 if (!conn)
524 pg_fatal("could not connect to database \"%s\"", pgdb);
525 }
526 else
527 {
528 conn = ConnectDatabase("postgres", connstr, pghost, pgport, pguser,
529 prompt_password, false,
531 if (!conn)
532 conn = ConnectDatabase("template1", connstr, pghost, pgport, pguser,
533 prompt_password, true,
535
536 if (!conn)
537 {
538 pg_log_error("could not connect to databases \"postgres\" or \"template1\"\n"
539 "Please specify an alternative database.");
540 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
541 exit_nicely(1);
542 }
543 }
544
545 /*
546 * Get a list of database names that match the exclude patterns
547 */
550
551 /*
552 * Open the output file if required, otherwise use stdout
553 */
554 if (filename)
555 {
557 if (!OPF)
558 pg_fatal("could not open output file \"%s\": %m",
559 filename);
560 }
561 else
562 OPF = stdout;
563
564 /*
565 * Set the client encoding if requested.
566 */
567 if (dumpencoding)
568 {
570 pg_fatal("invalid client encoding \"%s\" specified",
572 }
573
574 /*
575 * Force standard_conforming_strings on, just in case we are dumping from
576 * an old server that has it disabled. Without this, literals in views,
577 * expressions, etc, would be incorrect for modern servers.
578 */
579 executeCommand(conn, "SET standard_conforming_strings = on");
580
581 /*
582 * Get the active encoding, so we know how to escape strings.
583 */
586
587 /* Set the role if requested */
588 if (use_role)
589 {
591
592 appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
593 executeCommand(conn, query->data);
594 destroyPQExpBuffer(query);
595 }
596
597 /* Force quoting of all identifiers if requested. */
599 executeCommand(conn, "SET quote_all_identifiers = true");
600
601 fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n");
602 if (verbose)
603 dumpTimestamp("Started on");
604
605 /*
606 * Enter restricted mode to block any unexpected psql meta-commands. A
607 * malicious source might try to inject a variety of things via bogus
608 * responses to queries. While we cannot prevent such sources from
609 * affecting the destination at restore time, we can block psql
610 * meta-commands so that the client machine that runs psql with the dump
611 * output remains unaffected.
612 */
613 fprintf(OPF, "\\restrict %s\n\n", restrict_key);
614
615 /*
616 * We used to emit \connect postgres here, but that served no purpose
617 * other than to break things for installations without a postgres
618 * database. Everything we're restoring here is a global, so whichever
619 * database we're connected to at the moment is fine.
620 */
621
622 /* Restore will need to write to the target cluster */
623 fprintf(OPF, "SET default_transaction_read_only = off;\n\n");
624
625 /* Replicate encoding and standard_conforming_strings in output */
626 fprintf(OPF, "SET client_encoding = '%s';\n",
628 fprintf(OPF, "SET standard_conforming_strings = on;\n");
629 fprintf(OPF, "\n");
630
632 {
633 /*
634 * If asked to --clean, do that first. We can avoid detailed
635 * dependency analysis because databases never depend on each other,
636 * and tablespaces never depend on each other. Roles could have
637 * grants to each other, but DROP ROLE will clean those up silently.
638 */
639 if (output_clean)
640 {
642 dropDBs(conn);
643
644 if (!roles_only && !no_tablespaces)
646
647 if (!tablespaces_only)
649 }
650
651 /*
652 * Now create objects as requested. Be careful that option logic here
653 * is the same as for drops above.
654 */
655 if (!tablespaces_only)
656 {
657 /* Dump roles (users) */
659
660 /* Dump role memberships */
662
663 /* Dump role GUC privileges */
664 if (server_version >= 150000 && !skip_acls)
666 }
667
668 /* Dump tablespaces */
669 if (!roles_only && !no_tablespaces)
671 }
672
673 /*
674 * Exit restricted mode just before dumping the databases. pg_dump will
675 * handle entering restricted mode again as appropriate.
676 */
677 fprintf(OPF, "\\unrestrict %s\n\n", restrict_key);
678
681
682 PQfinish(conn);
683
684 if (verbose)
685 dumpTimestamp("Completed on");
686 fprintf(OPF, "--\n-- PostgreSQL database cluster dump complete\n--\n\n");
687
688 if (filename)
689 {
690 fclose(OPF);
691
692 /* sync the resulting file, errors are not fatal */
693 if (dosync)
694 (void) fsync_fname(filename, false);
695 }
696
697 exit_nicely(0);
698}
699
700
701static void
702help(void)
703{
704 printf(_("%s exports a PostgreSQL database cluster as an SQL script.\n\n"), progname);
705 printf(_("Usage:\n"));
706 printf(_(" %s [OPTION]...\n"), progname);
707
708 printf(_("\nGeneral options:\n"));
709 printf(_(" -f, --file=FILENAME output file name\n"));
710 printf(_(" -v, --verbose verbose mode\n"));
711 printf(_(" -V, --version output version information, then exit\n"));
712 printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
713 printf(_(" -?, --help show this help, then exit\n"));
714 printf(_("\nOptions controlling the output content:\n"));
715 printf(_(" -a, --data-only dump only the data, not the schema or statistics\n"));
716 printf(_(" -c, --clean clean (drop) databases before recreating\n"));
717 printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
718 printf(_(" -g, --globals-only dump only global objects, no databases\n"));
719 printf(_(" -O, --no-owner skip restoration of object ownership\n"));
720 printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n"));
721 printf(_(" -s, --schema-only dump only the schema, no data or statistics\n"));
722 printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n"));
723 printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n"));
724 printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
725 printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
726 printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
727 printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
728 printf(_(" --disable-triggers disable triggers during data-only restore\n"));
729 printf(_(" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n"));
730 printf(_(" --extra-float-digits=NUM override default setting for extra_float_digits\n"));
731 printf(_(" --filter=FILENAME exclude databases based on expressions in FILENAME\n"));
732 printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
733 printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
734 printf(_(" --load-via-partition-root load partitions via the root table\n"));
735 printf(_(" --no-comments do not dump comment commands\n"));
736 printf(_(" --no-data do not dump data\n"));
737 printf(_(" --no-policies do not dump row security policies\n"));
738 printf(_(" --no-publications do not dump publications\n"));
739 printf(_(" --no-role-passwords do not dump passwords for roles\n"));
740 printf(_(" --no-schema do not dump schema\n"));
741 printf(_(" --no-security-labels do not dump security label assignments\n"));
742 printf(_(" --no-statistics do not dump statistics\n"));
743 printf(_(" --no-subscriptions do not dump subscriptions\n"));
744 printf(_(" --no-sync do not wait for changes to be written safely to disk\n"));
745 printf(_(" --no-table-access-method do not dump table access methods\n"));
746 printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
747 printf(_(" --no-toast-compression do not dump TOAST compression methods\n"));
748 printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
749 printf(_(" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n"));
750 printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
751 printf(_(" --restrict-key=RESTRICT_KEY use provided string as psql \\restrict key\n"));
752 printf(_(" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n"));
753 printf(_(" --sequence-data include sequence data in dump\n"));
754 printf(_(" --statistics dump the statistics\n"));
755 printf(_(" --statistics-only dump only the statistics, not schema or data\n"));
756 printf(_(" --use-set-session-authorization\n"
757 " use SET SESSION AUTHORIZATION commands instead of\n"
758 " ALTER OWNER commands to set ownership\n"));
759
760 printf(_("\nConnection options:\n"));
761 printf(_(" -d, --dbname=CONNSTR connect using connection string\n"));
762 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
763 printf(_(" -l, --database=DBNAME alternative default database\n"));
764 printf(_(" -p, --port=PORT database server port number\n"));
765 printf(_(" -U, --username=NAME connect as specified database user\n"));
766 printf(_(" -w, --no-password never prompt for password\n"));
767 printf(_(" -W, --password force password prompt (should happen automatically)\n"));
768 printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
769
770 printf(_("\nIf -f/--file is not used, then the SQL script will be written to the standard\n"
771 "output.\n\n"));
772 printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
773 printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
774}
775
776
777/*
778 * Drop roles
779 */
780static void
782{
784 PGresult *res;
785 int i_rolname;
786 int i;
787
789 "SELECT rolname "
790 "FROM %s "
791 "WHERE rolname !~ '^pg_' "
792 "ORDER BY 1", role_catalog);
793
794 res = executeQuery(conn, buf->data);
795
796 i_rolname = PQfnumber(res, "rolname");
797
798 if (PQntuples(res) > 0)
799 fprintf(OPF, "--\n-- Drop roles\n--\n\n");
800
801 for (i = 0; i < PQntuples(res); i++)
802 {
803 const char *rolename;
804
805 rolename = PQgetvalue(res, i, i_rolname);
806
807 fprintf(OPF, "DROP ROLE %s%s;\n",
808 if_exists ? "IF EXISTS " : "",
809 fmtId(rolename));
810 }
811
812 PQclear(res);
814
815 fprintf(OPF, "\n\n");
816}
817
818/*
819 * Dump roles
820 */
821static void
823{
825 PGresult *res;
826 int i_oid,
827 i_rolname,
840 int i;
841
842 /*
843 * Notes: rolconfig is dumped later, and pg_authid must be used for
844 * extracting rolcomment regardless of role_catalog.
845 */
847 "SELECT oid, rolname, rolsuper, rolinherit, "
848 "rolcreaterole, rolcreatedb, "
849 "rolcanlogin, rolconnlimit, rolpassword, "
850 "rolvaliduntil, rolreplication, rolbypassrls, "
851 "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment, "
852 "rolname = current_user AS is_current_user "
853 "FROM %s "
854 "WHERE rolname !~ '^pg_' "
855 "ORDER BY 2", role_catalog);
856
857 res = executeQuery(conn, buf->data);
858
859 i_oid = PQfnumber(res, "oid");
860 i_rolname = PQfnumber(res, "rolname");
861 i_rolsuper = PQfnumber(res, "rolsuper");
862 i_rolinherit = PQfnumber(res, "rolinherit");
863 i_rolcreaterole = PQfnumber(res, "rolcreaterole");
864 i_rolcreatedb = PQfnumber(res, "rolcreatedb");
865 i_rolcanlogin = PQfnumber(res, "rolcanlogin");
866 i_rolconnlimit = PQfnumber(res, "rolconnlimit");
867 i_rolpassword = PQfnumber(res, "rolpassword");
868 i_rolvaliduntil = PQfnumber(res, "rolvaliduntil");
869 i_rolreplication = PQfnumber(res, "rolreplication");
870 i_rolbypassrls = PQfnumber(res, "rolbypassrls");
871 i_rolcomment = PQfnumber(res, "rolcomment");
872 i_is_current_user = PQfnumber(res, "is_current_user");
873
874 if (PQntuples(res) > 0)
875 fprintf(OPF, "--\n-- Roles\n--\n\n");
876
877 for (i = 0; i < PQntuples(res); i++)
878 {
879 const char *rolename;
881
882 auth_oid = atooid(PQgetvalue(res, i, i_oid));
883 rolename = PQgetvalue(res, i, i_rolname);
884
885 if (strncmp(rolename, "pg_", 3) == 0)
886 {
887 pg_log_warning("role name starting with \"pg_\" skipped (%s)",
888 rolename);
889 continue;
890 }
891
893
894 if (binary_upgrade)
895 {
896 appendPQExpBufferStr(buf, "\n-- For binary upgrade, must preserve pg_authid.oid\n");
898 "SELECT pg_catalog.binary_upgrade_set_next_pg_authid_oid('%u'::pg_catalog.oid);\n\n",
899 auth_oid);
900 }
901
902 /*
903 * We dump CREATE ROLE followed by ALTER ROLE to ensure that the role
904 * will acquire the right properties even if it already exists (ie, it
905 * won't hurt for the CREATE to fail). This is particularly important
906 * for the role we are connected as, since even with --clean we will
907 * have failed to drop it. binary_upgrade cannot generate any errors,
908 * so we assume the current role is already created.
909 */
910 if (!binary_upgrade ||
911 strcmp(PQgetvalue(res, i, i_is_current_user), "f") == 0)
912 appendPQExpBuffer(buf, "CREATE ROLE %s;\n", fmtId(rolename));
913 appendPQExpBuffer(buf, "ALTER ROLE %s WITH", fmtId(rolename));
914
915 if (strcmp(PQgetvalue(res, i, i_rolsuper), "t") == 0)
916 appendPQExpBufferStr(buf, " SUPERUSER");
917 else
918 appendPQExpBufferStr(buf, " NOSUPERUSER");
919
920 if (strcmp(PQgetvalue(res, i, i_rolinherit), "t") == 0)
921 appendPQExpBufferStr(buf, " INHERIT");
922 else
923 appendPQExpBufferStr(buf, " NOINHERIT");
924
925 if (strcmp(PQgetvalue(res, i, i_rolcreaterole), "t") == 0)
926 appendPQExpBufferStr(buf, " CREATEROLE");
927 else
928 appendPQExpBufferStr(buf, " NOCREATEROLE");
929
930 if (strcmp(PQgetvalue(res, i, i_rolcreatedb), "t") == 0)
931 appendPQExpBufferStr(buf, " CREATEDB");
932 else
933 appendPQExpBufferStr(buf, " NOCREATEDB");
934
935 if (strcmp(PQgetvalue(res, i, i_rolcanlogin), "t") == 0)
936 appendPQExpBufferStr(buf, " LOGIN");
937 else
938 appendPQExpBufferStr(buf, " NOLOGIN");
939
940 if (strcmp(PQgetvalue(res, i, i_rolreplication), "t") == 0)
941 appendPQExpBufferStr(buf, " REPLICATION");
942 else
943 appendPQExpBufferStr(buf, " NOREPLICATION");
944
945 if (strcmp(PQgetvalue(res, i, i_rolbypassrls), "t") == 0)
946 appendPQExpBufferStr(buf, " BYPASSRLS");
947 else
948 appendPQExpBufferStr(buf, " NOBYPASSRLS");
949
950 if (strcmp(PQgetvalue(res, i, i_rolconnlimit), "-1") != 0)
951 appendPQExpBuffer(buf, " CONNECTION LIMIT %s",
953
954
956 {
957 appendPQExpBufferStr(buf, " PASSWORD ");
959 }
960
961 if (!PQgetisnull(res, i, i_rolvaliduntil))
962 appendPQExpBuffer(buf, " VALID UNTIL '%s'",
964
966
967 if (!no_comments && !PQgetisnull(res, i, i_rolcomment))
968 {
969 appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
972 }
973
975 buildShSecLabels(conn, "pg_authid", auth_oid,
976 "ROLE", rolename,
977 buf);
978
979 fprintf(OPF, "%s", buf->data);
980 }
981
982 /*
983 * Dump configuration settings for roles after all roles have been dumped.
984 * We do it this way because config settings for roles could mention the
985 * names of other roles.
986 */
987 if (PQntuples(res) > 0)
988 fprintf(OPF, "\n--\n-- User Configurations\n--\n");
989
990 for (i = 0; i < PQntuples(res); i++)
992
993 PQclear(res);
994
995 fprintf(OPF, "\n\n");
996
998}
999
1000
1001/*
1002 * Dump role memberships.
1003 *
1004 * Note: we expect dumpRoles already created all the roles, but there is
1005 * no membership yet.
1006 */
1007static void
1009{
1012 PGresult *res;
1013 int start = 0,
1014 end,
1015 total;
1016 bool dump_grantors;
1017 bool dump_grant_options;
1018 int i_role;
1019 int i_member;
1020 int i_grantor;
1021 int i_roleid;
1022 int i_memberid;
1023 int i_grantorid;
1024 int i_admin_option;
1025 int i_inherit_option;
1026 int i_set_option;
1027
1028 /*
1029 * Previous versions of PostgreSQL didn't used to track the grantor very
1030 * carefully in the backend, and the grantor could be any user even if
1031 * they didn't have ADMIN OPTION on the role, or a user that no longer
1032 * existed. To avoid dump and restore failures, don't dump the grantor
1033 * when talking to an old server version.
1034 *
1035 * Also, in older versions the roleid and/or member could be role OIDs
1036 * that no longer exist. If we find such cases, print a warning and skip
1037 * the entry.
1038 */
1039 dump_grantors = (server_version >= 160000);
1040
1041 /*
1042 * Previous versions of PostgreSQL also did not have grant-level options.
1043 */
1044 dump_grant_options = (server_version >= 160000);
1045
1046 /* Generate and execute query. */
1047 printfPQExpBuffer(buf, "SELECT ur.rolname AS role, "
1048 "um.rolname AS member, "
1049 "ug.rolname AS grantor, "
1050 "a.roleid AS roleid, "
1051 "a.member AS memberid, "
1052 "a.grantor AS grantorid, "
1053 "a.admin_option");
1055 appendPQExpBufferStr(buf, ", a.inherit_option, a.set_option");
1056 appendPQExpBuffer(buf, " FROM pg_auth_members a "
1057 "LEFT JOIN %s ur on ur.oid = a.roleid "
1058 "LEFT JOIN %s um on um.oid = a.member "
1059 "LEFT JOIN %s ug on ug.oid = a.grantor "
1060 "WHERE NOT (ur.rolname ~ '^pg_' AND um.rolname ~ '^pg_')"
1061 "ORDER BY 1,2,3", role_catalog, role_catalog, role_catalog);
1062 res = executeQuery(conn, buf->data);
1063 i_role = PQfnumber(res, "role");
1064 i_member = PQfnumber(res, "member");
1065 i_grantor = PQfnumber(res, "grantor");
1066 i_roleid = PQfnumber(res, "roleid");
1067 i_memberid = PQfnumber(res, "memberid");
1068 i_grantorid = PQfnumber(res, "grantorid");
1069 i_admin_option = PQfnumber(res, "admin_option");
1070 i_inherit_option = PQfnumber(res, "inherit_option");
1071 i_set_option = PQfnumber(res, "set_option");
1072
1073 if (PQntuples(res) > 0)
1074 fprintf(OPF, "--\n-- Role memberships\n--\n\n");
1075
1076 /*
1077 * We can't dump these GRANT commands in arbitrary order, because a role
1078 * that is named as a grantor must already have ADMIN OPTION on the role
1079 * for which it is granting permissions, except for the bootstrap
1080 * superuser, who can always be named as the grantor.
1081 *
1082 * We handle this by considering these grants role by role. For each role,
1083 * we initially consider the only allowable grantor to be the bootstrap
1084 * superuser. Every time we grant ADMIN OPTION on the role to some user,
1085 * that user also becomes an allowable grantor. We make repeated passes
1086 * over the grants for the role, each time dumping those whose grantors
1087 * are allowable and which we haven't done yet. Eventually this should let
1088 * us dump all the grants.
1089 */
1090 total = PQntuples(res);
1091 while (start < total)
1092 {
1093 char *role = PQgetvalue(res, start, i_role);
1094 int i;
1095 bool *done;
1096 int remaining;
1097 int prev_remaining = 0;
1099
1100 /* If we hit a null roleid, we're done (nulls sort to the end). */
1101 if (PQgetisnull(res, start, i_role))
1102 {
1103 /* translator: %s represents a numeric role OID */
1104 pg_log_warning("ignoring role grant for missing role with OID %s",
1105 PQgetvalue(res, start, i_roleid));
1106 break;
1107 }
1108
1109 /* All memberships for a single role should be adjacent. */
1110 for (end = start; end < total; ++end)
1111 {
1112 char *otherrole;
1113
1114 otherrole = PQgetvalue(res, end, i_role);
1115 if (strcmp(role, otherrole) != 0)
1116 break;
1117 }
1118
1119 remaining = end - start;
1120 done = pg_malloc0_array(bool, remaining);
1121
1122 /*
1123 * We use a hashtable to track the member names that have been granted
1124 * admin option. Usually a hashtable is overkill, but sometimes not.
1125 */
1127
1128 /*
1129 * Make repeated passes over the grants for this role until all have
1130 * been dumped.
1131 */
1132 while (remaining > 0)
1133 {
1134 /*
1135 * We should make progress on every iteration, because a notional
1136 * graph whose vertices are grants and whose edges point from
1137 * grantors to members should be connected and acyclic. If we fail
1138 * to make progress, either we or the server have messed up.
1139 */
1141 {
1142 pg_log_error("could not find a legal dump ordering for memberships in role \"%s\"",
1143 role);
1144 PQfinish(conn);
1145 exit_nicely(1);
1146 }
1148
1149 /* Make one pass over the grants for this role. */
1150 for (i = start; i < end; ++i)
1151 {
1152 char *member;
1153 char *grantorid;
1154 char *grantor = NULL;
1156 char *set_option = "true";
1157 char *admin_option;
1158 bool found;
1159
1160 /* If we already did this grant, don't do it again. */
1161 if (done[i - start])
1162 continue;
1163
1164 /* Complain about, then ignore, entries for unknown members. */
1165 if (PQgetisnull(res, i, i_member))
1166 {
1167 /* translator: %s represents a numeric role OID */
1168 pg_log_warning("ignoring role grant to missing role with OID %s",
1169 PQgetvalue(res, i, i_memberid));
1170 done[i - start] = true;
1171 --remaining;
1172 continue;
1173 }
1174 member = PQgetvalue(res, i, i_member);
1175
1176 /* If the grantor is unknown, complain and dump without it. */
1179 {
1180 if (PQgetisnull(res, i, i_grantor))
1181 {
1182 /* translator: %s represents a numeric role OID */
1183 pg_log_warning("grant of role \"%s\" to \"%s\" has invalid grantor OID %s",
1184 role, member, grantorid);
1185 pg_log_warning_detail("This grant will be dumped without GRANTED BY.");
1186 dump_this_grantor = false;
1187 }
1188 else
1189 grantor = PQgetvalue(res, i, i_grantor);
1190 }
1191
1195
1196 /*
1197 * If we're not dumping the grantor or if the grantor is the
1198 * bootstrap superuser, it's fine to dump this now. Otherwise,
1199 * it's got to be someone who has already been granted ADMIN
1200 * OPTION.
1201 */
1202 if (dump_this_grantor &&
1204 rolename_lookup(ht, grantor) == NULL)
1205 continue;
1206
1207 /* Remember that we did this so that we don't do it again. */
1208 done[i - start] = true;
1209 --remaining;
1210
1211 /*
1212 * If ADMIN OPTION is being granted, remember that grants
1213 * listing this member as the grantor can now be dumped.
1214 */
1215 if (*admin_option == 't')
1216 rolename_insert(ht, member, &found);
1217
1218 /* Generate the actual GRANT statement. */
1220 fprintf(OPF, "GRANT %s", fmtId(role));
1221 fprintf(OPF, " TO %s", fmtId(member));
1222 if (*admin_option == 't')
1223 appendPQExpBufferStr(optbuf, "ADMIN OPTION");
1225 {
1226 char *inherit_option;
1227
1228 if (optbuf->data[0] != '\0')
1231 appendPQExpBuffer(optbuf, "INHERIT %s",
1232 *inherit_option == 't' ?
1233 "TRUE" : "FALSE");
1234 }
1235 if (*set_option != 't')
1236 {
1237 if (optbuf->data[0] != '\0')
1239 appendPQExpBufferStr(optbuf, "SET FALSE");
1240 }
1241 if (optbuf->data[0] != '\0')
1242 fprintf(OPF, " WITH %s", optbuf->data);
1244 fprintf(OPF, " GRANTED BY %s", fmtId(grantor));
1245 fprintf(OPF, ";\n");
1246 }
1247 }
1248
1250 pg_free(done);
1251 start = end;
1252 }
1253
1254 PQclear(res);
1256
1257 fprintf(OPF, "\n\n");
1258}
1259
1260
1261/*
1262 * Dump role configuration parameter privileges. This code is used for 15.0
1263 * and later servers.
1264 *
1265 * Note: we expect dumpRoles already created all the roles, but there are
1266 * no per-role configuration parameter privileges yet.
1267 */
1268static void
1270{
1271 PGresult *res;
1272 int i;
1273
1274 /*
1275 * Get all parameters that have non-default acls defined.
1276 */
1277 res = executeQuery(conn, "SELECT parname, "
1278 "pg_catalog.pg_get_userbyid(" CppAsString2(BOOTSTRAP_SUPERUSERID) ") AS parowner, "
1279 "paracl, "
1280 "pg_catalog.acldefault('p', " CppAsString2(BOOTSTRAP_SUPERUSERID) ") AS acldefault "
1281 "FROM pg_catalog.pg_parameter_acl "
1282 "ORDER BY 1");
1283
1284 if (PQntuples(res) > 0)
1285 fprintf(OPF, "--\n-- Role privileges on configuration parameters\n--\n\n");
1286
1287 for (i = 0; i < PQntuples(res); i++)
1288 {
1290 char *parname = PQgetvalue(res, i, 0);
1291 char *parowner = PQgetvalue(res, i, 1);
1292 char *paracl = PQgetvalue(res, i, 2);
1293 char *acldefault = PQgetvalue(res, i, 3);
1294 char *fparname;
1295
1296 /* needed for buildACLCommands() */
1298
1299 if (!buildACLCommands(fparname, NULL, NULL, "PARAMETER",
1302 {
1303 pg_log_error("could not parse ACL list (%s) for parameter \"%s\"",
1304 paracl, parname);
1305 PQfinish(conn);
1306 exit_nicely(1);
1307 }
1308
1309 fprintf(OPF, "%s", buf->data);
1310
1313 }
1314
1315 PQclear(res);
1316 fprintf(OPF, "\n\n");
1317}
1318
1319
1320/*
1321 * Drop tablespaces.
1322 */
1323static void
1325{
1326 PGresult *res;
1327 int i;
1328
1329 /*
1330 * Get all tablespaces except built-in ones (which we assume are named
1331 * pg_xxx)
1332 */
1333 res = executeQuery(conn, "SELECT spcname "
1334 "FROM pg_catalog.pg_tablespace "
1335 "WHERE spcname !~ '^pg_' "
1336 "ORDER BY 1");
1337
1338 if (PQntuples(res) > 0)
1339 fprintf(OPF, "--\n-- Drop tablespaces\n--\n\n");
1340
1341 for (i = 0; i < PQntuples(res); i++)
1342 {
1343 char *spcname = PQgetvalue(res, i, 0);
1344
1345 fprintf(OPF, "DROP TABLESPACE %s%s;\n",
1346 if_exists ? "IF EXISTS " : "",
1347 fmtId(spcname));
1348 }
1349
1350 PQclear(res);
1351
1352 fprintf(OPF, "\n\n");
1353}
1354
1355/*
1356 * Dump tablespaces.
1357 */
1358static void
1360{
1361 PGresult *res;
1362 int i;
1363
1364 /*
1365 * Get all tablespaces except built-in ones (which we assume are named
1366 * pg_xxx)
1367 */
1368 res = executeQuery(conn, "SELECT oid, spcname, "
1369 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
1370 "pg_catalog.pg_tablespace_location(oid), "
1371 "spcacl, acldefault('t', spcowner) AS acldefault, "
1372 "array_to_string(spcoptions, ', '),"
1373 "pg_catalog.shobj_description(oid, 'pg_tablespace') "
1374 "FROM pg_catalog.pg_tablespace "
1375 "WHERE spcname !~ '^pg_' "
1376 "ORDER BY 1");
1377
1378 if (PQntuples(res) > 0)
1379 fprintf(OPF, "--\n-- Tablespaces\n--\n\n");
1380
1381 for (i = 0; i < PQntuples(res); i++)
1382 {
1384 Oid spcoid = atooid(PQgetvalue(res, i, 0));
1385 char *spcname = PQgetvalue(res, i, 1);
1386 char *spcowner = PQgetvalue(res, i, 2);
1387 char *spclocation = PQgetvalue(res, i, 3);
1388 char *spcacl = PQgetvalue(res, i, 4);
1389 char *acldefault = PQgetvalue(res, i, 5);
1390 char *spcoptions = PQgetvalue(res, i, 6);
1391 char *spccomment = PQgetvalue(res, i, 7);
1392 char *fspcname;
1393
1394 /* needed for buildACLCommands() */
1396
1397 if (binary_upgrade)
1398 {
1399 appendPQExpBufferStr(buf, "\n-- For binary upgrade, must preserve pg_tablespace oid\n");
1400 appendPQExpBuffer(buf, "SELECT pg_catalog.binary_upgrade_set_next_pg_tablespace_oid('%u'::pg_catalog.oid);\n", spcoid);
1401 }
1402
1403 appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname);
1404 appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
1405
1406 appendPQExpBufferStr(buf, " LOCATION ");
1407
1408 /*
1409 * In-place tablespaces use a relative path, and need to be dumped
1410 * with an empty string as location.
1411 */
1414 else
1416
1417 appendPQExpBufferStr(buf, ";\n");
1418
1419 if (spcoptions && spcoptions[0] != '\0')
1420 appendPQExpBuffer(buf, "ALTER TABLESPACE %s SET (%s);\n",
1422
1423 /* tablespaces can't have initprivs */
1424
1425 if (!skip_acls &&
1426 !buildACLCommands(fspcname, NULL, NULL, "TABLESPACE",
1429 {
1430 pg_log_error("could not parse ACL list (%s) for tablespace \"%s\"",
1431 spcacl, spcname);
1432 PQfinish(conn);
1433 exit_nicely(1);
1434 }
1435
1436 if (!no_comments && spccomment && spccomment[0] != '\0')
1437 {
1438 appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
1440 appendPQExpBufferStr(buf, ";\n");
1441 }
1442
1443 if (!no_security_labels)
1444 buildShSecLabels(conn, "pg_tablespace", spcoid,
1445 "TABLESPACE", spcname,
1446 buf);
1447
1448 fprintf(OPF, "%s", buf->data);
1449
1452 }
1453
1454 PQclear(res);
1455 fprintf(OPF, "\n\n");
1456}
1457
1458
1459/*
1460 * Dump commands to drop each database.
1461 */
1462static void
1464{
1465 PGresult *res;
1466 int i;
1467
1468 /*
1469 * Skip databases marked not datallowconn, since we'd be unable to connect
1470 * to them anyway. This must agree with dumpDatabases().
1471 */
1472 res = executeQuery(conn,
1473 "SELECT datname "
1474 "FROM pg_database d "
1475 "WHERE datallowconn AND datconnlimit != -2 "
1476 "ORDER BY datname");
1477
1478 if (PQntuples(res) > 0)
1479 fprintf(OPF, "--\n-- Drop databases (except postgres and template1)\n--\n\n");
1480
1481 for (i = 0; i < PQntuples(res); i++)
1482 {
1483 char *dbname = PQgetvalue(res, i, 0);
1484
1485 /*
1486 * Skip "postgres" and "template1"; dumpDatabases() will deal with
1487 * them specially. Also, be sure to skip "template0", even if for
1488 * some reason it's not marked !datallowconn.
1489 */
1490 if (strcmp(dbname, "template1") != 0 &&
1491 strcmp(dbname, "template0") != 0 &&
1492 strcmp(dbname, "postgres") != 0)
1493 {
1494 fprintf(OPF, "DROP DATABASE %s%s;\n",
1495 if_exists ? "IF EXISTS " : "",
1496 fmtId(dbname));
1497 }
1498 }
1499
1500 PQclear(res);
1501
1502 fprintf(OPF, "\n\n");
1503}
1504
1505
1506/*
1507 * Dump user-specific configuration
1508 */
1509static void
1511{
1513 PGresult *res;
1514
1515 printfPQExpBuffer(buf, "SELECT unnest(setconfig) FROM pg_db_role_setting "
1516 "WHERE setdatabase = 0 AND setrole = "
1517 "(SELECT oid FROM %s WHERE rolname = ",
1518 role_catalog);
1521
1522 res = executeQuery(conn, buf->data);
1523
1524 if (PQntuples(res) > 0)
1525 {
1526 char *sanitized;
1527
1529 fprintf(OPF, "\n--\n-- User Config \"%s\"\n--\n\n", sanitized);
1530 free(sanitized);
1531 }
1532
1533 for (int i = 0; i < PQntuples(res); i++)
1534 {
1537 "ROLE", username, NULL, NULL,
1538 buf);
1539 fprintf(OPF, "%s", buf->data);
1540 }
1541
1542 PQclear(res);
1543
1545}
1546
1547/*
1548 * Find a list of database names that match the given patterns.
1549 * See also expand_table_name_patterns() in pg_dump.c
1550 */
1551static void
1554 SimpleStringList *names)
1555{
1556 PQExpBuffer query;
1557 PGresult *res;
1558
1559 if (patterns->head == NULL)
1560 return; /* nothing to do */
1561
1562 query = createPQExpBuffer();
1563
1564 /*
1565 * The loop below runs multiple SELECTs, which might sometimes result in
1566 * duplicate entries in the name list, but we don't care, since all we're
1567 * going to do is test membership of the list.
1568 */
1569
1570 for (SimpleStringListCell *cell = patterns->head; cell; cell = cell->next)
1571 {
1572 int dotcnt;
1573
1575 "SELECT datname FROM pg_catalog.pg_database n\n");
1576 processSQLNamePattern(conn, query, cell->val, false,
1577 false, NULL, "datname", NULL, NULL, NULL,
1578 &dotcnt);
1579
1580 if (dotcnt > 0)
1581 {
1582 pg_log_error("improper qualified name (too many dotted names): %s",
1583 cell->val);
1584 PQfinish(conn);
1585 exit_nicely(1);
1586 }
1587
1588 res = executeQuery(conn, query->data);
1589 for (int i = 0; i < PQntuples(res); i++)
1590 {
1591 simple_string_list_append(names, PQgetvalue(res, i, 0));
1592 }
1593
1594 PQclear(res);
1595 resetPQExpBuffer(query);
1596 }
1597
1598 destroyPQExpBuffer(query);
1599}
1600
1601/*
1602 * Dump contents of databases.
1603 */
1604static void
1606{
1607 PGresult *res;
1608 int i;
1609
1610 /*
1611 * Skip databases marked not datallowconn, since we'd be unable to connect
1612 * to them anyway. This must agree with dropDBs().
1613 *
1614 * We arrange for template1 to be processed first, then we process other
1615 * DBs in alphabetical order. If we just did them all alphabetically, we
1616 * might find ourselves trying to drop the "postgres" database while still
1617 * connected to it. This makes trying to run the restore script while
1618 * connected to "template1" a bad idea, but there's no fixed order that
1619 * doesn't have some failure mode with --clean.
1620 */
1621 res = executeQuery(conn,
1622 "SELECT datname "
1623 "FROM pg_database d "
1624 "WHERE datallowconn AND datconnlimit != -2 "
1625 "ORDER BY (datname <> 'template1'), datname");
1626
1627 if (PQntuples(res) > 0)
1628 fprintf(OPF, "--\n-- Databases\n--\n\n");
1629
1630 for (i = 0; i < PQntuples(res); i++)
1631 {
1632 char *dbname = PQgetvalue(res, i, 0);
1633 char *sanitized;
1634 const char *create_opts;
1635 int ret;
1636
1637 /* Skip template0, even if it's not marked !datallowconn. */
1638 if (strcmp(dbname, "template0") == 0)
1639 continue;
1640
1641 /* Skip any explicitly excluded database */
1643 {
1644 pg_log_info("excluding database \"%s\"", dbname);
1645 continue;
1646 }
1647
1648 pg_log_info("dumping database \"%s\"", dbname);
1649
1651 fprintf(OPF, "--\n-- Database \"%s\" dump\n--\n\n", sanitized);
1652 free(sanitized);
1653
1654 /*
1655 * We assume that "template1" and "postgres" already exist in the
1656 * target installation. dropDBs() won't have removed them, for fear
1657 * of removing the DB the restore script is initially connected to. If
1658 * --clean was specified, tell pg_dump to drop and recreate them;
1659 * otherwise we'll merely restore their contents. Other databases
1660 * should simply be created.
1661 */
1662 if (strcmp(dbname, "template1") == 0 || strcmp(dbname, "postgres") == 0)
1663 {
1664 if (output_clean)
1665 create_opts = "--clean --create";
1666 else
1667 {
1668 create_opts = "";
1669 /* Since pg_dump won't emit a \connect command, we must */
1670 fprintf(OPF, "\\connect %s\n\n", dbname);
1671 }
1672 }
1673 else
1674 create_opts = "--create";
1675
1676 if (filename)
1677 fclose(OPF);
1678
1680 if (ret != 0)
1681 pg_fatal("pg_dump failed on database \"%s\", exiting", dbname);
1682
1683 if (filename)
1684 {
1686 if (!OPF)
1687 pg_fatal("could not re-open the output file \"%s\": %m",
1688 filename);
1689 }
1690 }
1691
1692 PQclear(res);
1693}
1694
1695
1696
1697/*
1698 * Run pg_dump on dbname, with specified options.
1699 */
1700static int
1701runPgDump(const char *dbname, const char *create_opts)
1702{
1704 PQExpBufferData cmd;
1705 int ret;
1706
1708 initPQExpBuffer(&cmd);
1709
1710 printfPQExpBuffer(&cmd, "\"%s\" %s %s", pg_dump_bin,
1712
1713 /*
1714 * If we have a filename, use the undocumented plain-append pg_dump
1715 * format.
1716 */
1717 if (filename)
1718 appendPQExpBufferStr(&cmd, " -Fa ");
1719 else
1720 appendPQExpBufferStr(&cmd, " -Fp ");
1721
1722 /*
1723 * Append the database name to the already-constructed stem of connection
1724 * string.
1725 */
1726 appendPQExpBuffer(&connstrbuf, "%s dbname=", connstr);
1728
1730
1731 pg_log_info("running \"%s\"", cmd.data);
1732
1733 fflush(NULL);
1734
1735 ret = system(cmd.data);
1736
1737 termPQExpBuffer(&cmd);
1739
1740 return ret;
1741}
1742
1743/*
1744 * buildShSecLabels
1745 *
1746 * Build SECURITY LABEL command(s) for a shared object
1747 *
1748 * The caller has to provide object type and identity in two separate formats:
1749 * catalog_name (e.g., "pg_database") and object OID, as well as
1750 * type name (e.g., "DATABASE") and object name (not pre-quoted).
1751 *
1752 * The command(s) are appended to "buffer".
1753 */
1754static void
1756 const char *objtype, const char *objname,
1757 PQExpBuffer buffer)
1758{
1760 PGresult *res;
1761
1762 buildShSecLabelQuery(catalog_name, objectId, sql);
1763 res = executeQuery(conn, sql->data);
1764 emitShSecLabels(conn, res, buffer, objtype, objname);
1765
1766 PQclear(res);
1767 destroyPQExpBuffer(sql);
1768}
1769
1770/*
1771 * As above for a SQL command (which returns nothing).
1772 */
1773static void
1774executeCommand(PGconn *conn, const char *query)
1775{
1776 PGresult *res;
1777
1778 pg_log_info("executing %s", query);
1779
1780 res = PQexec(conn, query);
1781 if (!res ||
1783 {
1784 pg_log_error("query failed: %s", PQerrorMessage(conn));
1785 pg_log_error_detail("Query was: %s", query);
1786 PQfinish(conn);
1787 exit_nicely(1);
1788 }
1789
1790 PQclear(res);
1791}
1792
1793
1794/*
1795 * dumpTimestamp
1796 */
1797static void
1798dumpTimestamp(const char *msg)
1799{
1800 char buf[64];
1801 time_t now = time(NULL);
1802
1803 if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&now)) != 0)
1804 fprintf(OPF, "-- %s %s\n\n", msg, buf);
1805}
1806
1807/*
1808 * read_dumpall_filters - retrieve database identifier patterns from file
1809 *
1810 * Parse the specified filter file for include and exclude patterns, and add
1811 * them to the relevant lists. If the filename is "-" then filters will be
1812 * read from STDIN rather than a file.
1813 *
1814 * At the moment, the only allowed filter is for database exclusion.
1815 */
1816static void
1818{
1820 char *objname;
1822 FilterObjectType objtype;
1823
1825
1826 while (filter_read_item(&fstate, &objname, &comtype, &objtype))
1827 {
1829 {
1830 pg_log_filter_error(&fstate, _("%s filter for \"%s\" is not allowed"),
1831 "include",
1832 filter_object_type_name(objtype));
1833 exit_nicely(1);
1834 }
1835
1836 switch (objtype)
1837 {
1839 break;
1850 pg_log_filter_error(&fstate, _("unsupported filter object"));
1851 exit_nicely(1);
1852 break;
1853
1855 simple_string_list_append(pattern, objname);
1856 break;
1857 }
1858
1859 if (objname)
1860 free(objname);
1861 }
1862
1864}
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition acl.c:827
void set_option(char *arg)
Definition args.c:261
Datum now(PG_FUNCTION_ARGS)
Definition timestamp.c:1613
#define PG_BINARY_A
Definition c.h:1446
#define PG_TEXTDOMAIN(domain)
Definition c.h:1362
#define CppAsString2(x)
Definition c.h:565
uint32_t uint32
Definition c.h:683
#define PG_BINARY_W
Definition c.h:1448
int find_my_exec(const char *argv0, char *retpath)
Definition exec.c:161
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition exec.c:430
int find_other_exec(const char *argv0, const char *target, const char *versionstr, char *retpath)
Definition exec.c:311
int main(void)
PGresult * executeQuery(PGconn *conn, const char *query)
Definition connectdb.c:278
PGconn * ConnectDatabase(const char *dbname, const char *connection_string, const char *pghost, const char *pgport, const char *pguser, trivalue prompt_password, bool fail_on_error, const char *progname, const char **connstr, int *server_version, char *password, char *override_dbname)
Definition connectdb.c:40
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
char * generate_restrict_key(void)
Definition dumputils.c:976
bool buildACLCommands(const char *name, const char *subname, const char *nspname, const char *type, const char *acls, const char *baseacls, const char *owner, const char *prefix, int remoteVersion, PQExpBuffer sql)
Definition dumputils.c:104
bool valid_restrict_key(const char *restrict_key)
Definition dumputils.c:1000
void buildShSecLabelQuery(const char *catalog_name, Oid objectId, PQExpBuffer sql)
Definition dumputils.c:681
void makeAlterConfigCommand(PGconn *conn, const char *configitem, const char *type, const char *name, const char *type2, const char *name2, PQExpBuffer buf)
Definition dumputils.c:868
char * sanitize_line(const char *str, bool want_hyphen)
Definition dumputils.c:52
void emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer, const char *objtype, const char *objname)
Definition dumputils.c:699
#define PGDUMP_STRFTIME_FMT
Definition dumputils.h:34
#define _(x)
Definition elog.c:96
void fsync_fname(const char *fname, bool isdir)
Definition fd.c:757
int PQclientEncoding(const PGconn *conn)
void PQfinish(PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
int PQsetClientEncoding(PGconn *conn, const char *encoding)
int PQfnumber(const PGresult *res, const char *field_name)
Definition fe-exec.c:3620
PGresult * PQexec(PGconn *conn, const char *query)
Definition fe-exec.c:2279
char * pg_strdup(const char *in)
Definition fe_memutils.c:91
void pg_free(void *ptr)
#define pg_malloc0_array(type, count)
Definition fe_memutils.h:67
void filter_init(FilterStateData *fstate, const char *filename, exit_function f_exit)
Definition filter.c:36
void filter_free(FilterStateData *fstate)
Definition filter.c:60
const char * filter_object_type_name(FilterObjectType fot)
Definition filter.c:82
bool filter_read_item(FilterStateData *fstate, char **objname, FilterCommandType *comtype, FilterObjectType *objtype)
Definition filter.c:392
void pg_log_filter_error(FilterStateData *fstate, const char *fmt,...)
Definition filter.c:154
FilterObjectType
Definition filter.h:48
@ FILTER_OBJECT_TYPE_TABLE_DATA_AND_CHILDREN
Definition filter.h:51
@ FILTER_OBJECT_TYPE_SCHEMA
Definition filter.h:57
@ FILTER_OBJECT_TYPE_INDEX
Definition filter.h:56
@ FILTER_OBJECT_TYPE_TRIGGER
Definition filter.h:60
@ FILTER_OBJECT_TYPE_FOREIGN_DATA
Definition filter.h:54
@ FILTER_OBJECT_TYPE_DATABASE
Definition filter.h:52
@ FILTER_OBJECT_TYPE_FUNCTION
Definition filter.h:55
@ FILTER_OBJECT_TYPE_TABLE_DATA
Definition filter.h:50
@ FILTER_OBJECT_TYPE_NONE
Definition filter.h:49
@ FILTER_OBJECT_TYPE_TABLE_AND_CHILDREN
Definition filter.h:59
@ FILTER_OBJECT_TYPE_EXTENSION
Definition filter.h:53
@ FILTER_OBJECT_TYPE_TABLE
Definition filter.h:58
FilterCommandType
Definition filter.h:38
@ FILTER_COMMAND_TYPE_INCLUDE
Definition filter.h:40
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition getopt_long.c:60
#define no_argument
Definition getopt_long.h:25
#define required_argument
Definition getopt_long.h:26
return str start
int remaining
Definition informix.c:692
static char * username
Definition initdb.c:153
static char * encoding
Definition initdb.c:139
int i
Definition isn.c:77
#define PQgetvalue
#define PQclear
#define PQresultStatus
#define PQgetisnull
#define PQntuples
@ PGRES_COMMAND_OK
Definition libpq-fe.h:131
void pg_logging_increase_verbosity(void)
Definition logging.c:187
void pg_logging_init(const char *argv0)
Definition logging.c:85
void pg_logging_set_level(enum pg_log_level new_level)
Definition logging.c:178
#define pg_log_error(...)
Definition logging.h:108
#define pg_log_error_hint(...)
Definition logging.h:114
#define pg_log_info(...)
Definition logging.h:126
@ PG_LOG_WARNING
Definition logging.h:38
#define pg_log_warning_detail(...)
Definition logging.h:120
#define pg_log_error_detail(...)
Definition logging.h:111
const char * progname
Definition main.c:44
void exit_nicely(int code)
#define pg_fatal(...)
#define MAXPGPATH
static void dumpTimestamp(const char *msg)
static int if_exists
Definition pg_dumpall.c:92
static int on_conflict_do_nothing
Definition pg_dumpall.c:111
static void dropTablespaces(PGconn *conn)
static void expand_dbname_patterns(PGconn *conn, SimpleStringList *patterns, SimpleStringList *names)
static int no_role_passwords
Definition pg_dumpall.c:107
static PQExpBuffer pgdumpopts
Definition pg_dumpall.c:81
static int statistics_only
Definition pg_dumpall.c:112
static int no_table_access_method
Definition pg_dumpall.c:94
static int no_unlogged_table_data
Definition pg_dumpall.c:106
#define PG_AUTHID
Definition pg_dumpall.c:116
static int no_policies
Definition pg_dumpall.c:98
static int binary_upgrade
Definition pg_dumpall.c:88
static int disable_triggers
Definition pg_dumpall.c:91
static void dumpUserConfig(PGconn *conn, const char *username)
static bool dosync
Definition pg_dumpall.c:86
static const char * connstr
Definition pg_dumpall.c:82
static SimpleStringList database_exclude_patterns
Definition pg_dumpall.c:122
static void dumpTablespaces(PGconn *conn)
static void dumpRoleMembership(PGconn *conn)
static char pg_dump_bin[MAXPGPATH]
Definition pg_dumpall.c:80
static SimpleStringList database_exclude_names
Definition pg_dumpall.c:123
static FILE * OPF
Definition pg_dumpall.c:119
static int no_comments
Definition pg_dumpall.c:97
static int no_publications
Definition pg_dumpall.c:99
static int sequence_data
Definition pg_dumpall.c:113
static char * restrict_key
Definition pg_dumpall.c:125
static int no_security_labels
Definition pg_dumpall.c:100
static void dumpDatabases(PGconn *conn)
static int disable_dollar_quoting
Definition pg_dumpall.c:90
static void buildShSecLabels(PGconn *conn, const char *catalog_name, Oid objectId, const char *objtype, const char *objname, PQExpBuffer buffer)
static int no_tablespaces
Definition pg_dumpall.c:95
static int no_toast_compression
Definition pg_dumpall.c:105
#define PG_ROLES
Definition pg_dumpall.c:117
static int inserts
Definition pg_dumpall.c:93
static void executeCommand(PGconn *conn, const char *query)
static bool verbose
Definition pg_dumpall.c:85
static int runPgDump(const char *dbname, const char *create_opts)
static void dumpRoleGUCPrivs(PGconn *conn)
static int no_statistics
Definition pg_dumpall.c:103
static void dumpRoles(PGconn *conn)
Definition pg_dumpall.c:822
static void help(void)
Definition pg_dumpall.c:702
static int use_setsessauth
Definition pg_dumpall.c:96
static int no_data
Definition pg_dumpall.c:101
static int load_via_partition_root
Definition pg_dumpall.c:110
static int column_inserts
Definition pg_dumpall.c:89
static void read_dumpall_filters(const char *filename, SimpleStringList *pattern)
static void dropRoles(PGconn *conn)
Definition pg_dumpall.c:781
static void dropDBs(PGconn *conn)
static int server_version
Definition pg_dumpall.c:109
static char role_catalog[10]
Definition pg_dumpall.c:115
static bool output_clean
Definition pg_dumpall.c:83
static int no_schema
Definition pg_dumpall.c:102
static int no_subscriptions
Definition pg_dumpall.c:104
static char * filename
Definition pg_dumpall.c:120
static int with_statistics
Definition pg_dumpall.c:108
#define PGDUMP_VERSIONSTR
Definition pg_dumpall.c:35
static bool skip_acls
Definition pg_dumpall.c:84
PGDLLIMPORT int optind
Definition getopt.c:47
PGDLLIMPORT char * optarg
Definition getopt.c:49
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define pg_encoding_to_char
Definition pg_wchar.h:483
static const char * pghost
Definition pgbench.c:295
static const char * pgport
Definition pgbench.c:296
#define pg_log_warning(...)
Definition pgfnames.c:24
#define is_absolute_path(filename)
Definition port.h:105
#define sprintf
Definition port.h:263
const char * get_progname(const char *argv0)
Definition path.c:669
#define printf(...)
Definition port.h:267
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
unsigned int Oid
#define atooid(x)
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
PQExpBuffer createPQExpBuffer(void)
Definition pqexpbuffer.c:72
void initPQExpBuffer(PQExpBuffer str)
Definition pqexpbuffer.c:90
void resetPQExpBuffer(PQExpBuffer str)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void destroyPQExpBuffer(PQExpBuffer str)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
char * c
static int fb(int x)
bool quote_all_identifiers
Definition ruleutils.c:344
bool simple_string_list_member(SimpleStringList *list, const char *val)
Definition simple_list.c:87
void simple_string_list_append(SimpleStringList *list, const char *val)
Definition simple_list.c:63
#define free(a)
char * dbname
Definition streamutil.c:49
PGconn * conn
Definition streamutil.c:52
const char * fmtId(const char *rawid)
void setFmtEncoding(int encoding)
void appendShellString(PQExpBuffer buf, const char *str)
void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule, PQExpBuffer dbnamebuf, int *dotcnt)
void appendConnStrVal(PQExpBuffer buf, const char *str)
uint32 hashval
Definition pg_dumpall.c:40
uint32 status
Definition pg_dumpall.c:39
char * rolename
Definition pg_dumpall.c:41
SimpleStringListCell * head
Definition simple_list.h:42
trivalue
Definition vacuumlo.c:35
@ TRI_YES
Definition vacuumlo.c:38
@ TRI_DEFAULT
Definition vacuumlo.c:36
@ TRI_NO
Definition vacuumlo.c:37