1 /*-------------------------------------------------------------------------
5 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
8 * pg_dumpall forces all pg_dump output to be text, since it also outputs
9 * text into the same output stream.
11 * src/bin/pg_dump/pg_dumpall.c
13 *-------------------------------------------------------------------------
16 #include "postgres_fe.h"
21 #include "catalog/pg_authid_d.h"
22 #include "common/connect.h"
23 #include "common/file_utils.h"
24 #include "common/hashfn_unstable.h"
25 #include "common/logging.h"
26 #include "common/string.h"
27 #include "dumputils.h"
28 #include "fe_utils/string_utils.h"
30 #include "getopt_long.h"
31 #include "pg_backup.h"
33 /* version string we expect back from pg_dump */
34 #define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
43 #define SH_PREFIX rolename
44 #define SH_ELEMENT_TYPE RoleNameEntry
45 #define SH_KEY_TYPE char *
46 #define SH_KEY rolename
47 #define SH_HASH_KEY(tb, key) hash_string(key)
48 #define SH_EQUAL(tb, a, b) (strcmp(a, b) == 0)
50 #define SH_GET_HASH(tb, a) (a)->hashval
51 #define SH_SCOPE static inline
52 #define SH_RAW_ALLOCATOR pg_malloc0
55 #include "lib/simplehash.h"
57 static void help(void);
59 static void dropRoles(PGconn
*conn
);
60 static void dumpRoles(PGconn
*conn
);
61 static void dumpRoleMembership(PGconn
*conn
);
62 static void dumpRoleGUCPrivs(PGconn
*conn
);
63 static void dropTablespaces(PGconn
*conn
);
64 static void dumpTablespaces(PGconn
*conn
);
65 static void dropDBs(PGconn
*conn
);
66 static void dumpUserConfig(PGconn
*conn
, const char *username
);
67 static void dumpDatabases(PGconn
*conn
);
68 static void dumpTimestamp(const char *msg
);
69 static int runPgDump(const char *dbname
, const char *create_opts
);
70 static void buildShSecLabels(PGconn
*conn
,
71 const char *catalog_name
, Oid objectId
,
72 const char *objtype
, const char *objname
,
74 static PGconn
*connectDatabase(const char *dbname
,
75 const char *connection_string
, const char *pghost
,
76 const char *pgport
, const char *pguser
,
77 trivalue prompt_password
, bool fail_on_error
);
78 static char *constructConnStr(const char **keywords
, const char **values
);
79 static PGresult
*executeQuery(PGconn
*conn
, const char *query
);
80 static void executeCommand(PGconn
*conn
, const char *query
);
81 static void expand_dbname_patterns(PGconn
*conn
, SimpleStringList
*patterns
,
82 SimpleStringList
*names
);
83 static void read_dumpall_filters(const char *filename
, SimpleStringList
*pattern
);
85 static char pg_dump_bin
[MAXPGPATH
];
86 static const char *progname
;
87 static PQExpBuffer pgdumpopts
;
88 static char *connstr
= "";
89 static bool output_clean
= false;
90 static bool skip_acls
= false;
91 static bool verbose
= false;
92 static bool dosync
= true;
94 static int binary_upgrade
= 0;
95 static int column_inserts
= 0;
96 static int disable_dollar_quoting
= 0;
97 static int disable_triggers
= 0;
98 static int if_exists
= 0;
99 static int inserts
= 0;
100 static int no_table_access_method
= 0;
101 static int no_tablespaces
= 0;
102 static int use_setsessauth
= 0;
103 static int no_comments
= 0;
104 static int no_publications
= 0;
105 static int no_security_labels
= 0;
106 static int no_subscriptions
= 0;
107 static int no_toast_compression
= 0;
108 static int no_unlogged_table_data
= 0;
109 static int no_role_passwords
= 0;
110 static int server_version
;
111 static int load_via_partition_root
= 0;
112 static int on_conflict_do_nothing
= 0;
114 static char role_catalog
[10];
115 #define PG_AUTHID "pg_authid"
116 #define PG_ROLES "pg_roles "
119 static char *filename
= NULL
;
121 static SimpleStringList database_exclude_patterns
= {NULL
, NULL
};
122 static SimpleStringList database_exclude_names
= {NULL
, NULL
};
124 #define exit_nicely(code) exit(code)
127 main(int argc
, char *argv
[])
129 static struct option long_options
[] = {
130 {"data-only", no_argument
, NULL
, 'a'},
131 {"clean", no_argument
, NULL
, 'c'},
132 {"encoding", required_argument
, NULL
, 'E'},
133 {"file", required_argument
, NULL
, 'f'},
134 {"globals-only", no_argument
, NULL
, 'g'},
135 {"host", required_argument
, NULL
, 'h'},
136 {"dbname", required_argument
, NULL
, 'd'},
137 {"database", required_argument
, NULL
, 'l'},
138 {"no-owner", no_argument
, NULL
, 'O'},
139 {"port", required_argument
, NULL
, 'p'},
140 {"roles-only", no_argument
, NULL
, 'r'},
141 {"schema-only", no_argument
, NULL
, 's'},
142 {"superuser", required_argument
, NULL
, 'S'},
143 {"tablespaces-only", no_argument
, NULL
, 't'},
144 {"username", required_argument
, NULL
, 'U'},
145 {"verbose", no_argument
, NULL
, 'v'},
146 {"no-password", no_argument
, NULL
, 'w'},
147 {"password", no_argument
, NULL
, 'W'},
148 {"no-privileges", no_argument
, NULL
, 'x'},
149 {"no-acl", no_argument
, NULL
, 'x'},
152 * the following options don't have an equivalent short option letter
154 {"attribute-inserts", no_argument
, &column_inserts
, 1},
155 {"binary-upgrade", no_argument
, &binary_upgrade
, 1},
156 {"column-inserts", no_argument
, &column_inserts
, 1},
157 {"disable-dollar-quoting", no_argument
, &disable_dollar_quoting
, 1},
158 {"disable-triggers", no_argument
, &disable_triggers
, 1},
159 {"exclude-database", required_argument
, NULL
, 6},
160 {"extra-float-digits", required_argument
, NULL
, 5},
161 {"if-exists", no_argument
, &if_exists
, 1},
162 {"inserts", no_argument
, &inserts
, 1},
163 {"lock-wait-timeout", required_argument
, NULL
, 2},
164 {"no-table-access-method", no_argument
, &no_table_access_method
, 1},
165 {"no-tablespaces", no_argument
, &no_tablespaces
, 1},
166 {"quote-all-identifiers", no_argument
, "e_all_identifiers
, 1},
167 {"load-via-partition-root", no_argument
, &load_via_partition_root
, 1},
168 {"role", required_argument
, NULL
, 3},
169 {"use-set-session-authorization", no_argument
, &use_setsessauth
, 1},
170 {"no-comments", no_argument
, &no_comments
, 1},
171 {"no-publications", no_argument
, &no_publications
, 1},
172 {"no-role-passwords", no_argument
, &no_role_passwords
, 1},
173 {"no-security-labels", no_argument
, &no_security_labels
, 1},
174 {"no-subscriptions", no_argument
, &no_subscriptions
, 1},
175 {"no-sync", no_argument
, NULL
, 4},
176 {"no-toast-compression", no_argument
, &no_toast_compression
, 1},
177 {"no-unlogged-table-data", no_argument
, &no_unlogged_table_data
, 1},
178 {"on-conflict-do-nothing", no_argument
, &on_conflict_do_nothing
, 1},
179 {"rows-per-insert", required_argument
, NULL
, 7},
180 {"filter", required_argument
, NULL
, 8},
189 char *use_role
= NULL
;
190 const char *dumpencoding
= NULL
;
191 trivalue prompt_password
= TRI_DEFAULT
;
192 bool data_only
= false;
193 bool globals_only
= false;
194 bool roles_only
= false;
195 bool tablespaces_only
= false;
198 const char *std_strings
;
203 pg_logging_init(argv
[0]);
204 pg_logging_set_level(PG_LOG_WARNING
);
205 set_pglocale_pgservice(argv
[0], PG_TEXTDOMAIN("pg_dump"));
206 progname
= get_progname(argv
[0]);
210 if (strcmp(argv
[1], "--help") == 0 || strcmp(argv
[1], "-?") == 0)
215 if (strcmp(argv
[1], "--version") == 0 || strcmp(argv
[1], "-V") == 0)
217 puts("pg_dumpall (PostgreSQL) " PG_VERSION
);
222 if ((ret
= find_other_exec(argv
[0], "pg_dump", PGDUMP_VERSIONSTR
,
225 char full_path
[MAXPGPATH
];
227 if (find_my_exec(argv
[0], full_path
) < 0)
228 strlcpy(full_path
, progname
, sizeof(full_path
));
231 pg_fatal("program \"%s\" is needed by %s but was not found in the same directory as \"%s\"",
232 "pg_dump", progname
, full_path
);
234 pg_fatal("program \"%s\" was found by \"%s\" but was not the same version as %s",
235 "pg_dump", full_path
, progname
);
238 pgdumpopts
= createPQExpBuffer();
240 while ((c
= getopt_long(argc
, argv
, "acd:E:f:gh:l:Op:rsS:tU:vwWx", long_options
, &optindex
)) != -1)
246 appendPQExpBufferStr(pgdumpopts
, " -a");
254 connstr
= pg_strdup(optarg
);
258 dumpencoding
= pg_strdup(optarg
);
259 appendPQExpBufferStr(pgdumpopts
, " -E ");
260 appendShellString(pgdumpopts
, optarg
);
264 filename
= pg_strdup(optarg
);
265 appendPQExpBufferStr(pgdumpopts
, " -f ");
266 appendShellString(pgdumpopts
, filename
);
274 pghost
= pg_strdup(optarg
);
278 pgdb
= pg_strdup(optarg
);
282 appendPQExpBufferStr(pgdumpopts
, " -O");
286 pgport
= pg_strdup(optarg
);
294 appendPQExpBufferStr(pgdumpopts
, " -s");
298 appendPQExpBufferStr(pgdumpopts
, " -S ");
299 appendShellString(pgdumpopts
, optarg
);
303 tablespaces_only
= true;
307 pguser
= pg_strdup(optarg
);
312 pg_logging_increase_verbosity();
313 appendPQExpBufferStr(pgdumpopts
, " -v");
317 prompt_password
= TRI_NO
;
318 appendPQExpBufferStr(pgdumpopts
, " -w");
322 prompt_password
= TRI_YES
;
323 appendPQExpBufferStr(pgdumpopts
, " -W");
328 appendPQExpBufferStr(pgdumpopts
, " -x");
335 appendPQExpBufferStr(pgdumpopts
, " --lock-wait-timeout ");
336 appendShellString(pgdumpopts
, optarg
);
340 use_role
= pg_strdup(optarg
);
341 appendPQExpBufferStr(pgdumpopts
, " --role ");
342 appendShellString(pgdumpopts
, use_role
);
347 appendPQExpBufferStr(pgdumpopts
, " --no-sync");
351 appendPQExpBufferStr(pgdumpopts
, " --extra-float-digits ");
352 appendShellString(pgdumpopts
, optarg
);
356 simple_string_list_append(&database_exclude_patterns
, optarg
);
360 appendPQExpBufferStr(pgdumpopts
, " --rows-per-insert ");
361 appendShellString(pgdumpopts
, optarg
);
365 read_dumpall_filters(optarg
, &database_exclude_patterns
);
369 /* getopt_long already emitted a complaint */
370 pg_log_error_hint("Try \"%s --help\" for more information.", progname
);
375 /* Complain if any arguments remain */
378 pg_log_error("too many command-line arguments (first is \"%s\")",
380 pg_log_error_hint("Try \"%s --help\" for more information.", progname
);
384 if (database_exclude_patterns
.head
!= NULL
&&
385 (globals_only
|| roles_only
|| tablespaces_only
))
387 pg_log_error("option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only");
388 pg_log_error_hint("Try \"%s --help\" for more information.", progname
);
392 /* Make sure the user hasn't specified a mix of globals-only options */
393 if (globals_only
&& roles_only
)
395 pg_log_error("options -g/--globals-only and -r/--roles-only cannot be used together");
396 pg_log_error_hint("Try \"%s --help\" for more information.", progname
);
400 if (globals_only
&& tablespaces_only
)
402 pg_log_error("options -g/--globals-only and -t/--tablespaces-only cannot be used together");
403 pg_log_error_hint("Try \"%s --help\" for more information.", progname
);
407 if (if_exists
&& !output_clean
)
408 pg_fatal("option --if-exists requires option -c/--clean");
410 if (roles_only
&& tablespaces_only
)
412 pg_log_error("options -r/--roles-only and -t/--tablespaces-only cannot be used together");
413 pg_log_error_hint("Try \"%s --help\" for more information.", progname
);
418 * If password values are not required in the dump, switch to using
419 * pg_roles which is equally useful, just more likely to have unrestricted
420 * access than pg_authid.
422 if (no_role_passwords
)
423 sprintf(role_catalog
, "%s", PG_ROLES
);
425 sprintf(role_catalog
, "%s", PG_AUTHID
);
427 /* Add long options to the pg_dump argument list */
429 appendPQExpBufferStr(pgdumpopts
, " --binary-upgrade");
431 appendPQExpBufferStr(pgdumpopts
, " --column-inserts");
432 if (disable_dollar_quoting
)
433 appendPQExpBufferStr(pgdumpopts
, " --disable-dollar-quoting");
434 if (disable_triggers
)
435 appendPQExpBufferStr(pgdumpopts
, " --disable-triggers");
437 appendPQExpBufferStr(pgdumpopts
, " --inserts");
438 if (no_table_access_method
)
439 appendPQExpBufferStr(pgdumpopts
, " --no-table-access-method");
441 appendPQExpBufferStr(pgdumpopts
, " --no-tablespaces");
442 if (quote_all_identifiers
)
443 appendPQExpBufferStr(pgdumpopts
, " --quote-all-identifiers");
444 if (load_via_partition_root
)
445 appendPQExpBufferStr(pgdumpopts
, " --load-via-partition-root");
447 appendPQExpBufferStr(pgdumpopts
, " --use-set-session-authorization");
449 appendPQExpBufferStr(pgdumpopts
, " --no-comments");
451 appendPQExpBufferStr(pgdumpopts
, " --no-publications");
452 if (no_security_labels
)
453 appendPQExpBufferStr(pgdumpopts
, " --no-security-labels");
454 if (no_subscriptions
)
455 appendPQExpBufferStr(pgdumpopts
, " --no-subscriptions");
456 if (no_toast_compression
)
457 appendPQExpBufferStr(pgdumpopts
, " --no-toast-compression");
458 if (no_unlogged_table_data
)
459 appendPQExpBufferStr(pgdumpopts
, " --no-unlogged-table-data");
460 if (on_conflict_do_nothing
)
461 appendPQExpBufferStr(pgdumpopts
, " --on-conflict-do-nothing");
464 * If there was a database specified on the command line, use that,
465 * otherwise try to connect to database "postgres", and failing that
470 conn
= connectDatabase(pgdb
, connstr
, pghost
, pgport
, pguser
,
471 prompt_password
, false);
474 pg_fatal("could not connect to database \"%s\"", pgdb
);
478 conn
= connectDatabase("postgres", connstr
, pghost
, pgport
, pguser
,
479 prompt_password
, false);
481 conn
= connectDatabase("template1", connstr
, pghost
, pgport
, pguser
,
482 prompt_password
, true);
486 pg_log_error("could not connect to databases \"postgres\" or \"template1\"\n"
487 "Please specify an alternative database.");
488 pg_log_error_hint("Try \"%s --help\" for more information.", progname
);
494 * Get a list of database names that match the exclude patterns
496 expand_dbname_patterns(conn
, &database_exclude_patterns
,
497 &database_exclude_names
);
500 * Open the output file if required, otherwise use stdout
504 OPF
= fopen(filename
, PG_BINARY_W
);
506 pg_fatal("could not open output file \"%s\": %m",
513 * Set the client encoding if requested.
517 if (PQsetClientEncoding(conn
, dumpencoding
) < 0)
518 pg_fatal("invalid client encoding \"%s\" specified",
523 * Get the active encoding and the standard_conforming_strings setting, so
524 * we know how to escape strings.
526 encoding
= PQclientEncoding(conn
);
527 std_strings
= PQparameterStatus(conn
, "standard_conforming_strings");
531 /* Set the role if requested */
534 PQExpBuffer query
= createPQExpBuffer();
536 appendPQExpBuffer(query
, "SET ROLE %s", fmtId(use_role
));
537 executeCommand(conn
, query
->data
);
538 destroyPQExpBuffer(query
);
541 /* Force quoting of all identifiers if requested. */
542 if (quote_all_identifiers
)
543 executeCommand(conn
, "SET quote_all_identifiers = true");
545 fprintf(OPF
, "--\n-- PostgreSQL database cluster dump\n--\n\n");
547 dumpTimestamp("Started on");
550 * We used to emit \connect postgres here, but that served no purpose
551 * other than to break things for installations without a postgres
552 * database. Everything we're restoring here is a global, so whichever
553 * database we're connected to at the moment is fine.
556 /* Restore will need to write to the target cluster */
557 fprintf(OPF
, "SET default_transaction_read_only = off;\n\n");
559 /* Replicate encoding and std_strings in output */
560 fprintf(OPF
, "SET client_encoding = '%s';\n",
561 pg_encoding_to_char(encoding
));
562 fprintf(OPF
, "SET standard_conforming_strings = %s;\n", std_strings
);
563 if (strcmp(std_strings
, "off") == 0)
564 fprintf(OPF
, "SET escape_string_warning = off;\n");
570 * If asked to --clean, do that first. We can avoid detailed
571 * dependency analysis because databases never depend on each other,
572 * and tablespaces never depend on each other. Roles could have
573 * grants to each other, but DROP ROLE will clean those up silently.
577 if (!globals_only
&& !roles_only
&& !tablespaces_only
)
580 if (!roles_only
&& !no_tablespaces
)
581 dropTablespaces(conn
);
583 if (!tablespaces_only
)
588 * Now create objects as requested. Be careful that option logic here
589 * is the same as for drops above.
591 if (!tablespaces_only
)
593 /* Dump roles (users) */
596 /* Dump role memberships */
597 dumpRoleMembership(conn
);
599 /* Dump role GUC privileges */
600 if (server_version
>= 150000 && !skip_acls
)
601 dumpRoleGUCPrivs(conn
);
604 /* Dump tablespaces */
605 if (!roles_only
&& !no_tablespaces
)
606 dumpTablespaces(conn
);
609 if (!globals_only
&& !roles_only
&& !tablespaces_only
)
615 dumpTimestamp("Completed on");
616 fprintf(OPF
, "--\n-- PostgreSQL database cluster dump complete\n--\n\n");
622 /* sync the resulting file, errors are not fatal */
624 (void) fsync_fname(filename
, false);
634 printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname
);
635 printf(_("Usage:\n"));
636 printf(_(" %s [OPTION]...\n"), progname
);
638 printf(_("\nGeneral options:\n"));
639 printf(_(" -f, --file=FILENAME output file name\n"));
640 printf(_(" -v, --verbose verbose mode\n"));
641 printf(_(" -V, --version output version information, then exit\n"));
642 printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
643 printf(_(" -?, --help show this help, then exit\n"));
644 printf(_("\nOptions controlling the output content:\n"));
645 printf(_(" -a, --data-only dump only the data, not the schema\n"));
646 printf(_(" -c, --clean clean (drop) databases before recreating\n"));
647 printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
648 printf(_(" -g, --globals-only dump only global objects, no databases\n"));
649 printf(_(" -O, --no-owner skip restoration of object ownership\n"));
650 printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n"));
651 printf(_(" -s, --schema-only dump only the schema, no data\n"));
652 printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n"));
653 printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n"));
654 printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
655 printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
656 printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
657 printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
658 printf(_(" --disable-triggers disable triggers during data-only restore\n"));
659 printf(_(" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n"));
660 printf(_(" --extra-float-digits=NUM override default setting for extra_float_digits\n"));
661 printf(_(" --filter=FILENAME exclude databases based on expressions in FILENAME\n"));
662 printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
663 printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
664 printf(_(" --load-via-partition-root load partitions via the root table\n"));
665 printf(_(" --no-comments do not dump comment commands\n"));
666 printf(_(" --no-publications do not dump publications\n"));
667 printf(_(" --no-role-passwords do not dump passwords for roles\n"));
668 printf(_(" --no-security-labels do not dump security label assignments\n"));
669 printf(_(" --no-subscriptions do not dump subscriptions\n"));
670 printf(_(" --no-sync do not wait for changes to be written safely to disk\n"));
671 printf(_(" --no-table-access-method do not dump table access methods\n"));
672 printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
673 printf(_(" --no-toast-compression do not dump TOAST compression methods\n"));
674 printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
675 printf(_(" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n"));
676 printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
677 printf(_(" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n"));
678 printf(_(" --use-set-session-authorization\n"
679 " use SET SESSION AUTHORIZATION commands instead of\n"
680 " ALTER OWNER commands to set ownership\n"));
682 printf(_("\nConnection options:\n"));
683 printf(_(" -d, --dbname=CONNSTR connect using connection string\n"));
684 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
685 printf(_(" -l, --database=DBNAME alternative default database\n"));
686 printf(_(" -p, --port=PORT database server port number\n"));
687 printf(_(" -U, --username=NAME connect as specified database user\n"));
688 printf(_(" -w, --no-password never prompt for password\n"));
689 printf(_(" -W, --password force password prompt (should happen automatically)\n"));
690 printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
692 printf(_("\nIf -f/--file is not used, then the SQL script will be written to the standard\n"
694 printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT
);
695 printf(_("%s home page: <%s>\n"), PACKAGE_NAME
, PACKAGE_URL
);
703 dropRoles(PGconn
*conn
)
705 PQExpBuffer buf
= createPQExpBuffer();
710 if (server_version
>= 90600)
711 printfPQExpBuffer(buf
,
714 "WHERE rolname !~ '^pg_' "
715 "ORDER BY 1", role_catalog
);
717 printfPQExpBuffer(buf
,
720 "ORDER BY 1", role_catalog
);
722 res
= executeQuery(conn
, buf
->data
);
724 i_rolname
= PQfnumber(res
, "rolname");
726 if (PQntuples(res
) > 0)
727 fprintf(OPF
, "--\n-- Drop roles\n--\n\n");
729 for (i
= 0; i
< PQntuples(res
); i
++)
731 const char *rolename
;
733 rolename
= PQgetvalue(res
, i
, i_rolname
);
735 fprintf(OPF
, "DROP ROLE %s%s;\n",
736 if_exists
? "IF EXISTS " : "",
741 destroyPQExpBuffer(buf
);
743 fprintf(OPF
, "\n\n");
750 dumpRoles(PGconn
*conn
)
752 PQExpBuffer buf
= createPQExpBuffer();
771 * Notes: rolconfig is dumped later, and pg_authid must be used for
772 * extracting rolcomment regardless of role_catalog.
774 if (server_version
>= 90600)
775 printfPQExpBuffer(buf
,
776 "SELECT oid, rolname, rolsuper, rolinherit, "
777 "rolcreaterole, rolcreatedb, "
778 "rolcanlogin, rolconnlimit, rolpassword, "
779 "rolvaliduntil, rolreplication, rolbypassrls, "
780 "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment, "
781 "rolname = current_user AS is_current_user "
783 "WHERE rolname !~ '^pg_' "
784 "ORDER BY 2", role_catalog
);
785 else if (server_version
>= 90500)
786 printfPQExpBuffer(buf
,
787 "SELECT oid, rolname, rolsuper, rolinherit, "
788 "rolcreaterole, rolcreatedb, "
789 "rolcanlogin, rolconnlimit, rolpassword, "
790 "rolvaliduntil, rolreplication, rolbypassrls, "
791 "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment, "
792 "rolname = current_user AS is_current_user "
794 "ORDER BY 2", role_catalog
);
796 printfPQExpBuffer(buf
,
797 "SELECT oid, rolname, rolsuper, rolinherit, "
798 "rolcreaterole, rolcreatedb, "
799 "rolcanlogin, rolconnlimit, rolpassword, "
800 "rolvaliduntil, rolreplication, "
801 "false as rolbypassrls, "
802 "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment, "
803 "rolname = current_user AS is_current_user "
805 "ORDER BY 2", role_catalog
);
807 res
= executeQuery(conn
, buf
->data
);
809 i_oid
= PQfnumber(res
, "oid");
810 i_rolname
= PQfnumber(res
, "rolname");
811 i_rolsuper
= PQfnumber(res
, "rolsuper");
812 i_rolinherit
= PQfnumber(res
, "rolinherit");
813 i_rolcreaterole
= PQfnumber(res
, "rolcreaterole");
814 i_rolcreatedb
= PQfnumber(res
, "rolcreatedb");
815 i_rolcanlogin
= PQfnumber(res
, "rolcanlogin");
816 i_rolconnlimit
= PQfnumber(res
, "rolconnlimit");
817 i_rolpassword
= PQfnumber(res
, "rolpassword");
818 i_rolvaliduntil
= PQfnumber(res
, "rolvaliduntil");
819 i_rolreplication
= PQfnumber(res
, "rolreplication");
820 i_rolbypassrls
= PQfnumber(res
, "rolbypassrls");
821 i_rolcomment
= PQfnumber(res
, "rolcomment");
822 i_is_current_user
= PQfnumber(res
, "is_current_user");
824 if (PQntuples(res
) > 0)
825 fprintf(OPF
, "--\n-- Roles\n--\n\n");
827 for (i
= 0; i
< PQntuples(res
); i
++)
829 const char *rolename
;
832 auth_oid
= atooid(PQgetvalue(res
, i
, i_oid
));
833 rolename
= PQgetvalue(res
, i
, i_rolname
);
835 if (strncmp(rolename
, "pg_", 3) == 0)
837 pg_log_warning("role name starting with \"pg_\" skipped (%s)",
842 resetPQExpBuffer(buf
);
846 appendPQExpBufferStr(buf
, "\n-- For binary upgrade, must preserve pg_authid.oid\n");
847 appendPQExpBuffer(buf
,
848 "SELECT pg_catalog.binary_upgrade_set_next_pg_authid_oid('%u'::pg_catalog.oid);\n\n",
853 * We dump CREATE ROLE followed by ALTER ROLE to ensure that the role
854 * will acquire the right properties even if it already exists (ie, it
855 * won't hurt for the CREATE to fail). This is particularly important
856 * for the role we are connected as, since even with --clean we will
857 * have failed to drop it. binary_upgrade cannot generate any errors,
858 * so we assume the current role is already created.
860 if (!binary_upgrade
||
861 strcmp(PQgetvalue(res
, i
, i_is_current_user
), "f") == 0)
862 appendPQExpBuffer(buf
, "CREATE ROLE %s;\n", fmtId(rolename
));
863 appendPQExpBuffer(buf
, "ALTER ROLE %s WITH", fmtId(rolename
));
865 if (strcmp(PQgetvalue(res
, i
, i_rolsuper
), "t") == 0)
866 appendPQExpBufferStr(buf
, " SUPERUSER");
868 appendPQExpBufferStr(buf
, " NOSUPERUSER");
870 if (strcmp(PQgetvalue(res
, i
, i_rolinherit
), "t") == 0)
871 appendPQExpBufferStr(buf
, " INHERIT");
873 appendPQExpBufferStr(buf
, " NOINHERIT");
875 if (strcmp(PQgetvalue(res
, i
, i_rolcreaterole
), "t") == 0)
876 appendPQExpBufferStr(buf
, " CREATEROLE");
878 appendPQExpBufferStr(buf
, " NOCREATEROLE");
880 if (strcmp(PQgetvalue(res
, i
, i_rolcreatedb
), "t") == 0)
881 appendPQExpBufferStr(buf
, " CREATEDB");
883 appendPQExpBufferStr(buf
, " NOCREATEDB");
885 if (strcmp(PQgetvalue(res
, i
, i_rolcanlogin
), "t") == 0)
886 appendPQExpBufferStr(buf
, " LOGIN");
888 appendPQExpBufferStr(buf
, " NOLOGIN");
890 if (strcmp(PQgetvalue(res
, i
, i_rolreplication
), "t") == 0)
891 appendPQExpBufferStr(buf
, " REPLICATION");
893 appendPQExpBufferStr(buf
, " NOREPLICATION");
895 if (strcmp(PQgetvalue(res
, i
, i_rolbypassrls
), "t") == 0)
896 appendPQExpBufferStr(buf
, " BYPASSRLS");
898 appendPQExpBufferStr(buf
, " NOBYPASSRLS");
900 if (strcmp(PQgetvalue(res
, i
, i_rolconnlimit
), "-1") != 0)
901 appendPQExpBuffer(buf
, " CONNECTION LIMIT %s",
902 PQgetvalue(res
, i
, i_rolconnlimit
));
905 if (!PQgetisnull(res
, i
, i_rolpassword
) && !no_role_passwords
)
907 appendPQExpBufferStr(buf
, " PASSWORD ");
908 appendStringLiteralConn(buf
, PQgetvalue(res
, i
, i_rolpassword
), conn
);
911 if (!PQgetisnull(res
, i
, i_rolvaliduntil
))
912 appendPQExpBuffer(buf
, " VALID UNTIL '%s'",
913 PQgetvalue(res
, i
, i_rolvaliduntil
));
915 appendPQExpBufferStr(buf
, ";\n");
917 if (!no_comments
&& !PQgetisnull(res
, i
, i_rolcomment
))
919 appendPQExpBuffer(buf
, "COMMENT ON ROLE %s IS ", fmtId(rolename
));
920 appendStringLiteralConn(buf
, PQgetvalue(res
, i
, i_rolcomment
), conn
);
921 appendPQExpBufferStr(buf
, ";\n");
924 if (!no_security_labels
)
925 buildShSecLabels(conn
, "pg_authid", auth_oid
,
929 fprintf(OPF
, "%s", buf
->data
);
933 * Dump configuration settings for roles after all roles have been dumped.
934 * We do it this way because config settings for roles could mention the
935 * names of other roles.
937 if (PQntuples(res
) > 0)
938 fprintf(OPF
, "\n--\n-- User Configurations\n--\n");
940 for (i
= 0; i
< PQntuples(res
); i
++)
941 dumpUserConfig(conn
, PQgetvalue(res
, i
, i_rolname
));
945 fprintf(OPF
, "\n\n");
947 destroyPQExpBuffer(buf
);
952 * Dump role memberships.
954 * Note: we expect dumpRoles already created all the roles, but there is
958 dumpRoleMembership(PGconn
*conn
)
960 PQExpBuffer buf
= createPQExpBuffer();
961 PQExpBuffer optbuf
= createPQExpBuffer();
967 bool dump_grant_options
;
968 int i_inherit_option
;
972 * Previous versions of PostgreSQL didn't used to track the grantor very
973 * carefully in the backend, and the grantor could be any user even if
974 * they didn't have ADMIN OPTION on the role, or a user that no longer
975 * existed. To avoid dump and restore failures, don't dump the grantor
976 * when talking to an old server version.
978 dump_grantors
= (PQserverVersion(conn
) >= 160000);
981 * Previous versions of PostgreSQL also did not have grant-level options.
983 dump_grant_options
= (server_version
>= 160000);
985 /* Generate and execute query. */
986 printfPQExpBuffer(buf
, "SELECT ur.rolname AS role, "
987 "um.rolname AS member, "
988 "ug.oid AS grantorid, "
989 "ug.rolname AS grantor, "
991 if (dump_grant_options
)
992 appendPQExpBufferStr(buf
, ", a.inherit_option, a.set_option");
993 appendPQExpBuffer(buf
, " FROM pg_auth_members a "
994 "LEFT JOIN %s ur on ur.oid = a.roleid "
995 "LEFT JOIN %s um on um.oid = a.member "
996 "LEFT JOIN %s ug on ug.oid = a.grantor "
997 "WHERE NOT (ur.rolname ~ '^pg_' AND um.rolname ~ '^pg_')"
998 "ORDER BY 1,2,4", role_catalog
, role_catalog
, role_catalog
);
999 res
= executeQuery(conn
, buf
->data
);
1000 i_inherit_option
= PQfnumber(res
, "inherit_option");
1001 i_set_option
= PQfnumber(res
, "set_option");
1003 if (PQntuples(res
) > 0)
1004 fprintf(OPF
, "--\n-- Role memberships\n--\n\n");
1007 * We can't dump these GRANT commands in arbitrary order, because a role
1008 * that is named as a grantor must already have ADMIN OPTION on the role
1009 * for which it is granting permissions, except for the bootstrap
1010 * superuser, who can always be named as the grantor.
1012 * We handle this by considering these grants role by role. For each role,
1013 * we initially consider the only allowable grantor to be the bootstrap
1014 * superuser. Every time we grant ADMIN OPTION on the role to some user,
1015 * that user also becomes an allowable grantor. We make repeated passes
1016 * over the grants for the role, each time dumping those whose grantors
1017 * are allowable and which we haven't done yet. Eventually this should let
1018 * us dump all the grants.
1020 total
= PQntuples(res
);
1021 while (start
< total
)
1023 char *role
= PQgetvalue(res
, start
, 0);
1027 int prev_remaining
= 0;
1030 /* All memberships for a single role should be adjacent. */
1031 for (end
= start
; end
< total
; ++end
)
1035 otherrole
= PQgetvalue(res
, end
, 0);
1036 if (strcmp(role
, otherrole
) != 0)
1040 role
= PQgetvalue(res
, start
, 0);
1041 remaining
= end
- start
;
1042 done
= pg_malloc0(remaining
* sizeof(bool));
1043 ht
= rolename_create(remaining
, NULL
);
1046 * Make repeated passes over the grants for this role until all have
1049 while (remaining
> 0)
1052 * We should make progress on every iteration, because a notional
1053 * graph whose vertices are grants and whose edges point from
1054 * grantors to members should be connected and acyclic. If we fail
1055 * to make progress, either we or the server have messed up.
1057 if (remaining
== prev_remaining
)
1059 pg_log_error("could not find a legal dump ordering for memberships in role \"%s\"",
1064 prev_remaining
= remaining
;
1066 /* Make one pass over the grants for this role. */
1067 for (i
= start
; i
< end
; ++i
)
1073 char *set_option
= "true";
1076 /* If we already did this grant, don't do it again. */
1077 if (done
[i
- start
])
1080 member
= PQgetvalue(res
, i
, 1);
1081 grantorid
= PQgetvalue(res
, i
, 2);
1082 grantor
= PQgetvalue(res
, i
, 3);
1083 admin_option
= PQgetvalue(res
, i
, 4);
1084 if (dump_grant_options
)
1085 set_option
= PQgetvalue(res
, i
, i_set_option
);
1088 * If we're not dumping grantors or if the grantor is the
1089 * bootstrap superuser, it's fine to dump this now. Otherwise,
1090 * it's got to be someone who has already been granted ADMIN
1093 if (dump_grantors
&&
1094 atooid(grantorid
) != BOOTSTRAP_SUPERUSERID
&&
1095 rolename_lookup(ht
, grantor
) == NULL
)
1098 /* Remember that we did this so that we don't do it again. */
1099 done
[i
- start
] = true;
1103 * If ADMIN OPTION is being granted, remember that grants
1104 * listing this member as the grantor can now be dumped.
1106 if (*admin_option
== 't')
1107 rolename_insert(ht
, member
, &found
);
1109 /* Generate the actual GRANT statement. */
1110 resetPQExpBuffer(optbuf
);
1111 fprintf(OPF
, "GRANT %s", fmtId(role
));
1112 fprintf(OPF
, " TO %s", fmtId(member
));
1113 if (*admin_option
== 't')
1114 appendPQExpBufferStr(optbuf
, "ADMIN OPTION");
1115 if (dump_grant_options
)
1117 char *inherit_option
;
1119 if (optbuf
->data
[0] != '\0')
1120 appendPQExpBufferStr(optbuf
, ", ");
1121 inherit_option
= PQgetvalue(res
, i
, i_inherit_option
);
1122 appendPQExpBuffer(optbuf
, "INHERIT %s",
1123 *inherit_option
== 't' ?
1126 if (*set_option
!= 't')
1128 if (optbuf
->data
[0] != '\0')
1129 appendPQExpBufferStr(optbuf
, ", ");
1130 appendPQExpBuffer(optbuf
, "SET FALSE");
1132 if (optbuf
->data
[0] != '\0')
1133 fprintf(OPF
, " WITH %s", optbuf
->data
);
1135 fprintf(OPF
, " GRANTED BY %s", fmtId(grantor
));
1136 fprintf(OPF
, ";\n");
1140 rolename_destroy(ht
);
1146 destroyPQExpBuffer(buf
);
1148 fprintf(OPF
, "\n\n");
1153 * Dump role configuration parameter privileges. This code is used for 15.0
1154 * and later servers.
1156 * Note: we expect dumpRoles already created all the roles, but there are
1157 * no per-role configuration parameter privileges yet.
1160 dumpRoleGUCPrivs(PGconn
*conn
)
1166 * Get all parameters that have non-default acls defined.
1168 res
= executeQuery(conn
, "SELECT parname, "
1169 "pg_catalog.pg_get_userbyid(" CppAsString2(BOOTSTRAP_SUPERUSERID
) ") AS parowner, "
1171 "pg_catalog.acldefault('p', " CppAsString2(BOOTSTRAP_SUPERUSERID
) ") AS acldefault "
1172 "FROM pg_catalog.pg_parameter_acl "
1175 if (PQntuples(res
) > 0)
1176 fprintf(OPF
, "--\n-- Role privileges on configuration parameters\n--\n\n");
1178 for (i
= 0; i
< PQntuples(res
); i
++)
1180 PQExpBuffer buf
= createPQExpBuffer();
1181 char *parname
= PQgetvalue(res
, i
, 0);
1182 char *parowner
= PQgetvalue(res
, i
, 1);
1183 char *paracl
= PQgetvalue(res
, i
, 2);
1184 char *acldefault
= PQgetvalue(res
, i
, 3);
1187 /* needed for buildACLCommands() */
1188 fparname
= pg_strdup(fmtId(parname
));
1190 if (!buildACLCommands(fparname
, NULL
, NULL
, "PARAMETER",
1192 parowner
, "", server_version
, buf
))
1194 pg_log_error("could not parse ACL list (%s) for parameter \"%s\"",
1200 fprintf(OPF
, "%s", buf
->data
);
1203 destroyPQExpBuffer(buf
);
1207 fprintf(OPF
, "\n\n");
1215 dropTablespaces(PGconn
*conn
)
1221 * Get all tablespaces except built-in ones (which we assume are named
1224 res
= executeQuery(conn
, "SELECT spcname "
1225 "FROM pg_catalog.pg_tablespace "
1226 "WHERE spcname !~ '^pg_' "
1229 if (PQntuples(res
) > 0)
1230 fprintf(OPF
, "--\n-- Drop tablespaces\n--\n\n");
1232 for (i
= 0; i
< PQntuples(res
); i
++)
1234 char *spcname
= PQgetvalue(res
, i
, 0);
1236 fprintf(OPF
, "DROP TABLESPACE %s%s;\n",
1237 if_exists
? "IF EXISTS " : "",
1243 fprintf(OPF
, "\n\n");
1250 dumpTablespaces(PGconn
*conn
)
1256 * Get all tablespaces except built-in ones (which we assume are named
1259 res
= executeQuery(conn
, "SELECT oid, spcname, "
1260 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
1261 "pg_catalog.pg_tablespace_location(oid), "
1262 "spcacl, acldefault('t', spcowner) AS acldefault, "
1263 "array_to_string(spcoptions, ', '),"
1264 "pg_catalog.shobj_description(oid, 'pg_tablespace') "
1265 "FROM pg_catalog.pg_tablespace "
1266 "WHERE spcname !~ '^pg_' "
1269 if (PQntuples(res
) > 0)
1270 fprintf(OPF
, "--\n-- Tablespaces\n--\n\n");
1272 for (i
= 0; i
< PQntuples(res
); i
++)
1274 PQExpBuffer buf
= createPQExpBuffer();
1275 Oid spcoid
= atooid(PQgetvalue(res
, i
, 0));
1276 char *spcname
= PQgetvalue(res
, i
, 1);
1277 char *spcowner
= PQgetvalue(res
, i
, 2);
1278 char *spclocation
= PQgetvalue(res
, i
, 3);
1279 char *spcacl
= PQgetvalue(res
, i
, 4);
1280 char *acldefault
= PQgetvalue(res
, i
, 5);
1281 char *spcoptions
= PQgetvalue(res
, i
, 6);
1282 char *spccomment
= PQgetvalue(res
, i
, 7);
1285 /* needed for buildACLCommands() */
1286 fspcname
= pg_strdup(fmtId(spcname
));
1290 appendPQExpBufferStr(buf
, "\n-- For binary upgrade, must preserve pg_tablespace oid\n");
1291 appendPQExpBuffer(buf
, "SELECT pg_catalog.binary_upgrade_set_next_pg_tablespace_oid('%u'::pg_catalog.oid);\n", spcoid
);
1294 appendPQExpBuffer(buf
, "CREATE TABLESPACE %s", fspcname
);
1295 appendPQExpBuffer(buf
, " OWNER %s", fmtId(spcowner
));
1297 appendPQExpBufferStr(buf
, " LOCATION ");
1300 * In-place tablespaces use a relative path, and need to be dumped
1301 * with an empty string as location.
1303 if (is_absolute_path(spclocation
))
1304 appendStringLiteralConn(buf
, spclocation
, conn
);
1306 appendStringLiteralConn(buf
, "", conn
);
1308 appendPQExpBufferStr(buf
, ";\n");
1310 if (spcoptions
&& spcoptions
[0] != '\0')
1311 appendPQExpBuffer(buf
, "ALTER TABLESPACE %s SET (%s);\n",
1312 fspcname
, spcoptions
);
1314 /* tablespaces can't have initprivs */
1317 !buildACLCommands(fspcname
, NULL
, NULL
, "TABLESPACE",
1319 spcowner
, "", server_version
, buf
))
1321 pg_log_error("could not parse ACL list (%s) for tablespace \"%s\"",
1327 if (!no_comments
&& spccomment
&& spccomment
[0] != '\0')
1329 appendPQExpBuffer(buf
, "COMMENT ON TABLESPACE %s IS ", fspcname
);
1330 appendStringLiteralConn(buf
, spccomment
, conn
);
1331 appendPQExpBufferStr(buf
, ";\n");
1334 if (!no_security_labels
)
1335 buildShSecLabels(conn
, "pg_tablespace", spcoid
,
1336 "TABLESPACE", spcname
,
1339 fprintf(OPF
, "%s", buf
->data
);
1342 destroyPQExpBuffer(buf
);
1346 fprintf(OPF
, "\n\n");
1351 * Dump commands to drop each database.
1354 dropDBs(PGconn
*conn
)
1360 * Skip databases marked not datallowconn, since we'd be unable to connect
1361 * to them anyway. This must agree with dumpDatabases().
1363 res
= executeQuery(conn
,
1365 "FROM pg_database d "
1366 "WHERE datallowconn AND datconnlimit != -2 "
1367 "ORDER BY datname");
1369 if (PQntuples(res
) > 0)
1370 fprintf(OPF
, "--\n-- Drop databases (except postgres and template1)\n--\n\n");
1372 for (i
= 0; i
< PQntuples(res
); i
++)
1374 char *dbname
= PQgetvalue(res
, i
, 0);
1377 * Skip "postgres" and "template1"; dumpDatabases() will deal with
1378 * them specially. Also, be sure to skip "template0", even if for
1379 * some reason it's not marked !datallowconn.
1381 if (strcmp(dbname
, "template1") != 0 &&
1382 strcmp(dbname
, "template0") != 0 &&
1383 strcmp(dbname
, "postgres") != 0)
1385 fprintf(OPF
, "DROP DATABASE %s%s;\n",
1386 if_exists
? "IF EXISTS " : "",
1393 fprintf(OPF
, "\n\n");
1398 * Dump user-specific configuration
1401 dumpUserConfig(PGconn
*conn
, const char *username
)
1403 PQExpBuffer buf
= createPQExpBuffer();
1406 printfPQExpBuffer(buf
, "SELECT unnest(setconfig) FROM pg_db_role_setting "
1407 "WHERE setdatabase = 0 AND setrole = "
1408 "(SELECT oid FROM %s WHERE rolname = ",
1410 appendStringLiteralConn(buf
, username
, conn
);
1411 appendPQExpBufferChar(buf
, ')');
1413 res
= executeQuery(conn
, buf
->data
);
1415 if (PQntuples(res
) > 0)
1416 fprintf(OPF
, "\n--\n-- User Config \"%s\"\n--\n\n", username
);
1418 for (int i
= 0; i
< PQntuples(res
); i
++)
1420 resetPQExpBuffer(buf
);
1421 makeAlterConfigCommand(conn
, PQgetvalue(res
, i
, 0),
1422 "ROLE", username
, NULL
, NULL
,
1424 fprintf(OPF
, "%s", buf
->data
);
1429 destroyPQExpBuffer(buf
);
1433 * Find a list of database names that match the given patterns.
1434 * See also expand_table_name_patterns() in pg_dump.c
1437 expand_dbname_patterns(PGconn
*conn
,
1438 SimpleStringList
*patterns
,
1439 SimpleStringList
*names
)
1444 if (patterns
->head
== NULL
)
1445 return; /* nothing to do */
1447 query
= createPQExpBuffer();
1450 * The loop below runs multiple SELECTs, which might sometimes result in
1451 * duplicate entries in the name list, but we don't care, since all we're
1452 * going to do is test membership of the list.
1455 for (SimpleStringListCell
*cell
= patterns
->head
; cell
; cell
= cell
->next
)
1459 appendPQExpBufferStr(query
,
1460 "SELECT datname FROM pg_catalog.pg_database n\n");
1461 processSQLNamePattern(conn
, query
, cell
->val
, false,
1462 false, NULL
, "datname", NULL
, NULL
, NULL
,
1467 pg_log_error("improper qualified name (too many dotted names): %s",
1473 res
= executeQuery(conn
, query
->data
);
1474 for (int i
= 0; i
< PQntuples(res
); i
++)
1476 simple_string_list_append(names
, PQgetvalue(res
, i
, 0));
1480 resetPQExpBuffer(query
);
1483 destroyPQExpBuffer(query
);
1487 * Dump contents of databases.
1490 dumpDatabases(PGconn
*conn
)
1496 * Skip databases marked not datallowconn, since we'd be unable to connect
1497 * to them anyway. This must agree with dropDBs().
1499 * We arrange for template1 to be processed first, then we process other
1500 * DBs in alphabetical order. If we just did them all alphabetically, we
1501 * might find ourselves trying to drop the "postgres" database while still
1502 * connected to it. This makes trying to run the restore script while
1503 * connected to "template1" a bad idea, but there's no fixed order that
1504 * doesn't have some failure mode with --clean.
1506 res
= executeQuery(conn
,
1508 "FROM pg_database d "
1509 "WHERE datallowconn AND datconnlimit != -2 "
1510 "ORDER BY (datname <> 'template1'), datname");
1512 if (PQntuples(res
) > 0)
1513 fprintf(OPF
, "--\n-- Databases\n--\n\n");
1515 for (i
= 0; i
< PQntuples(res
); i
++)
1517 char *dbname
= PQgetvalue(res
, i
, 0);
1518 const char *create_opts
;
1521 /* Skip template0, even if it's not marked !datallowconn. */
1522 if (strcmp(dbname
, "template0") == 0)
1525 /* Skip any explicitly excluded database */
1526 if (simple_string_list_member(&database_exclude_names
, dbname
))
1528 pg_log_info("excluding database \"%s\"", dbname
);
1532 pg_log_info("dumping database \"%s\"", dbname
);
1534 fprintf(OPF
, "--\n-- Database \"%s\" dump\n--\n\n", dbname
);
1537 * We assume that "template1" and "postgres" already exist in the
1538 * target installation. dropDBs() won't have removed them, for fear
1539 * of removing the DB the restore script is initially connected to. If
1540 * --clean was specified, tell pg_dump to drop and recreate them;
1541 * otherwise we'll merely restore their contents. Other databases
1542 * should simply be created.
1544 if (strcmp(dbname
, "template1") == 0 || strcmp(dbname
, "postgres") == 0)
1547 create_opts
= "--clean --create";
1551 /* Since pg_dump won't emit a \connect command, we must */
1552 fprintf(OPF
, "\\connect %s\n\n", dbname
);
1556 create_opts
= "--create";
1561 ret
= runPgDump(dbname
, create_opts
);
1563 pg_fatal("pg_dump failed on database \"%s\", exiting", dbname
);
1567 OPF
= fopen(filename
, PG_BINARY_A
);
1569 pg_fatal("could not re-open the output file \"%s\": %m",
1580 * Run pg_dump on dbname, with specified options.
1583 runPgDump(const char *dbname
, const char *create_opts
)
1585 PQExpBufferData connstrbuf
;
1586 PQExpBufferData cmd
;
1589 initPQExpBuffer(&connstrbuf
);
1590 initPQExpBuffer(&cmd
);
1592 printfPQExpBuffer(&cmd
, "\"%s\" %s %s", pg_dump_bin
,
1593 pgdumpopts
->data
, create_opts
);
1596 * If we have a filename, use the undocumented plain-append pg_dump
1600 appendPQExpBufferStr(&cmd
, " -Fa ");
1602 appendPQExpBufferStr(&cmd
, " -Fp ");
1605 * Append the database name to the already-constructed stem of connection
1608 appendPQExpBuffer(&connstrbuf
, "%s dbname=", connstr
);
1609 appendConnStrVal(&connstrbuf
, dbname
);
1611 appendShellString(&cmd
, connstrbuf
.data
);
1613 pg_log_info("running \"%s\"", cmd
.data
);
1617 ret
= system(cmd
.data
);
1619 termPQExpBuffer(&cmd
);
1620 termPQExpBuffer(&connstrbuf
);
1628 * Build SECURITY LABEL command(s) for a shared object
1630 * The caller has to provide object type and identity in two separate formats:
1631 * catalog_name (e.g., "pg_database") and object OID, as well as
1632 * type name (e.g., "DATABASE") and object name (not pre-quoted).
1634 * The command(s) are appended to "buffer".
1637 buildShSecLabels(PGconn
*conn
, const char *catalog_name
, Oid objectId
,
1638 const char *objtype
, const char *objname
,
1641 PQExpBuffer sql
= createPQExpBuffer();
1644 buildShSecLabelQuery(catalog_name
, objectId
, sql
);
1645 res
= executeQuery(conn
, sql
->data
);
1646 emitShSecLabels(conn
, res
, buffer
, objtype
, objname
);
1649 destroyPQExpBuffer(sql
);
1653 * Make a database connection with the given parameters. An
1654 * interactive password prompt is automatically issued if required.
1656 * If fail_on_error is false, we return NULL without printing any message
1657 * on failure, but preserve any prompted password for the next try.
1659 * On success, the global variable 'connstr' is set to a connection string
1660 * containing the options used.
1663 connectDatabase(const char *dbname
, const char *connection_string
,
1664 const char *pghost
, const char *pgport
, const char *pguser
,
1665 trivalue prompt_password
, bool fail_on_error
)
1669 const char *remoteversion_str
;
1671 const char **keywords
= NULL
;
1672 const char **values
= NULL
;
1673 PQconninfoOption
*conn_opts
= NULL
;
1674 static char *password
= NULL
;
1676 if (prompt_password
== TRI_YES
&& !password
)
1677 password
= simple_prompt("Password: ", false);
1680 * Start the connection. Loop until we have a password if requested by
1686 PQconninfoOption
*conn_opt
;
1687 char *err_msg
= NULL
;
1692 PQconninfoFree(conn_opts
);
1695 * Merge the connection info inputs given in form of connection string
1696 * and other options. Explicitly discard any dbname value in the
1697 * connection string; otherwise, PQconnectdbParams() would interpret
1698 * that value as being itself a connection string.
1700 if (connection_string
)
1702 conn_opts
= PQconninfoParse(connection_string
, &err_msg
);
1703 if (conn_opts
== NULL
)
1704 pg_fatal("%s", err_msg
);
1706 for (conn_opt
= conn_opts
; conn_opt
->keyword
!= NULL
; conn_opt
++)
1708 if (conn_opt
->val
!= NULL
&& conn_opt
->val
[0] != '\0' &&
1709 strcmp(conn_opt
->keyword
, "dbname") != 0)
1713 keywords
= pg_malloc0((argcount
+ 1) * sizeof(*keywords
));
1714 values
= pg_malloc0((argcount
+ 1) * sizeof(*values
));
1716 for (conn_opt
= conn_opts
; conn_opt
->keyword
!= NULL
; conn_opt
++)
1718 if (conn_opt
->val
!= NULL
&& conn_opt
->val
[0] != '\0' &&
1719 strcmp(conn_opt
->keyword
, "dbname") != 0)
1721 keywords
[i
] = conn_opt
->keyword
;
1722 values
[i
] = conn_opt
->val
;
1729 keywords
= pg_malloc0((argcount
+ 1) * sizeof(*keywords
));
1730 values
= pg_malloc0((argcount
+ 1) * sizeof(*values
));
1735 keywords
[i
] = "host";
1741 keywords
[i
] = "port";
1747 keywords
[i
] = "user";
1753 keywords
[i
] = "password";
1754 values
[i
] = password
;
1759 keywords
[i
] = "dbname";
1763 keywords
[i
] = "fallback_application_name";
1764 values
[i
] = progname
;
1768 conn
= PQconnectdbParams(keywords
, values
, true);
1771 pg_fatal("could not connect to database \"%s\"", dbname
);
1773 if (PQstatus(conn
) == CONNECTION_BAD
&&
1774 PQconnectionNeedsPassword(conn
) &&
1776 prompt_password
!= TRI_NO
)
1779 password
= simple_prompt("Password: ", false);
1784 /* check to see that the backend connection was successfully made */
1785 if (PQstatus(conn
) == CONNECTION_BAD
)
1788 pg_fatal("%s", PQerrorMessage(conn
));
1795 PQconninfoFree(conn_opts
);
1802 * Ok, connected successfully. Remember the options used, in the form of a
1803 * connection string.
1805 connstr
= constructConnStr(keywords
, values
);
1809 PQconninfoFree(conn_opts
);
1812 remoteversion_str
= PQparameterStatus(conn
, "server_version");
1813 if (!remoteversion_str
)
1814 pg_fatal("could not get server version");
1815 server_version
= PQserverVersion(conn
);
1816 if (server_version
== 0)
1817 pg_fatal("could not parse server version \"%s\"",
1820 my_version
= PG_VERSION_NUM
;
1823 * We allow the server to be back to 9.2, and up to any minor release of
1824 * our own major version. (See also version check in pg_dump.c.)
1826 if (my_version
!= server_version
1827 && (server_version
< 90200 ||
1828 (server_version
/ 100) > (my_version
/ 100)))
1830 pg_log_error("aborting because of server version mismatch");
1831 pg_log_error_detail("server version: %s; %s version: %s",
1832 remoteversion_str
, progname
, PG_VERSION
);
1836 PQclear(executeQuery(conn
, ALWAYS_SECURE_SEARCH_PATH_SQL
));
1842 * Construct a connection string from the given keyword/value pairs. It is
1843 * used to pass the connection options to the pg_dump subprocess.
1845 * The following parameters are excluded:
1846 * dbname - varies in each pg_dump invocation
1847 * password - it's not secure to pass a password on the command line
1848 * fallback_application_name - we'll let pg_dump set it
1852 constructConnStr(const char **keywords
, const char **values
)
1854 PQExpBuffer buf
= createPQExpBuffer();
1857 bool firstkeyword
= true;
1859 /* Construct a new connection string in key='value' format. */
1860 for (i
= 0; keywords
[i
] != NULL
; i
++)
1862 if (strcmp(keywords
[i
], "dbname") == 0 ||
1863 strcmp(keywords
[i
], "password") == 0 ||
1864 strcmp(keywords
[i
], "fallback_application_name") == 0)
1868 appendPQExpBufferChar(buf
, ' ');
1869 firstkeyword
= false;
1870 appendPQExpBuffer(buf
, "%s=", keywords
[i
]);
1871 appendConnStrVal(buf
, values
[i
]);
1874 connstr
= pg_strdup(buf
->data
);
1875 destroyPQExpBuffer(buf
);
1880 * Run a query, return the results, exit program on failure.
1883 executeQuery(PGconn
*conn
, const char *query
)
1887 pg_log_info("executing %s", query
);
1889 res
= PQexec(conn
, query
);
1891 PQresultStatus(res
) != PGRES_TUPLES_OK
)
1893 pg_log_error("query failed: %s", PQerrorMessage(conn
));
1894 pg_log_error_detail("Query was: %s", query
);
1903 * As above for a SQL command (which returns nothing).
1906 executeCommand(PGconn
*conn
, const char *query
)
1910 pg_log_info("executing %s", query
);
1912 res
= PQexec(conn
, query
);
1914 PQresultStatus(res
) != PGRES_COMMAND_OK
)
1916 pg_log_error("query failed: %s", PQerrorMessage(conn
));
1917 pg_log_error_detail("Query was: %s", query
);
1930 dumpTimestamp(const char *msg
)
1933 time_t now
= time(NULL
);
1935 if (strftime(buf
, sizeof(buf
), PGDUMP_STRFTIME_FMT
, localtime(&now
)) != 0)
1936 fprintf(OPF
, "-- %s %s\n\n", msg
, buf
);
1940 * read_dumpall_filters - retrieve database identifier patterns from file
1942 * Parse the specified filter file for include and exclude patterns, and add
1943 * them to the relevant lists. If the filename is "-" then filters will be
1944 * read from STDIN rather than a file.
1946 * At the moment, the only allowed filter is for database exclusion.
1949 read_dumpall_filters(const char *filename
, SimpleStringList
*pattern
)
1951 FilterStateData fstate
;
1953 FilterCommandType comtype
;
1954 FilterObjectType objtype
;
1956 filter_init(&fstate
, filename
, exit
);
1958 while (filter_read_item(&fstate
, &objname
, &comtype
, &objtype
))
1960 if (comtype
== FILTER_COMMAND_TYPE_INCLUDE
)
1962 pg_log_filter_error(&fstate
, _("%s filter for \"%s\" is not allowed"),
1964 filter_object_type_name(objtype
));
1970 case FILTER_OBJECT_TYPE_NONE
:
1972 case FILTER_OBJECT_TYPE_FUNCTION
:
1973 case FILTER_OBJECT_TYPE_INDEX
:
1974 case FILTER_OBJECT_TYPE_TABLE_DATA
:
1975 case FILTER_OBJECT_TYPE_TABLE_DATA_AND_CHILDREN
:
1976 case FILTER_OBJECT_TYPE_TRIGGER
:
1977 case FILTER_OBJECT_TYPE_EXTENSION
:
1978 case FILTER_OBJECT_TYPE_FOREIGN_DATA
:
1979 case FILTER_OBJECT_TYPE_SCHEMA
:
1980 case FILTER_OBJECT_TYPE_TABLE
:
1981 case FILTER_OBJECT_TYPE_TABLE_AND_CHILDREN
:
1982 pg_log_filter_error(&fstate
, _("unsupported filter object"));
1986 case FILTER_OBJECT_TYPE_DATABASE
:
1987 simple_string_list_append(pattern
, objname
);
1995 filter_free(&fstate
);