Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pg_dumpall.c
4 : *
5 : * Portions Copyright (c) 1996-2023, 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_utils.h"
24 : #include "common/hashfn.h"
25 : #include "common/logging.h"
26 : #include "common/string.h"
27 : #include "dumputils.h"
28 : #include "fe_utils/string_utils.h"
29 : #include "getopt_long.h"
30 : #include "pg_backup.h"
31 :
32 : /* version string we expect back from pg_dump */
33 : #define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
34 :
35 : static uint32 hash_string_pointer(char *s);
36 :
37 : typedef struct
38 : {
39 : uint32 status;
40 : uint32 hashval;
41 : char *rolename;
42 : } RoleNameEntry;
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_pointer(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 :
58 : static void help(void);
59 :
60 : static void dropRoles(PGconn *conn);
61 : static void dumpRoles(PGconn *conn);
62 : static void dumpRoleMembership(PGconn *conn);
63 : static void dumpRoleGUCPrivs(PGconn *conn);
64 : static void dropTablespaces(PGconn *conn);
65 : static void dumpTablespaces(PGconn *conn);
66 : static void dropDBs(PGconn *conn);
67 : static void dumpUserConfig(PGconn *conn, const char *username);
68 : static void dumpDatabases(PGconn *conn);
69 : static void dumpTimestamp(const char *msg);
70 : static int runPgDump(const char *dbname, const char *create_opts);
71 : static void buildShSecLabels(PGconn *conn,
72 : const char *catalog_name, Oid objectId,
73 : const char *objtype, const char *objname,
74 : PQExpBuffer buffer);
75 : static PGconn *connectDatabase(const char *dbname,
76 : const char *connection_string, const char *pghost,
77 : const char *pgport, const char *pguser,
78 : trivalue prompt_password, bool fail_on_error);
79 : static char *constructConnStr(const char **keywords, const char **values);
80 : static PGresult *executeQuery(PGconn *conn, const char *query);
81 : static void executeCommand(PGconn *conn, const char *query);
82 : static void expand_dbname_patterns(PGconn *conn, SimpleStringList *patterns,
83 : SimpleStringList *names);
84 :
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;
93 :
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;
113 :
114 : static char role_catalog[10];
115 : #define PG_AUTHID "pg_authid"
116 : #define PG_ROLES "pg_roles "
117 :
118 : static FILE *OPF;
119 : static char *filename = NULL;
120 :
121 : static SimpleStringList database_exclude_patterns = {NULL, NULL};
122 : static SimpleStringList database_exclude_names = {NULL, NULL};
123 :
124 : #define exit_nicely(code) exit(code)
125 :
126 : int
7530 peter_e 127 GIC 31 : main(int argc, char *argv[])
128 : {
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'},
150 :
151 : /*
6028 peter_e 152 ECB : * the following options don't have an equivalent short option letter
153 : */
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 :
181 : {NULL, 0, NULL, 0}
182 : };
183 :
3782 bruce 184 GIC 31 : char *pghost = NULL;
185 31 : char *pgport = NULL;
186 31 : char *pguser = NULL;
187 31 : char *pgdb = NULL;
188 31 : char *use_role = NULL;
2046 rhaas 189 31 : const char *dumpencoding = NULL;
3099 alvherre 190 31 : trivalue prompt_password = TRI_DEFAULT;
3782 bruce 191 31 : bool data_only = false;
192 31 : bool globals_only = false;
193 31 : bool roles_only = false;
194 31 : bool tablespaces_only = false;
195 : PGconn *conn;
196 : int encoding;
197 : const char *std_strings;
198 : int c,
199 : ret;
200 : int optindex;
201 :
1469 peter 202 31 : pg_logging_init(argv[0]);
203 31 : pg_logging_set_level(PG_LOG_WARNING);
5232 peter_e 204 31 : set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
7310 bruce 205 31 : progname = get_progname(argv[0]);
206 :
7530 peter_e 207 31 : if (argc > 1)
208 : {
7530 peter_e 209 CBC 31 : if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
7530 peter_e 210 ECB : {
7530 peter_e 211 CBC 1 : help();
4070 rhaas 212 1 : exit_nicely(0);
7530 peter_e 213 ECB : }
7530 peter_e 214 CBC 30 : if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
7530 peter_e 215 ECB : {
7530 peter_e 216 CBC 3 : puts("pg_dumpall (PostgreSQL) " PG_VERSION);
4070 rhaas 217 3 : exit_nicely(0);
7530 peter_e 218 ECB : }
219 : }
220 :
6166 peter_e 221 GIC 27 : if ((ret = find_other_exec(argv[0], "pg_dump", PGDUMP_VERSIONSTR,
222 : pg_dump_bin)) < 0)
223 : {
224 : char full_path[MAXPGPATH];
225 :
6750 bruce 226 UIC 0 : if (find_my_exec(argv[0], full_path) < 0)
5902 peter_e 227 LBC 0 : strlcpy(full_path, progname, sizeof(full_path));
6750 bruce 228 ECB :
6907 bruce 229 LBC 0 : if (ret == -1)
366 tgl 230 0 : pg_fatal("program \"%s\" is needed by %s but was not found in the same directory as \"%s\"",
231 : "pg_dump", progname, full_path);
6907 bruce 232 ECB : else
366 tgl 233 UIC 0 : pg_fatal("program \"%s\" was found by \"%s\" but was not the same version as %s",
366 tgl 234 ECB : "pg_dump", full_path, progname);
235 : }
6907 bruce 236 :
7530 peter_e 237 CBC 27 : pgdumpopts = createPQExpBuffer();
238 :
1417 michael 239 106 : while ((c = getopt_long(argc, argv, "acd:E:f:gh:l:Op:rsS:tU:vwWx", long_options, &optindex)) != -1)
240 : {
7530 peter_e 241 80 : switch (c)
7530 peter_e 242 ECB : {
7254 tgl 243 UIC 0 : case 'a':
244 0 : data_only = true;
3429 heikki.linnakangas 245 0 : appendPQExpBufferStr(pgdumpopts, " -a");
7254 tgl 246 LBC 0 : break;
247 :
7530 peter_e 248 GIC 1 : case 'c':
249 1 : output_clean = true;
250 1 : break;
7530 peter_e 251 EUB :
3695 heikki.linnakangas 252 GBC 6 : case 'd':
3695 heikki.linnakangas 253 GIC 6 : connstr = pg_strdup(optarg);
3695 heikki.linnakangas 254 GBC 6 : break;
3695 heikki.linnakangas 255 EUB :
2046 rhaas 256 UIC 0 : case 'E':
257 0 : dumpencoding = pg_strdup(optarg);
2046 rhaas 258 UBC 0 : appendPQExpBufferStr(pgdumpopts, " -E ");
2046 rhaas 259 UIC 0 : appendShellString(pgdumpopts, optarg);
260 0 : break;
261 :
5918 bruce 262 CBC 16 : case 'f':
3831 bruce 263 GIC 16 : filename = pg_strdup(optarg);
3429 heikki.linnakangas 264 CBC 16 : appendPQExpBufferStr(pgdumpopts, " -f ");
2435 noah 265 GIC 16 : appendShellString(pgdumpopts, filename);
5918 bruce 266 CBC 16 : break;
267 :
7530 peter_e 268 GBC 7 : case 'g':
269 7 : globals_only = true;
270 7 : break;
7530 peter_e 271 EUB :
7530 peter_e 272 GIC 1 : case 'h':
3831 bruce 273 CBC 1 : pghost = pg_strdup(optarg);
7530 peter_e 274 1 : break;
7530 peter_e 275 ECB :
5918 bruce 276 GIC 1 : case 'l':
3831 bruce 277 CBC 1 : pgdb = pg_strdup(optarg);
5918 278 1 : break;
6565 tgl 279 ECB :
6845 bruce 280 UIC 0 : case 'O':
3429 heikki.linnakangas 281 UBC 0 : appendPQExpBufferStr(pgdumpopts, " -O");
6845 bruce 282 0 : break;
6845 bruce 283 EUB :
7530 peter_e 284 GBC 4 : case 'p':
3831 bruce 285 4 : pgport = pg_strdup(optarg);
7530 peter_e 286 GIC 4 : break;
5624 bruce 287 ECB :
5918 bruce 288 CBC 7 : case 'r':
289 7 : roles_only = true;
290 7 : break;
7530 peter_e 291 ECB :
7254 tgl 292 UIC 0 : case 's':
3429 heikki.linnakangas 293 LBC 0 : appendPQExpBufferStr(pgdumpopts, " -s");
7254 tgl 294 0 : break;
7254 tgl 295 ECB :
6845 bruce 296 UIC 0 : case 'S':
3429 heikki.linnakangas 297 LBC 0 : appendPQExpBufferStr(pgdumpopts, " -S ");
2435 noah 298 0 : appendShellString(pgdumpopts, optarg);
6845 bruce 299 0 : break;
300 :
5918 bruce 301 CBC 2 : case 't':
302 2 : tablespaces_only = true;
303 2 : break;
304 :
7530 peter_e 305 GBC 8 : case 'U':
3831 bruce 306 8 : pguser = pg_strdup(optarg);
7530 peter_e 307 8 : break;
308 :
7530 peter_e 309 CBC 2 : case 'v':
310 2 : verbose = true;
934 tgl 311 2 : pg_logging_increase_verbosity();
3429 heikki.linnakangas 312 GIC 2 : appendPQExpBufferStr(pgdumpopts, " -v");
7530 peter_e 313 CBC 2 : break;
7530 peter_e 314 ECB :
5155 peter_e 315 LBC 0 : case 'w':
5155 peter_e 316 UIC 0 : prompt_password = TRI_NO;
3429 heikki.linnakangas 317 UBC 0 : appendPQExpBufferStr(pgdumpopts, " -w");
5155 peter_e 318 0 : break;
5155 peter_e 319 EUB :
7530 peter_e 320 UIC 0 : case 'W':
5155 peter_e 321 UBC 0 : prompt_password = TRI_YES;
3429 heikki.linnakangas 322 0 : appendPQExpBufferStr(pgdumpopts, " -W");
7530 peter_e 323 0 : break;
7530 peter_e 324 EUB :
7254 tgl 325 UIC 0 : case 'x':
7254 tgl 326 LBC 0 : skip_acls = true;
3429 heikki.linnakangas 327 0 : appendPQExpBufferStr(pgdumpopts, " -x");
7254 tgl 328 0 : break;
329 :
6845 bruce 330 CBC 4 : case 0:
331 4 : break;
6845 bruce 332 ECB :
5336 alvherre 333 UIC 0 : case 2:
3429 heikki.linnakangas 334 LBC 0 : appendPQExpBufferStr(pgdumpopts, " --lock-wait-timeout ");
2435 noah 335 0 : appendShellString(pgdumpopts, optarg);
5207 tgl 336 0 : break;
5207 tgl 337 ECB :
5207 tgl 338 LBC 0 : case 3:
3831 bruce 339 UIC 0 : use_role = pg_strdup(optarg);
3429 heikki.linnakangas 340 UBC 0 : appendPQExpBufferStr(pgdumpopts, " --role ");
2435 noah 341 0 : appendShellString(pgdumpopts, use_role);
5336 alvherre 342 0 : break;
5336 alvherre 343 EUB :
2209 andrew 344 GIC 15 : case 4:
2209 andrew 345 GBC 15 : dosync = false;
346 15 : appendPQExpBufferStr(pgdumpopts, " --no-sync");
347 15 : break;
2209 andrew 348 EUB :
1511 andrew 349 UIC 0 : case 5:
1511 andrew 350 UBC 0 : appendPQExpBufferStr(pgdumpopts, " --extra-float-digits ");
351 0 : appendShellString(pgdumpopts, optarg);
352 0 : break;
1511 andrew 353 EUB :
1500 andrew 354 GIC 5 : case 6:
1500 andrew 355 CBC 5 : simple_string_list_append(&database_exclude_patterns, optarg);
356 5 : break;
357 :
1395 alvherre 358 UBC 0 : case 7:
359 0 : appendPQExpBufferStr(pgdumpopts, " --rows-per-insert ");
360 0 : appendShellString(pgdumpopts, optarg);
361 0 : break;
362 :
7522 bruce 363 GBC 1 : default:
366 tgl 364 EUB : /* getopt_long already emitted a complaint */
366 tgl 365 GBC 1 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
4070 rhaas 366 1 : exit_nicely(1);
7530 peter_e 367 EUB : }
368 : }
7530 peter_e 369 ECB :
4622 tgl 370 : /* Complain if any arguments remain */
7522 bruce 371 CBC 26 : if (optind < argc)
7522 bruce 372 ECB : {
1469 peter 373 GIC 1 : pg_log_error("too many command-line arguments (first is \"%s\")",
1469 peter 374 EUB : argv[optind]);
366 tgl 375 GBC 1 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
4070 rhaas 376 1 : exit_nicely(1);
7522 bruce 377 EUB : }
378 :
1500 andrew 379 CBC 25 : if (database_exclude_patterns.head != NULL &&
380 4 : (globals_only || roles_only || tablespaces_only))
1500 andrew 381 ECB : {
1378 peter 382 GIC 1 : pg_log_error("option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only");
366 tgl 383 GBC 1 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
1500 andrew 384 1 : exit_nicely(1);
1500 andrew 385 EUB : }
386 :
387 : /* Make sure the user hasn't specified a mix of globals-only options */
5918 bruce 388 CBC 24 : if (globals_only && roles_only)
389 : {
1469 peter 390 1 : pg_log_error("options -g/--globals-only and -r/--roles-only cannot be used together");
366 tgl 391 1 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
4070 rhaas 392 GIC 1 : exit_nicely(1);
393 : }
394 :
5918 bruce 395 23 : if (globals_only && tablespaces_only)
5918 bruce 396 ECB : {
1469 peter 397 GIC 1 : pg_log_error("options -g/--globals-only and -t/--tablespaces-only cannot be used together");
366 tgl 398 CBC 1 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
4070 rhaas 399 GIC 1 : exit_nicely(1);
5918 bruce 400 ECB : }
5624 401 :
3324 alvherre 402 GIC 22 : if (if_exists && !output_clean)
366 tgl 403 1 : pg_fatal("option --if-exists requires option -c/--clean");
3324 alvherre 404 ECB :
5918 bruce 405 CBC 21 : if (roles_only && tablespaces_only)
406 : {
1469 peter 407 1 : pg_log_error("options -r/--roles-only and -t/--tablespaces-only cannot be used together");
366 tgl 408 1 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
4070 rhaas 409 1 : exit_nicely(1);
410 : }
411 :
412 : /*
2153 bruce 413 ECB : * If password values are not required in the dump, switch to using
414 : * pg_roles which is equally useful, just more likely to have unrestricted
415 : * access than pg_authid.
2224 simon 416 : */
2224 simon 417 CBC 20 : if (no_role_passwords)
2224 simon 418 UIC 0 : sprintf(role_catalog, "%s", PG_ROLES);
419 : else
2224 simon 420 CBC 20 : sprintf(role_catalog, "%s", PG_AUTHID);
421 :
4622 tgl 422 ECB : /* Add long options to the pg_dump argument list */
4622 tgl 423 CBC 20 : if (binary_upgrade)
3429 heikki.linnakangas 424 1 : appendPQExpBufferStr(pgdumpopts, " --binary-upgrade");
4622 tgl 425 GIC 20 : if (column_inserts)
3429 heikki.linnakangas 426 UIC 0 : appendPQExpBufferStr(pgdumpopts, " --column-inserts");
4622 tgl 427 CBC 20 : if (disable_dollar_quoting)
3429 heikki.linnakangas 428 LBC 0 : appendPQExpBufferStr(pgdumpopts, " --disable-dollar-quoting");
4622 tgl 429 GIC 20 : if (disable_triggers)
3429 heikki.linnakangas 430 LBC 0 : appendPQExpBufferStr(pgdumpopts, " --disable-triggers");
4622 tgl 431 GIC 20 : if (inserts)
3429 heikki.linnakangas 432 LBC 0 : appendPQExpBufferStr(pgdumpopts, " --inserts");
447 michael 433 CBC 20 : if (no_table_access_method)
447 michael 434 LBC 0 : appendPQExpBufferStr(pgdumpopts, " --no-table-access-method");
4622 tgl 435 GIC 20 : if (no_tablespaces)
3429 heikki.linnakangas 436 UIC 0 : appendPQExpBufferStr(pgdumpopts, " --no-tablespaces");
4622 tgl 437 GIC 20 : if (quote_all_identifiers)
3429 heikki.linnakangas 438 1 : appendPQExpBufferStr(pgdumpopts, " --quote-all-identifiers");
2064 rhaas 439 20 : if (load_via_partition_root)
2064 rhaas 440 UIC 0 : appendPQExpBufferStr(pgdumpopts, " --load-via-partition-root");
4622 tgl 441 GIC 20 : if (use_setsessauth)
3429 heikki.linnakangas 442 LBC 0 : appendPQExpBufferStr(pgdumpopts, " --use-set-session-authorization");
1900 tgl 443 GBC 20 : if (no_comments)
1900 tgl 444 UIC 0 : appendPQExpBufferStr(pgdumpopts, " --no-comments");
2158 peter_e 445 CBC 20 : if (no_publications)
2158 peter_e 446 UIC 0 : appendPQExpBufferStr(pgdumpopts, " --no-publications");
4343 peter_e 447 GIC 20 : if (no_security_labels)
3429 heikki.linnakangas 448 LBC 0 : appendPQExpBufferStr(pgdumpopts, " --no-security-labels");
2161 peter_e 449 CBC 20 : if (no_subscriptions)
2161 peter_e 450 LBC 0 : appendPQExpBufferStr(pgdumpopts, " --no-subscriptions");
690 michael 451 GBC 20 : if (no_toast_compression)
690 michael 452 LBC 0 : appendPQExpBufferStr(pgdumpopts, " --no-toast-compression");
4484 rhaas 453 GBC 20 : if (no_unlogged_table_data)
3429 heikki.linnakangas 454 CBC 1 : appendPQExpBufferStr(pgdumpopts, " --no-unlogged-table-data");
1731 tmunro 455 GBC 20 : if (on_conflict_do_nothing)
1731 tmunro 456 LBC 0 : appendPQExpBufferStr(pgdumpopts, " --on-conflict-do-nothing");
4622 tgl 457 EUB :
6484 tgl 458 ECB : /*
5918 bruce 459 EUB : * If there was a database specified on the command line, use that,
5918 bruce 460 ECB : * otherwise try to connect to database "postgres", and failing that
481 tgl 461 EUB : * "template1".
6484 tgl 462 ECB : */
5918 bruce 463 CBC 20 : if (pgdb)
5918 bruce 464 ECB : {
3695 heikki.linnakangas 465 GBC 1 : conn = connectDatabase(pgdb, connstr, pghost, pgport, pguser,
5155 peter_e 466 ECB : prompt_password, false);
5624 bruce 467 EUB :
5918 bruce 468 CBC 1 : if (!conn)
366 tgl 469 UBC 0 : pg_fatal("could not connect to database \"%s\"", pgdb);
5918 bruce 470 ECB : }
5918 bruce 471 EUB : else
5918 bruce 472 ECB : {
3695 heikki.linnakangas 473 GBC 19 : conn = connectDatabase("postgres", connstr, pghost, pgport, pguser,
5155 peter_e 474 ECB : prompt_password, false);
5918 bruce 475 GBC 19 : if (!conn)
3695 heikki.linnakangas 476 LBC 0 : conn = connectDatabase("template1", connstr, pghost, pgport, pguser,
5155 peter_e 477 EUB : prompt_password, true);
5624 bruce 478 ECB :
5918 bruce 479 CBC 19 : if (!conn)
5918 bruce 480 ECB : {
1469 peter 481 UBC 0 : pg_log_error("could not connect to databases \"postgres\" or \"template1\"\n"
482 : "Please specify an alternative database.");
366 tgl 483 UIC 0 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
4070 rhaas 484 0 : exit_nicely(1);
485 : }
486 : }
487 :
1500 andrew 488 ECB : /*
489 : * Get a list of database names that match the exclude patterns
490 : */
1500 andrew 491 GIC 20 : expand_dbname_patterns(conn, &database_exclude_patterns,
492 : &database_exclude_names);
1500 andrew 493 ECB :
5918 bruce 494 EUB : /*
495 : * Open the output file if required, otherwise use stdout
496 : */
5918 bruce 497 GIC 18 : if (filename)
5918 bruce 498 ECB : {
5918 bruce 499 GIC 16 : OPF = fopen(filename, PG_BINARY_W);
5918 bruce 500 CBC 16 : if (!OPF)
366 tgl 501 UBC 0 : pg_fatal("could not open output file \"%s\": %m",
502 : filename);
503 : }
5918 bruce 504 ECB : else
5918 bruce 505 GIC 2 : OPF = stdout;
7530 peter_e 506 EUB :
507 : /*
2046 rhaas 508 : * Set the client encoding if requested.
509 : */
2046 rhaas 510 GIC 18 : if (dumpencoding)
511 : {
2046 rhaas 512 UIC 0 : if (PQsetClientEncoding(conn, dumpencoding) < 0)
366 tgl 513 0 : pg_fatal("invalid client encoding \"%s\" specified",
514 : dumpencoding);
515 : }
2046 rhaas 516 ECB :
517 : /*
518 : * Get the active encoding and the standard_conforming_strings setting, so
519 : * we know how to escape strings.
520 : */
6160 tgl 521 GIC 18 : encoding = PQclientEncoding(conn);
6160 tgl 522 CBC 18 : std_strings = PQparameterStatus(conn, "standard_conforming_strings");
6160 tgl 523 GIC 18 : if (!std_strings)
6160 tgl 524 LBC 0 : std_strings = "off";
6160 tgl 525 ECB :
5207 tgl 526 EUB : /* Set the role if requested */
481 tgl 527 GIC 18 : if (use_role)
528 : {
5207 tgl 529 UIC 0 : PQExpBuffer query = createPQExpBuffer();
5207 tgl 530 ECB :
5207 tgl 531 UIC 0 : appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
532 0 : executeCommand(conn, query->data);
533 0 : destroyPQExpBuffer(query);
534 : }
5207 tgl 535 ECB :
536 : /* Force quoting of all identifiers if requested. */
481 tgl 537 GBC 18 : if (quote_all_identifiers)
4644 rhaas 538 1 : executeCommand(conn, "SET quote_all_identifiers = true");
539 :
5918 bruce 540 GIC 18 : fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n");
6880 541 18 : if (verbose)
6797 542 2 : dumpTimestamp("Started on");
543 :
544 : /*
545 : * We used to emit \connect postgres here, but that served no purpose
4181 rhaas 546 ECB : * other than to break things for installations without a postgres
547 : * database. Everything we're restoring here is a global, so whichever
548 : * database we're connected to at the moment is fine.
4181 rhaas 549 EUB : */
550 :
551 : /* Restore will need to write to the target cluster */
3417 kgrittn 552 CBC 18 : fprintf(OPF, "SET default_transaction_read_only = off;\n\n");
553 :
5111 tgl 554 EUB : /* Replicate encoding and std_strings in output */
5111 tgl 555 GIC 18 : fprintf(OPF, "SET client_encoding = '%s';\n",
5111 tgl 556 EUB : pg_encoding_to_char(encoding));
5111 tgl 557 GBC 18 : fprintf(OPF, "SET standard_conforming_strings = %s;\n", std_strings);
558 18 : if (strcmp(std_strings, "off") == 0)
5111 tgl 559 UIC 0 : fprintf(OPF, "SET escape_string_warning = off;\n");
5111 tgl 560 GIC 18 : fprintf(OPF, "\n");
561 :
7254 tgl 562 CBC 18 : if (!data_only)
7254 tgl 563 ECB : {
564 : /*
3260 bruce 565 : * If asked to --clean, do that first. We can avoid detailed
5111 tgl 566 : * dependency analysis because databases never depend on each other,
3260 bruce 567 : * and tablespaces never depend on each other. Roles could have
568 : * grants to each other, but DROP ROLE will clean those up silently.
569 : */
5111 tgl 570 GIC 18 : if (output_clean)
571 : {
572 1 : if (!globals_only && !roles_only && !tablespaces_only)
5111 tgl 573 UIC 0 : dropDBs(conn);
574 :
5111 tgl 575 GIC 1 : if (!roles_only && !no_tablespaces)
2370 576 1 : dropTablespaces(conn);
5111 tgl 577 ECB :
5111 tgl 578 GIC 1 : if (!tablespaces_only)
579 1 : dropRoles(conn);
5111 tgl 580 ECB : }
581 :
582 : /*
5050 bruce 583 : * Now create objects as requested. Be careful that option logic here
5050 bruce 584 EUB : * is the same as for drops above.
5111 tgl 585 ECB : */
5918 bruce 586 GIC 18 : if (!tablespaces_only)
5918 bruce 587 ECB : {
588 : /* Dump roles (users) */
5918 bruce 589 GIC 18 : dumpRoles(conn);
590 :
591 : /* Dump role memberships */
481 tgl 592 18 : dumpRoleMembership(conn);
593 :
594 : /* Dump role GUC privileges */
368 tgl 595 CBC 18 : if (server_version >= 150000 && !skip_acls)
368 tgl 596 GIC 18 : dumpRoleGUCPrivs(conn);
5918 bruce 597 ECB : }
6461 tgl 598 EUB :
599 : /* Dump tablespaces */
5498 tgl 600 CBC 18 : if (!roles_only && !no_tablespaces)
2370 601 13 : dumpTablespaces(conn);
602 : }
7530 peter_e 603 ECB :
5918 bruce 604 CBC 18 : if (!globals_only && !roles_only && !tablespaces_only)
7254 tgl 605 GIC 9 : dumpDatabases(conn);
606 :
7530 peter_e 607 17 : PQfinish(conn);
608 :
6880 bruce 609 17 : if (verbose)
610 2 : dumpTimestamp("Completed on");
5918 bruce 611 CBC 17 : fprintf(OPF, "--\n-- PostgreSQL database cluster dump complete\n--\n\n");
612 :
5918 bruce 613 GIC 17 : if (filename)
2209 andrew 614 ECB : {
5918 bruce 615 GIC 15 : fclose(OPF);
616 :
2209 andrew 617 ECB : /* sync the resulting file, errors are not fatal */
2209 andrew 618 GIC 15 : if (dosync)
1469 peter 619 2 : (void) fsync_fname(filename, false);
2209 andrew 620 ECB : }
621 :
4070 rhaas 622 GIC 17 : exit_nicely(0);
623 : }
624 :
7530 peter_e 625 ECB :
626 : static void
7530 peter_e 627 GIC 1 : help(void)
628 : {
7530 peter_e 629 CBC 1 : printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname);
630 1 : printf(_("Usage:\n"));
7478 peter_e 631 GIC 1 : printf(_(" %s [OPTION]...\n"), progname);
7530 peter_e 632 ECB :
6838 bruce 633 GIC 1 : printf(_("\nGeneral options:\n"));
3978 peter_e 634 CBC 1 : printf(_(" -f, --file=FILENAME output file name\n"));
2297 sfrost 635 1 : printf(_(" -v, --verbose verbose mode\n"));
3947 peter_e 636 1 : printf(_(" -V, --version output version information, then exit\n"));
3978 peter_e 637 GIC 1 : printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
3947 peter_e 638 CBC 1 : printf(_(" -?, --help show this help, then exit\n"));
6838 bruce 639 GIC 1 : printf(_("\nOptions controlling the output content:\n"));
3978 peter_e 640 CBC 1 : printf(_(" -a, --data-only dump only the data, not the schema\n"));
3978 peter_e 641 GIC 1 : printf(_(" -c, --clean clean (drop) databases before recreating\n"));
2046 rhaas 642 1 : printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
3978 peter_e 643 CBC 1 : printf(_(" -g, --globals-only dump only global objects, no databases\n"));
644 1 : printf(_(" -O, --no-owner skip restoration of object ownership\n"));
3978 peter_e 645 GIC 1 : printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n"));
646 1 : printf(_(" -s, --schema-only dump only the schema, no data\n"));
3978 peter_e 647 CBC 1 : printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n"));
3978 peter_e 648 GIC 1 : printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n"));
649 1 : printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
650 1 : printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
651 1 : printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
3978 peter_e 652 CBC 1 : printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
3978 peter_e 653 GIC 1 : printf(_(" --disable-triggers disable triggers during data-only restore\n"));
1500 andrew 654 CBC 1 : printf(_(" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n"));
1511 655 1 : printf(_(" --extra-float-digits=NUM override default setting for extra_float_digits\n"));
3324 alvherre 656 1 : printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
3978 peter_e 657 GIC 1 : printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
1770 peter_e 658 CBC 1 : printf(_(" --load-via-partition-root load partitions via the root table\n"));
1900 tgl 659 1 : printf(_(" --no-comments do not dump comments\n"));
2158 peter_e 660 1 : printf(_(" --no-publications do not dump publications\n"));
2131 661 1 : printf(_(" --no-role-passwords do not dump passwords for roles\n"));
3978 662 1 : printf(_(" --no-security-labels do not dump security label assignments\n"));
2161 663 1 : printf(_(" --no-subscriptions do not dump subscriptions\n"));
2209 andrew 664 1 : printf(_(" --no-sync do not wait for changes to be written safely to disk\n"));
447 michael 665 1 : printf(_(" --no-table-access-method do not dump table access methods\n"));
3978 peter_e 666 1 : printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
690 michael 667 1 : printf(_(" --no-toast-compression do not dump TOAST compression methods\n"));
3978 peter_e 668 1 : printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
1731 tmunro 669 1 : printf(_(" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n"));
3978 peter_e 670 1 : printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
1395 alvherre 671 1 : printf(_(" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n"));
6028 peter_e 672 1 : printf(_(" --use-set-session-authorization\n"
3978 peter_e 673 ECB : " use SET SESSION AUTHORIZATION commands instead of\n"
674 : " ALTER OWNER commands to set ownership\n"));
7478 675 :
7478 peter_e 676 CBC 1 : printf(_("\nConnection options:\n"));
3695 heikki.linnakangas 677 1 : printf(_(" -d, --dbname=CONNSTR connect using connection string\n"));
7242 bruce 678 1 : printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
5156 peter_e 679 1 : printf(_(" -l, --database=DBNAME alternative default database\n"));
7478 680 1 : printf(_(" -p, --port=PORT database server port number\n"));
681 1 : printf(_(" -U, --username=NAME connect as specified database user\n"));
5155 682 1 : printf(_(" -w, --no-password never prompt for password\n"));
7478 683 1 : printf(_(" -W, --password force password prompt (should happen automatically)\n"));
4337 684 1 : printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
7530 peter_e 685 ECB :
5156 peter_e 686 CBC 1 : printf(_("\nIf -f/--file is not used, then the SQL script will be written to the standard\n"
5050 bruce 687 ECB : "output.\n\n"));
1136 peter 688 CBC 1 : printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
689 1 : printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
7530 peter_e 690 1 : }
7530 peter_e 691 ECB :
692 :
5111 tgl 693 : /*
694 : * Drop roles
695 : */
696 : static void
5111 tgl 697 CBC 1 : dropRoles(PGconn *conn)
698 : {
2224 simon 699 GIC 1 : PQExpBuffer buf = createPQExpBuffer();
700 : PGresult *res;
5111 tgl 701 ECB : int i_rolname;
702 : int i;
703 :
2511 sfrost 704 CBC 1 : if (server_version >= 90600)
2224 simon 705 1 : printfPQExpBuffer(buf,
2153 bruce 706 ECB : "SELECT rolname "
707 : "FROM %s "
708 : "WHERE rolname !~ '^pg_' "
709 : "ORDER BY 1", role_catalog);
710 : else
2224 simon 711 LBC 0 : printfPQExpBuffer(buf,
712 : "SELECT rolname "
2153 bruce 713 ECB : "FROM %s "
714 : "ORDER BY 1", role_catalog);
5111 tgl 715 :
2224 simon 716 GIC 1 : res = executeQuery(conn, buf->data);
717 :
5111 tgl 718 1 : i_rolname = PQfnumber(res, "rolname");
719 :
720 1 : if (PQntuples(res) > 0)
721 1 : fprintf(OPF, "--\n-- Drop roles\n--\n\n");
5111 tgl 722 ECB :
5111 tgl 723 GIC 4 : for (i = 0; i < PQntuples(res); i++)
5111 tgl 724 ECB : {
725 : const char *rolename;
726 :
5111 tgl 727 GIC 3 : rolename = PQgetvalue(res, i, i_rolname);
728 :
3324 alvherre 729 CBC 6 : fprintf(OPF, "DROP ROLE %s%s;\n",
730 3 : if_exists ? "IF EXISTS " : "",
731 : fmtId(rolename));
732 : }
733 :
5111 tgl 734 GIC 1 : PQclear(res);
2224 simon 735 1 : destroyPQExpBuffer(buf);
5111 tgl 736 EUB :
5111 tgl 737 GIC 1 : fprintf(OPF, "\n\n");
738 1 : }
739 :
740 : /*
6461 tgl 741 ECB : * Dump roles
742 : */
7530 peter_e 743 : static void
6390 tgl 744 GIC 18 : dumpRoles(PGconn *conn)
7530 peter_e 745 ECB : {
6484 tgl 746 CBC 18 : PQExpBuffer buf = createPQExpBuffer();
747 : PGresult *res;
4475 bruce 748 ECB : int i_oid,
749 : i_rolname,
750 : i_rolsuper,
751 : i_rolinherit,
6461 tgl 752 : i_rolcreaterole,
753 : i_rolcreatedb,
754 : i_rolcanlogin,
755 : i_rolconnlimit,
756 : i_rolpassword,
757 : i_rolvaliduntil,
758 : i_rolreplication,
3124 sfrost 759 : i_rolbypassrls,
3779 bruce 760 : i_rolcomment,
761 : i_is_current_user;
7522 762 : int i;
7530 peter_e 763 :
764 : /* note: rolconfig is dumped later */
2557 sfrost 765 GIC 18 : if (server_version >= 90600)
3124 766 18 : printfPQExpBuffer(buf,
767 : "SELECT oid, rolname, rolsuper, rolinherit, "
768 : "rolcreaterole, rolcreatedb, "
3029 alvherre 769 ECB : "rolcanlogin, rolconnlimit, rolpassword, "
770 : "rolvaliduntil, rolreplication, rolbypassrls, "
2118 tgl 771 : "pg_catalog.shobj_description(oid, '%s') as rolcomment, "
772 : "rolname = current_user AS is_current_user "
773 : "FROM %s "
774 : "WHERE rolname !~ '^pg_' "
775 : "ORDER BY 2", role_catalog, role_catalog);
2529 sfrost 776 UIC 0 : else if (server_version >= 90500)
777 0 : printfPQExpBuffer(buf,
778 : "SELECT oid, rolname, rolsuper, rolinherit, "
779 : "rolcreaterole, rolcreatedb, "
780 : "rolcanlogin, rolconnlimit, rolpassword, "
781 : "rolvaliduntil, rolreplication, rolbypassrls, "
782 : "pg_catalog.shobj_description(oid, '%s') as rolcomment, "
783 : "rolname = current_user AS is_current_user "
784 : "FROM %s "
785 : "ORDER BY 2", role_catalog, role_catalog);
786 : else
6461 tgl 787 0 : printfPQExpBuffer(buf,
788 : "SELECT oid, rolname, rolsuper, rolinherit, "
789 : "rolcreaterole, rolcreatedb, "
6461 tgl 790 ECB : "rolcanlogin, rolconnlimit, rolpassword, "
4484 magnus 791 : "rolvaliduntil, rolreplication, "
792 : "false as rolbypassrls, "
793 : "pg_catalog.shobj_description(oid, '%s') as rolcomment, "
794 : "rolname = current_user AS is_current_user "
795 : "FROM %s "
796 : "ORDER BY 2", role_catalog, role_catalog);
797 :
6461 tgl 798 GIC 18 : res = executeQuery(conn, buf->data);
799 :
4475 bruce 800 18 : i_oid = PQfnumber(res, "oid");
6461 tgl 801 GBC 18 : i_rolname = PQfnumber(res, "rolname");
802 18 : i_rolsuper = PQfnumber(res, "rolsuper");
6461 tgl 803 GIC 18 : i_rolinherit = PQfnumber(res, "rolinherit");
804 18 : i_rolcreaterole = PQfnumber(res, "rolcreaterole");
805 18 : i_rolcreatedb = PQfnumber(res, "rolcreatedb");
806 18 : i_rolcanlogin = PQfnumber(res, "rolcanlogin");
807 18 : i_rolconnlimit = PQfnumber(res, "rolconnlimit");
808 18 : i_rolpassword = PQfnumber(res, "rolpassword");
809 18 : i_rolvaliduntil = PQfnumber(res, "rolvaliduntil");
4484 magnus 810 18 : i_rolreplication = PQfnumber(res, "rolreplication");
3124 sfrost 811 18 : i_rolbypassrls = PQfnumber(res, "rolbypassrls");
6265 bruce 812 GBC 18 : i_rolcomment = PQfnumber(res, "rolcomment");
3779 bruce 813 GIC 18 : i_is_current_user = PQfnumber(res, "is_current_user");
814 :
6390 tgl 815 18 : if (PQntuples(res) > 0)
5918 bruce 816 18 : fprintf(OPF, "--\n-- Roles\n--\n\n");
817 :
7530 peter_e 818 75 : for (i = 0; i < PQntuples(res); i++)
819 : {
820 : const char *rolename;
821 : Oid auth_oid;
822 :
4281 rhaas 823 CBC 57 : auth_oid = atooid(PQgetvalue(res, i, i_oid));
6461 tgl 824 GIC 57 : rolename = PQgetvalue(res, i, i_rolname);
6838 bruce 825 ECB :
2495 rhaas 826 CBC 57 : if (strncmp(rolename, "pg_", 3) == 0)
2557 sfrost 827 ECB : {
1469 peter 828 LBC 0 : pg_log_warning("role name starting with \"pg_\" skipped (%s)",
1469 peter 829 ECB : rolename);
2557 sfrost 830 LBC 0 : continue;
2557 sfrost 831 ECB : }
832 :
6390 tgl 833 CBC 57 : resetPQExpBuffer(buf);
6390 tgl 834 ECB :
4475 bruce 835 CBC 57 : if (binary_upgrade)
4475 bruce 836 ECB : {
3429 heikki.linnakangas 837 CBC 1 : appendPQExpBufferStr(buf, "\n-- For binary upgrade, must preserve pg_authid.oid\n");
4475 bruce 838 1 : appendPQExpBuffer(buf,
839 : "SELECT pg_catalog.binary_upgrade_set_next_pg_authid_oid('%u'::pg_catalog.oid);\n\n",
4475 bruce 840 ECB : auth_oid);
841 : }
842 :
6797 843 : /*
844 : * We dump CREATE ROLE followed by ALTER ROLE to ensure that the role
845 : * will acquire the right properties even if it already exists (ie, it
846 : * won't hurt for the CREATE to fail). This is particularly important
847 : * for the role we are connected as, since even with --clean we will
3260 848 : * have failed to drop it. binary_upgrade cannot generate any errors,
3779 849 : * so we assume the current role is already created.
850 : */
3779 bruce 851 CBC 57 : if (!binary_upgrade ||
3779 bruce 852 GIC 1 : strcmp(PQgetvalue(res, i, i_is_current_user), "f") == 0)
3782 bruce 853 GBC 56 : appendPQExpBuffer(buf, "CREATE ROLE %s;\n", fmtId(rolename));
6390 tgl 854 GIC 57 : appendPQExpBuffer(buf, "ALTER ROLE %s WITH", fmtId(rolename));
7530 peter_e 855 EUB :
6461 tgl 856 GIC 57 : if (strcmp(PQgetvalue(res, i, i_rolsuper), "t") == 0)
3429 heikki.linnakangas 857 46 : appendPQExpBufferStr(buf, " SUPERUSER");
6461 tgl 858 ECB : else
3429 heikki.linnakangas 859 GIC 11 : appendPQExpBufferStr(buf, " NOSUPERUSER");
7530 peter_e 860 ECB :
6461 tgl 861 GIC 57 : if (strcmp(PQgetvalue(res, i, i_rolinherit), "t") == 0)
3429 heikki.linnakangas 862 CBC 57 : appendPQExpBufferStr(buf, " INHERIT");
6461 tgl 863 ECB : else
3429 heikki.linnakangas 864 UIC 0 : appendPQExpBufferStr(buf, " NOINHERIT");
865 :
6461 tgl 866 GIC 57 : if (strcmp(PQgetvalue(res, i, i_rolcreaterole), "t") == 0)
3429 heikki.linnakangas 867 46 : appendPQExpBufferStr(buf, " CREATEROLE");
868 : else
869 11 : appendPQExpBufferStr(buf, " NOCREATEROLE");
870 :
6461 tgl 871 57 : if (strcmp(PQgetvalue(res, i, i_rolcreatedb), "t") == 0)
3429 heikki.linnakangas 872 46 : appendPQExpBufferStr(buf, " CREATEDB");
873 : else
874 11 : appendPQExpBufferStr(buf, " NOCREATEDB");
875 :
6461 tgl 876 CBC 57 : if (strcmp(PQgetvalue(res, i, i_rolcanlogin), "t") == 0)
3429 heikki.linnakangas 877 46 : appendPQExpBufferStr(buf, " LOGIN");
7530 peter_e 878 ECB : else
3429 heikki.linnakangas 879 CBC 11 : appendPQExpBufferStr(buf, " NOLOGIN");
880 :
4484 magnus 881 57 : if (strcmp(PQgetvalue(res, i, i_rolreplication), "t") == 0)
3429 heikki.linnakangas 882 18 : appendPQExpBufferStr(buf, " REPLICATION");
883 : else
884 39 : appendPQExpBufferStr(buf, " NOREPLICATION");
885 :
3124 sfrost 886 57 : if (strcmp(PQgetvalue(res, i, i_rolbypassrls), "t") == 0)
887 18 : appendPQExpBufferStr(buf, " BYPASSRLS");
888 : else
3124 sfrost 889 GBC 39 : appendPQExpBufferStr(buf, " NOBYPASSRLS");
890 :
6461 tgl 891 CBC 57 : if (strcmp(PQgetvalue(res, i, i_rolconnlimit), "-1") != 0)
6461 tgl 892 LBC 0 : appendPQExpBuffer(buf, " CONNECTION LIMIT %s",
893 : PQgetvalue(res, i, i_rolconnlimit));
7530 peter_e 894 ECB :
895 :
2224 simon 896 CBC 57 : if (!PQgetisnull(res, i, i_rolpassword) && !no_role_passwords)
6461 tgl 897 ECB : {
3429 heikki.linnakangas 898 UIC 0 : appendPQExpBufferStr(buf, " PASSWORD ");
6160 tgl 899 LBC 0 : appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolpassword), conn);
900 : }
6461 tgl 901 ECB :
6461 tgl 902 CBC 57 : if (!PQgetisnull(res, i, i_rolvaliduntil))
7254 tgl 903 UIC 0 : appendPQExpBuffer(buf, " VALID UNTIL '%s'",
6461 tgl 904 ECB : PQgetvalue(res, i, i_rolvaliduntil));
905 :
3429 heikki.linnakangas 906 CBC 57 : appendPQExpBufferStr(buf, ";\n");
7530 peter_e 907 ECB :
1900 tgl 908 GIC 57 : if (!no_comments && !PQgetisnull(res, i, i_rolcomment))
6031 bruce 909 ECB : {
6265 bruce 910 UIC 0 : appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
6160 tgl 911 LBC 0 : appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolcomment), conn);
3429 heikki.linnakangas 912 0 : appendPQExpBufferStr(buf, ";\n");
913 : }
6265 bruce 914 ECB :
481 tgl 915 GIC 57 : if (!no_security_labels)
4281 rhaas 916 CBC 57 : buildShSecLabels(conn, "pg_authid", auth_oid,
1868 tgl 917 EUB : "ROLE", rolename,
918 : buf);
919 :
5918 bruce 920 GIC 57 : fprintf(OPF, "%s", buf->data);
7530 peter_e 921 ECB : }
922 :
4195 rhaas 923 EUB : /*
924 : * Dump configuration settings for roles after all roles have been dumped.
925 : * We do it this way because config settings for roles could mention the
926 : * names of other roles.
4195 rhaas 927 ECB : */
481 tgl 928 GBC 18 : if (PQntuples(res) > 0)
481 tgl 929 GIC 18 : fprintf(OPF, "\n--\n-- User Configurations\n--\n");
930 :
2370 tgl 931 CBC 75 : for (i = 0; i < PQntuples(res); i++)
2370 tgl 932 GIC 57 : dumpUserConfig(conn, PQgetvalue(res, i, i_rolname));
4195 rhaas 933 ECB :
7530 peter_e 934 GIC 18 : PQclear(res);
6484 tgl 935 EUB :
5918 bruce 936 GBC 18 : fprintf(OPF, "\n\n");
6484 tgl 937 EUB :
6484 tgl 938 GIC 18 : destroyPQExpBuffer(buf);
7530 peter_e 939 18 : }
7530 peter_e 940 ECB :
941 :
942 : /*
943 : * Dump role memberships.
944 : *
6461 tgl 945 : * Note: we expect dumpRoles already created all the roles, but there is
946 : * no membership yet.
947 : */
948 : static void
6461 tgl 949 GIC 18 : dumpRoleMembership(PGconn *conn)
950 : {
2224 simon 951 18 : PQExpBuffer buf = createPQExpBuffer();
227 rhaas 952 GNC 18 : PQExpBuffer optbuf = createPQExpBuffer();
953 : PGresult *res;
230 954 18 : int start = 0,
955 : end,
956 : total;
957 : bool dump_grantors;
958 : bool dump_grant_options;
959 : int i_inherit_option;
960 : int i_set_option;
6461 tgl 961 ECB :
962 : /*
963 : * Previous versions of PostgreSQL didn't used to track the grantor very
964 : * carefully in the backend, and the grantor could be any user even if
965 : * they didn't have ADMIN OPTION on the role, or a user that no longer
966 : * existed. To avoid dump and restore failures, don't dump the grantor
967 : * when talking to an old server version.
968 : */
230 rhaas 969 GNC 18 : dump_grantors = (PQserverVersion(conn) >= 160000);
970 :
971 : /*
972 : * Previous versions of PostgreSQL also did not have grant-level options.
973 : */
142 974 18 : dump_grant_options = (server_version >= 160000);
975 :
976 : /* Generate and execute query. */
230 977 18 : printfPQExpBuffer(buf, "SELECT ur.rolname AS role, "
2153 bruce 978 ECB : "um.rolname AS member, "
979 : "ug.oid AS grantorid, "
980 : "ug.rolname AS grantor, "
981 : "a.admin_option");
142 rhaas 982 GNC 18 : if (dump_grant_options)
983 18 : appendPQExpBufferStr(buf, ", a.inherit_option, a.set_option");
227 984 18 : appendPQExpBuffer(buf, " FROM pg_auth_members a "
985 : "LEFT JOIN %s ur on ur.oid = a.roleid "
2153 bruce 986 ECB : "LEFT JOIN %s um on um.oid = a.member "
987 : "LEFT JOIN %s ug on ug.oid = a.grantor "
2118 tgl 988 : "WHERE NOT (ur.rolname ~ '^pg_' AND um.rolname ~ '^pg_')"
989 : "ORDER BY 1,2,4", role_catalog, role_catalog, role_catalog);
2224 simon 990 GIC 18 : res = executeQuery(conn, buf->data);
227 rhaas 991 GNC 18 : i_inherit_option = PQfnumber(res, "inherit_option");
142 992 18 : i_set_option = PQfnumber(res, "set_option");
993 :
6390 tgl 994 GIC 18 : if (PQntuples(res) > 0)
5918 bruce 995 UIC 0 : fprintf(OPF, "--\n-- Role memberships\n--\n\n");
996 :
997 : /*
998 : * We can't dump these GRANT commands in arbitrary order, because a role
999 : * that is named as a grantor must already have ADMIN OPTION on the
1000 : * role for which it is granting permissions, except for the boostrap
1001 : * superuser, who can always be named as the grantor.
1002 : *
1003 : * We handle this by considering these grants role by role. For each role,
1004 : * we initially consider the only allowable grantor to be the boostrap
1005 : * superuser. Every time we grant ADMIN OPTION on the role to some user,
1006 : * that user also becomes an allowable grantor. We make repeated passes
1007 : * over the grants for the role, each time dumping those whose grantors
1008 : * are allowable and which we haven't done yet. Eventually this should
1009 : * let us dump all the grants.
1010 : */
230 rhaas 1011 GNC 18 : total = PQntuples(res);
1012 18 : while (start < total)
1013 : {
230 rhaas 1014 UNC 0 : char *role = PQgetvalue(res, start, 0);
1015 : int i;
1016 : bool *done;
1017 : int remaining;
1018 0 : int prev_remaining = 0;
1019 : rolename_hash *ht;
1020 :
1021 : /* All memberships for a single role should be adjacent. */
1022 0 : for (end = start; end < total; ++end)
1023 : {
1024 : char *otherrole;
1025 :
1026 0 : otherrole = PQgetvalue(res, end, 0);
1027 0 : if (strcmp(role, otherrole) != 0)
1028 0 : break;
1029 : }
1030 :
1031 0 : role = PQgetvalue(res, start, 0);
1032 0 : remaining = end - start;
1033 0 : done = pg_malloc0(remaining * sizeof(bool));
1034 0 : ht = rolename_create(remaining, NULL);
1035 :
1036 : /*
1037 : * Make repeated passes over the grants for this role until all have
1038 : * been dumped.
1039 : */
1040 0 : while (remaining > 0)
1041 : {
1042 : /*
1043 : * We should make progress on every iteration, because a notional
1044 : * graph whose vertices are grants and whose edges point from
1045 : * grantors to members should be connected and acyclic. If we fail
1046 : * to make progress, either we or the server have messed up.
1047 : */
1048 0 : if (remaining == prev_remaining)
1049 : {
1050 0 : pg_log_error("could not find a legal dump ordering for memberships in role \"%s\"",
1051 : role);
1052 0 : PQfinish(conn);
1053 0 : exit_nicely(1);
1054 : }
1055 :
1056 : /* Make one pass over the grants for this role. */
1057 0 : for (i = start; i < end; ++i)
1058 : {
1059 : char *member;
1060 : char *admin_option;
1061 : char *grantorid;
1062 : char *grantor;
142 1063 0 : char *set_option = "true";
1064 : bool found;
1065 :
1066 : /* If we already did this grant, don't do it again. */
230 1067 0 : if (done[i - start])
1068 0 : continue;
1069 :
1070 0 : member = PQgetvalue(res, i, 1);
1071 0 : grantorid = PQgetvalue(res, i, 2);
1072 0 : grantor = PQgetvalue(res, i, 3);
1073 0 : admin_option = PQgetvalue(res, i, 4);
142 1074 0 : if (dump_grant_options)
1075 0 : set_option = PQgetvalue(res, i, i_set_option);
1076 :
1077 : /*
1078 : * If we're not dumping grantors or if the grantor is the
1079 : * bootstrap superuser, it's fine to dump this now. Otherwise,
1080 : * it's got to be someone who has already been granted ADMIN
1081 : * OPTION.
1082 : */
230 1083 0 : if (dump_grantors &&
1084 0 : atooid(grantorid) != BOOTSTRAP_SUPERUSERID &&
1085 0 : rolename_lookup(ht, grantor) == NULL)
1086 0 : continue;
1087 :
1088 : /* Remember that we did this so that we don't do it again. */
1089 0 : done[i - start] = true;
1090 0 : --remaining;
1091 :
1092 : /*
1093 : * If ADMIN OPTION is being granted, remember that grants
1094 : * listing this member as the grantor can now be dumped.
1095 : */
1096 0 : if (*admin_option == 't')
1097 0 : rolename_insert(ht, member, &found);
1098 :
1099 : /* Generate the actual GRANT statement. */
227 1100 0 : resetPQExpBuffer(optbuf);
230 1101 0 : fprintf(OPF, "GRANT %s", fmtId(role));
1102 0 : fprintf(OPF, " TO %s", fmtId(member));
1103 0 : if (*admin_option == 't')
227 1104 0 : appendPQExpBufferStr(optbuf, "ADMIN OPTION");
142 1105 0 : if (dump_grant_options)
1106 : {
1107 : char *inherit_option;
1108 :
227 1109 0 : if (optbuf->data[0] != '\0')
1110 0 : appendPQExpBufferStr(optbuf, ", ");
1111 0 : inherit_option = PQgetvalue(res, i, i_inherit_option);
1112 0 : appendPQExpBuffer(optbuf, "INHERIT %s",
1113 0 : *inherit_option == 't' ?
1114 : "TRUE" : "FALSE");
1115 : }
142 1116 0 : if (*set_option != 't')
1117 : {
1118 0 : if (optbuf->data[0] != '\0')
1119 0 : appendPQExpBufferStr(optbuf, ", ");
1120 0 : appendPQExpBuffer(optbuf, "SET FALSE");
1121 : }
227 1122 0 : if (optbuf->data[0] != '\0')
1123 0 : fprintf(OPF, " WITH %s", optbuf->data);
230 1124 0 : if (dump_grantors)
1125 0 : fprintf(OPF, " GRANTED BY %s", fmtId(grantor));
1126 0 : fprintf(OPF, ";\n");
1127 : }
1128 : }
1129 :
1130 0 : rolename_destroy(ht);
1131 0 : pg_free(done);
1132 0 : start = end;
1133 : }
1134 :
6461 tgl 1135 CBC 18 : PQclear(res);
2224 simon 1136 GIC 18 : destroyPQExpBuffer(buf);
1137 :
5918 bruce 1138 18 : fprintf(OPF, "\n\n");
6461 tgl 1139 18 : }
7530 peter_e 1140 ECB :
1141 :
1142 : /*
368 tgl 1143 : * Dump role configuration parameter privileges. This code is used for 15.0
1144 : * and later servers.
1145 : *
1146 : * Note: we expect dumpRoles already created all the roles, but there are
1147 : * no per-role configuration parameter privileges yet.
1148 : */
1149 : static void
368 tgl 1150 CBC 18 : dumpRoleGUCPrivs(PGconn *conn)
1151 : {
1152 : PGresult *res;
1153 : int i;
1154 :
1155 : /*
368 tgl 1156 ECB : * Get all parameters that have non-default acls defined.
1157 : */
368 tgl 1158 CBC 18 : res = executeQuery(conn, "SELECT parname, "
1159 : "pg_catalog.pg_get_userbyid(" CppAsString2(BOOTSTRAP_SUPERUSERID) ") AS parowner, "
368 tgl 1160 ECB : "paracl, "
368 tgl 1161 EUB : "pg_catalog.acldefault('p', " CppAsString2(BOOTSTRAP_SUPERUSERID) ") AS acldefault "
1162 : "FROM pg_catalog.pg_parameter_acl "
1163 : "ORDER BY 1");
1164 :
368 tgl 1165 GIC 18 : if (PQntuples(res) > 0)
1166 1 : fprintf(OPF, "--\n-- Role privileges on configuration parameters\n--\n\n");
1167 :
1168 21 : for (i = 0; i < PQntuples(res); i++)
1169 : {
1170 3 : PQExpBuffer buf = createPQExpBuffer();
1171 3 : char *parname = PQgetvalue(res, i, 0);
1172 3 : char *parowner = PQgetvalue(res, i, 1);
1173 3 : char *paracl = PQgetvalue(res, i, 2);
1174 3 : char *acldefault = PQgetvalue(res, i, 3);
1175 : char *fparname;
1176 :
368 tgl 1177 ECB : /* needed for buildACLCommands() */
368 tgl 1178 CBC 3 : fparname = pg_strdup(fmtId(parname));
1179 :
368 tgl 1180 GBC 3 : if (!buildACLCommands(fparname, NULL, NULL, "PARAMETER",
1181 : paracl, acldefault,
1182 : parowner, "", server_version, buf))
1183 : {
368 tgl 1184 UBC 0 : pg_log_error("could not parse ACL list (%s) for parameter \"%s\"",
1185 : paracl, parname);
368 tgl 1186 UIC 0 : PQfinish(conn);
1187 0 : exit_nicely(1);
368 tgl 1188 EUB : }
1189 :
368 tgl 1190 GIC 3 : fprintf(OPF, "%s", buf->data);
1191 :
368 tgl 1192 GBC 3 : free(fparname);
1193 3 : destroyPQExpBuffer(buf);
368 tgl 1194 EUB : }
1195 :
368 tgl 1196 GIC 18 : PQclear(res);
368 tgl 1197 GBC 18 : fprintf(OPF, "\n\n");
1198 18 : }
368 tgl 1199 EUB :
1200 :
1201 : /*
1202 : * Drop tablespaces.
1203 : */
1204 : static void
5111 tgl 1205 GIC 1 : dropTablespaces(PGconn *conn)
5111 tgl 1206 EUB : {
1207 : PGresult *res;
1208 : int i;
1209 :
1210 : /*
1211 : * Get all tablespaces except built-in ones (which we assume are named
1212 : * pg_xxx)
1213 : */
5111 tgl 1214 GBC 1 : res = executeQuery(conn, "SELECT spcname "
1215 : "FROM pg_catalog.pg_tablespace "
5111 tgl 1216 EUB : "WHERE spcname !~ '^pg_' "
1217 : "ORDER BY 1");
1218 :
5111 tgl 1219 GBC 1 : if (PQntuples(res) > 0)
5111 tgl 1220 UIC 0 : fprintf(OPF, "--\n-- Drop tablespaces\n--\n\n");
1221 :
5111 tgl 1222 GIC 1 : for (i = 0; i < PQntuples(res); i++)
5111 tgl 1223 EUB : {
5111 tgl 1224 UIC 0 : char *spcname = PQgetvalue(res, i, 0);
1225 :
3324 alvherre 1226 0 : fprintf(OPF, "DROP TABLESPACE %s%s;\n",
1227 0 : if_exists ? "IF EXISTS " : "",
1228 : fmtId(spcname));
5111 tgl 1229 EUB : }
1230 :
5111 tgl 1231 GIC 1 : PQclear(res);
1232 :
5111 tgl 1233 GBC 1 : fprintf(OPF, "\n\n");
1234 1 : }
1235 :
6869 tgl 1236 EUB : /*
1237 : * Dump tablespaces.
1238 : */
1239 : static void
6869 tgl 1240 GBC 13 : dumpTablespaces(PGconn *conn)
6869 tgl 1241 EUB : {
1242 : PGresult *res;
1243 : int i;
1244 :
1245 : /*
1246 : * Get all tablespaces except built-in ones (which we assume are named
1247 : * pg_xxx)
1248 : */
481 tgl 1249 GBC 13 : res = executeQuery(conn, "SELECT oid, spcname, "
481 tgl 1250 EUB : "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
1251 : "pg_catalog.pg_tablespace_location(oid), "
1252 : "spcacl, acldefault('t', spcowner) AS acldefault, "
1253 : "array_to_string(spcoptions, ', '),"
1254 : "pg_catalog.shobj_description(oid, 'pg_tablespace') "
1255 : "FROM pg_catalog.pg_tablespace "
1256 : "WHERE spcname !~ '^pg_' "
1257 : "ORDER BY 1");
1258 :
6838 bruce 1259 GIC 13 : if (PQntuples(res) > 0)
5918 bruce 1260 UIC 0 : fprintf(OPF, "--\n-- Tablespaces\n--\n\n");
1261 :
6869 tgl 1262 GBC 13 : for (i = 0; i < PQntuples(res); i++)
6869 tgl 1263 EUB : {
6869 tgl 1264 UIC 0 : PQExpBuffer buf = createPQExpBuffer();
1868 1265 0 : Oid spcoid = atooid(PQgetvalue(res, i, 0));
4281 rhaas 1266 UBC 0 : char *spcname = PQgetvalue(res, i, 1);
1267 0 : char *spcowner = PQgetvalue(res, i, 2);
1268 0 : char *spclocation = PQgetvalue(res, i, 3);
1269 0 : char *spcacl = PQgetvalue(res, i, 4);
489 tgl 1270 0 : char *acldefault = PQgetvalue(res, i, 5);
2457 sfrost 1271 0 : char *spcoptions = PQgetvalue(res, i, 6);
2457 sfrost 1272 UIC 0 : char *spccomment = PQgetvalue(res, i, 7);
1273 : char *fspcname;
1274 :
6869 tgl 1275 EUB : /* needed for buildACLCommands() */
4153 bruce 1276 UBC 0 : fspcname = pg_strdup(fmtId(spcname));
6869 tgl 1277 EUB :
416 rhaas 1278 UBC 0 : if (binary_upgrade)
416 rhaas 1279 EUB : {
416 rhaas 1280 UIC 0 : appendPQExpBufferStr(buf, "\n-- For binary upgrade, must preserve pg_tablespace oid\n");
1281 0 : appendPQExpBuffer(buf, "SELECT pg_catalog.binary_upgrade_set_next_pg_tablespace_oid('%u'::pg_catalog.oid);\n", spcoid);
416 rhaas 1282 EUB : }
1283 :
6869 tgl 1284 UBC 0 : appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname);
1285 0 : appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
7530 peter_e 1286 EUB :
3429 heikki.linnakangas 1287 UIC 0 : appendPQExpBufferStr(buf, " LOCATION ");
6160 tgl 1288 UBC 0 : appendStringLiteralConn(buf, spclocation, conn);
3429 heikki.linnakangas 1289 0 : appendPQExpBufferStr(buf, ";\n");
6869 tgl 1290 EUB :
4842 rhaas 1291 UBC 0 : if (spcoptions && spcoptions[0] != '\0')
1292 0 : appendPQExpBuffer(buf, "ALTER TABLESPACE %s SET (%s);\n",
1293 : fspcname, spcoptions);
1294 :
1295 : /* tablespaces can't have initprivs */
489 tgl 1296 EUB :
6869 tgl 1297 UBC 0 : if (!skip_acls &&
1868 1298 0 : !buildACLCommands(fspcname, NULL, NULL, "TABLESPACE",
1299 : spcacl, acldefault,
1300 : spcowner, "", server_version, buf))
6869 tgl 1301 ECB : {
1469 peter 1302 LBC 0 : pg_log_error("could not parse ACL list (%s) for tablespace \"%s\"",
1303 : spcacl, spcname);
6869 tgl 1304 0 : PQfinish(conn);
4070 rhaas 1305 0 : exit_nicely(1);
1306 : }
1307 :
1900 tgl 1308 UIC 0 : if (!no_comments && spccomment && spccomment[0] != '\0')
1309 : {
6265 bruce 1310 0 : appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
6160 tgl 1311 0 : appendStringLiteralConn(buf, spccomment, conn);
3429 heikki.linnakangas 1312 0 : appendPQExpBufferStr(buf, ";\n");
1313 : }
1314 :
481 tgl 1315 0 : if (!no_security_labels)
4281 rhaas 1316 LBC 0 : buildShSecLabels(conn, "pg_tablespace", spcoid,
1317 : "TABLESPACE", spcname,
1318 : buf);
1319 :
5918 bruce 1320 UIC 0 : fprintf(OPF, "%s", buf->data);
1321 :
6869 tgl 1322 0 : free(fspcname);
1323 0 : destroyPQExpBuffer(buf);
6869 tgl 1324 ECB : }
1325 :
6869 tgl 1326 GIC 13 : PQclear(res);
5918 bruce 1327 13 : fprintf(OPF, "\n\n");
6869 tgl 1328 13 : }
1329 :
1330 :
5111 tgl 1331 ECB : /*
1332 : * Dump commands to drop each database.
1333 : */
1334 : static void
5111 tgl 1335 UIC 0 : dropDBs(PGconn *conn)
5111 tgl 1336 ECB : {
1337 : PGresult *res;
1338 : int i;
1339 :
1903 1340 : /*
1341 : * Skip databases marked not datallowconn, since we'd be unable to connect
1342 : * to them anyway. This must agree with dumpDatabases().
1343 : */
2370 tgl 1344 LBC 0 : res = executeQuery(conn,
1345 : "SELECT datname "
2370 tgl 1346 ECB : "FROM pg_database d "
1347 : "WHERE datallowconn "
1348 : "ORDER BY datname");
1349 :
5111 tgl 1350 UBC 0 : if (PQntuples(res) > 0)
1903 tgl 1351 UIC 0 : fprintf(OPF, "--\n-- Drop databases (except postgres and template1)\n--\n\n");
5111 tgl 1352 EUB :
5111 tgl 1353 UBC 0 : for (i = 0; i < PQntuples(res); i++)
1354 : {
5111 tgl 1355 UIC 0 : char *dbname = PQgetvalue(res, i, 0);
5111 tgl 1356 ECB :
1357 : /*
1903 1358 : * Skip "postgres" and "template1"; dumpDatabases() will deal with
1359 : * them specially. Also, be sure to skip "template0", even if for
1360 : * some reason it's not marked !datallowconn.
1361 : */
5111 tgl 1362 LBC 0 : if (strcmp(dbname, "template1") != 0 &&
1903 1363 0 : strcmp(dbname, "template0") != 0 &&
5111 1364 0 : strcmp(dbname, "postgres") != 0)
1365 : {
3324 alvherre 1366 UIC 0 : fprintf(OPF, "DROP DATABASE %s%s;\n",
1367 0 : if_exists ? "IF EXISTS " : "",
1368 : fmtId(dbname));
1369 : }
1370 : }
5111 tgl 1371 ECB :
5111 tgl 1372 UIC 0 : PQclear(res);
1373 :
1374 0 : fprintf(OPF, "\n\n");
1375 0 : }
1376 :
1377 :
1378 : /*
1379 : * Dump user-specific configuration
7529 peter_e 1380 ECB : */
1381 : static void
7529 peter_e 1382 GIC 57 : dumpUserConfig(PGconn *conn, const char *username)
1383 : {
1384 57 : PQExpBuffer buf = createPQExpBuffer();
481 tgl 1385 ECB : PGresult *res;
7529 peter_e 1386 EUB :
121 akorotkov 1387 GNC 57 : printfPQExpBuffer(buf, "SELECT unnest(setconfig)");
1388 57 : if (server_version >= 160000)
1389 57 : appendPQExpBufferStr(buf, ", unnest(setuser)");
1390 57 : appendPQExpBuffer(buf, " FROM pg_db_role_setting "
481 tgl 1391 ECB : "WHERE setdatabase = 0 AND setrole = "
1392 : "(SELECT oid FROM %s WHERE rolname = ",
481 tgl 1393 EUB : role_catalog);
481 tgl 1394 GIC 57 : appendStringLiteralConn(buf, username, conn);
481 tgl 1395 GBC 57 : appendPQExpBufferChar(buf, ')');
1500 andrew 1396 EUB :
481 tgl 1397 GIC 57 : res = executeQuery(conn, buf->data);
1398 :
1399 57 : if (PQntuples(res) > 0)
481 tgl 1400 LBC 0 : fprintf(OPF, "\n--\n-- User Config \"%s\"\n--\n\n", username);
1401 :
481 tgl 1402 CBC 57 : for (int i = 0; i < PQntuples(res); i++)
481 tgl 1403 ECB : {
121 akorotkov 1404 UNC 0 : char *userset = NULL;
1405 :
1406 0 : if (server_version >= 160000)
1407 0 : userset = PQgetvalue(res, i, 1);
1408 :
481 tgl 1409 UIC 0 : resetPQExpBuffer(buf);
121 akorotkov 1410 UNC 0 : makeAlterConfigCommand(conn, PQgetvalue(res, i, 0), userset,
1411 : "ROLE", username, NULL, NULL,
1412 : buf);
481 tgl 1413 UIC 0 : fprintf(OPF, "%s", buf->data);
7529 peter_e 1414 ECB : }
1415 :
481 tgl 1416 GIC 57 : PQclear(res);
1417 :
7529 peter_e 1418 57 : destroyPQExpBuffer(buf);
1419 57 : }
1420 :
1421 : /*
1422 : * Find a list of database names that match the given patterns.
1500 andrew 1423 ECB : * See also expand_table_name_patterns() in pg_dump.c
1424 : */
1425 : static void
1500 andrew 1426 GIC 20 : expand_dbname_patterns(PGconn *conn,
1427 : SimpleStringList *patterns,
1428 : SimpleStringList *names)
1429 : {
1430 : PQExpBuffer query;
1431 : PGresult *res;
1432 :
1500 andrew 1433 CBC 20 : if (patterns->head == NULL)
1500 andrew 1434 GBC 16 : return; /* nothing to do */
1435 :
1500 andrew 1436 CBC 4 : query = createPQExpBuffer();
1437 :
1500 andrew 1438 EUB : /*
1439 : * The loop below runs multiple SELECTs, which might sometimes result in
1418 tgl 1440 : * duplicate entries in the name list, but we don't care, since all we're
1441 : * going to do is test membership of the list.
1500 andrew 1442 : */
1443 :
1500 andrew 1444 GBC 6 : for (SimpleStringListCell *cell = patterns->head; cell; cell = cell->next)
1500 andrew 1445 EUB : {
332 tgl 1446 : int dotcnt;
1447 :
1375 drowley 1448 GIC 4 : appendPQExpBufferStr(query,
1449 : "SELECT datname FROM pg_catalog.pg_database n\n");
1500 andrew 1450 GBC 4 : processSQLNamePattern(conn, query, cell->val, false,
1451 : false, NULL, "datname", NULL, NULL, NULL,
354 rhaas 1452 EUB : &dotcnt);
1453 :
354 rhaas 1454 GBC 4 : if (dotcnt > 0)
354 rhaas 1455 EUB : {
354 rhaas 1456 GIC 2 : pg_log_error("improper qualified name (too many dotted names): %s",
1457 : cell->val);
354 rhaas 1458 GBC 2 : PQfinish(conn);
1459 2 : exit_nicely(1);
1460 : }
1500 andrew 1461 EUB :
1500 andrew 1462 GBC 2 : res = executeQuery(conn, query->data);
1463 5 : for (int i = 0; i < PQntuples(res); i++)
1464 : {
1465 3 : simple_string_list_append(names, PQgetvalue(res, i, 0));
1500 andrew 1466 EUB : }
1467 :
1500 andrew 1468 GIC 2 : PQclear(res);
1469 2 : resetPQExpBuffer(query);
1470 : }
1500 andrew 1471 EUB :
1500 andrew 1472 GBC 2 : destroyPQExpBuffer(query);
1473 : }
1474 :
1475 : /*
7530 peter_e 1476 EUB : * Dump contents of databases.
1477 : */
1478 : static void
7530 peter_e 1479 GBC 9 : dumpDatabases(PGconn *conn)
1480 : {
1481 : PGresult *res;
7522 bruce 1482 EUB : int i;
1483 :
1903 tgl 1484 : /*
1485 : * Skip databases marked not datallowconn, since we'd be unable to connect
1486 : * to them anyway. This must agree with dropDBs().
1487 : *
1488 : * We arrange for template1 to be processed first, then we process other
1489 : * DBs in alphabetical order. If we just did them all alphabetically, we
1490 : * might find ourselves trying to drop the "postgres" database while still
1491 : * connected to it. This makes trying to run the restore script while
1492 : * connected to "template1" a bad idea, but there's no fixed order that
1493 : * doesn't have some failure mode with --clean.
1494 : */
1903 tgl 1495 GIC 9 : res = executeQuery(conn,
1903 tgl 1496 EUB : "SELECT datname "
1497 : "FROM pg_database d "
1498 : "WHERE datallowconn "
1499 : "ORDER BY (datname <> 'template1'), datname");
7254 tgl 1500 ECB :
1500 andrew 1501 CBC 9 : if (PQntuples(res) > 0)
1502 9 : fprintf(OPF, "--\n-- Databases\n--\n\n");
1503 :
7530 peter_e 1504 GIC 52 : for (i = 0; i < PQntuples(res); i++)
1505 : {
1903 tgl 1506 44 : char *dbname = PQgetvalue(res, i, 0);
1507 : const char *create_opts;
1508 : int ret;
7522 bruce 1509 EUB :
1510 : /* Skip template0, even if it's not marked !datallowconn. */
1903 tgl 1511 GIC 44 : if (strcmp(dbname, "template0") == 0)
1903 tgl 1512 UIC 0 : continue;
1513 :
1514 : /* Skip any explicitly excluded database */
1500 andrew 1515 GIC 44 : if (simple_string_list_member(&database_exclude_names, dbname))
1516 : {
1370 peter 1517 3 : pg_log_info("excluding database \"%s\"", dbname);
1500 andrew 1518 GBC 3 : continue;
1519 : }
1520 :
1370 peter 1521 GIC 41 : pg_log_info("dumping database \"%s\"", dbname);
1522 :
1500 andrew 1523 41 : fprintf(OPF, "--\n-- Database \"%s\" dump\n--\n\n", dbname);
1500 andrew 1524 EUB :
3417 kgrittn 1525 : /*
1526 : * We assume that "template1" and "postgres" already exist in the
1903 tgl 1527 : * target installation. dropDBs() won't have removed them, for fear
1528 : * of removing the DB the restore script is initially connected to. If
1529 : * --clean was specified, tell pg_dump to drop and recreate them;
1530 : * otherwise we'll merely restore their contents. Other databases
1531 : * should simply be created.
1532 : */
1903 tgl 1533 GIC 41 : if (strcmp(dbname, "template1") == 0 || strcmp(dbname, "postgres") == 0)
1534 : {
1535 17 : if (output_clean)
1903 tgl 1536 UBC 0 : create_opts = "--clean --create";
1903 tgl 1537 EUB : else
1538 : {
1903 tgl 1539 GIC 17 : create_opts = "";
1903 tgl 1540 EUB : /* Since pg_dump won't emit a \connect command, we must */
1903 tgl 1541 GBC 17 : fprintf(OPF, "\\connect %s\n\n", dbname);
1542 : }
1543 : }
1544 : else
1903 tgl 1545 GIC 24 : create_opts = "--create";
3417 kgrittn 1546 EUB :
5918 bruce 1547 GIC 41 : if (filename)
5918 bruce 1548 GBC 35 : fclose(OPF);
5624 bruce 1549 EUB :
1903 tgl 1550 GIC 41 : ret = runPgDump(dbname, create_opts);
7530 peter_e 1551 40 : if (ret != 0)
366 tgl 1552 UIC 0 : pg_fatal("pg_dump failed on database \"%s\", exiting", dbname);
1553 :
5918 bruce 1554 GIC 40 : if (filename)
1555 : {
5918 bruce 1556 CBC 34 : OPF = fopen(filename, PG_BINARY_A);
5918 bruce 1557 GIC 34 : if (!OPF)
366 tgl 1558 LBC 0 : pg_fatal("could not re-open the output file \"%s\": %m",
1559 : filename);
1560 : }
7530 peter_e 1561 ECB : }
1562 :
7530 peter_e 1563 CBC 8 : PQclear(res);
1564 8 : }
1565 :
1566 :
1567 :
7530 peter_e 1568 ECB : /*
1903 tgl 1569 : * Run pg_dump on dbname, with specified options.
1570 : */
7530 peter_e 1571 : static int
1903 tgl 1572 GIC 41 : runPgDump(const char *dbname, const char *create_opts)
7530 peter_e 1573 ECB : {
3695 heikki.linnakangas 1574 GBC 41 : PQExpBuffer connstrbuf = createPQExpBuffer();
7530 peter_e 1575 GIC 41 : PQExpBuffer cmd = createPQExpBuffer();
7522 bruce 1576 ECB : int ret;
1577 :
1903 tgl 1578 GBC 41 : appendPQExpBuffer(cmd, "\"%s\" %s %s", pg_dump_bin,
1903 tgl 1579 GIC 41 : pgdumpopts->data, create_opts);
5207 tgl 1580 EUB :
6818 bruce 1581 : /*
1582 : * If we have a filename, use the undocumented plain-append pg_dump
5624 1583 : * format.
6797 1584 : */
5918 bruce 1585 GIC 41 : if (filename)
3429 heikki.linnakangas 1586 35 : appendPQExpBufferStr(cmd, " -Fa ");
5918 bruce 1587 EUB : else
3429 heikki.linnakangas 1588 GIC 6 : appendPQExpBufferStr(cmd, " -Fp ");
1589 :
3700 heikki.linnakangas 1590 ECB : /*
1591 : * Append the database name to the already-constructed stem of connection
3695 1592 : * string.
3700 1593 : */
3695 heikki.linnakangas 1594 GIC 41 : appendPQExpBuffer(connstrbuf, "%s dbname=", connstr);
2435 noah 1595 41 : appendConnStrVal(connstrbuf, dbname);
1596 :
1597 41 : appendShellString(cmd, connstrbuf->data);
1598 :
1469 peter 1599 40 : pg_log_info("running \"%s\"", cmd->data);
7530 peter_e 1600 ECB :
223 tgl 1601 GNC 40 : fflush(NULL);
1602 :
7530 peter_e 1603 GIC 40 : ret = system(cmd->data);
1604 :
1605 40 : destroyPQExpBuffer(cmd);
3695 heikki.linnakangas 1606 CBC 40 : destroyPQExpBuffer(connstrbuf);
7530 peter_e 1607 ECB :
7530 peter_e 1608 GIC 40 : return ret;
7530 peter_e 1609 ECB : }
1610 :
1611 : /*
1612 : * buildShSecLabels
1613 : *
1614 : * Build SECURITY LABEL command(s) for a shared object
1615 : *
1616 : * The caller has to provide object type and identity in two separate formats:
1868 tgl 1617 : * catalog_name (e.g., "pg_database") and object OID, as well as
1618 : * type name (e.g., "DATABASE") and object name (not pre-quoted).
1619 : *
1620 : * The command(s) are appended to "buffer".
4281 rhaas 1621 : */
1622 : static void
1868 tgl 1623 CBC 57 : buildShSecLabels(PGconn *conn, const char *catalog_name, Oid objectId,
1624 : const char *objtype, const char *objname,
1625 : PQExpBuffer buffer)
1626 : {
3955 bruce 1627 57 : PQExpBuffer sql = createPQExpBuffer();
1628 : PGresult *res;
4281 rhaas 1629 ECB :
957 peter 1630 GIC 57 : buildShSecLabelQuery(catalog_name, objectId, sql);
4281 rhaas 1631 CBC 57 : res = executeQuery(conn, sql->data);
1868 tgl 1632 57 : emitShSecLabels(conn, res, buffer, objtype, objname);
1633 :
4281 rhaas 1634 GIC 57 : PQclear(res);
4281 rhaas 1635 CBC 57 : destroyPQExpBuffer(sql);
1636 57 : }
1637 :
7530 peter_e 1638 ECB : /*
1639 : * Make a database connection with the given parameters. An
1640 : * interactive password prompt is automatically issued if required.
6484 tgl 1641 : *
1642 : * If fail_on_error is false, we return NULL without printing any message
1643 : * on failure, but preserve any prompted password for the next try.
1644 : *
3695 heikki.linnakangas 1645 : * On success, the global variable 'connstr' is set to a connection string
1646 : * containing the options used.
1647 : */
1648 : static PGconn *
3695 heikki.linnakangas 1649 GIC 20 : connectDatabase(const char *dbname, const char *connection_string,
1650 : const char *pghost, const char *pgport, const char *pguser,
1651 : trivalue prompt_password, bool fail_on_error)
7530 peter_e 1652 ECB : {
1653 : PGconn *conn;
1654 : bool new_pass;
1655 : const char *remoteversion_str;
1656 : int my_version;
3695 heikki.linnakangas 1657 GIC 20 : const char **keywords = NULL;
1658 20 : const char **values = NULL;
1659 20 : PQconninfoOption *conn_opts = NULL;
1660 : static char *password = NULL;
1661 :
948 tgl 1662 20 : if (prompt_password == TRI_YES && !password)
948 tgl 1663 UIC 0 : password = simple_prompt("Password: ", false);
1664 :
1665 : /*
1666 : * Start the connection. Loop until we have a password if requested by
1667 : * backend.
7530 peter_e 1668 ECB : */
1669 : do
1670 : {
3695 heikki.linnakangas 1671 GIC 20 : int argcount = 6;
1672 : PQconninfoOption *conn_opt;
1673 20 : char *err_msg = NULL;
3695 heikki.linnakangas 1674 CBC 20 : int i = 0;
3695 heikki.linnakangas 1675 ECB :
297 peter 1676 GNC 20 : free(keywords);
1677 20 : free(values);
280 1678 20 : PQconninfoFree(conn_opts);
1679 :
1680 : /*
3695 heikki.linnakangas 1681 ECB : * Merge the connection info inputs given in form of connection string
2435 noah 1682 EUB : * and other options. Explicitly discard any dbname value in the
1683 : * connection string; otherwise, PQconnectdbParams() would interpret
1684 : * that value as being itself a connection string.
3695 heikki.linnakangas 1685 ECB : */
3695 heikki.linnakangas 1686 GIC 20 : if (connection_string)
3695 heikki.linnakangas 1687 ECB : {
3695 heikki.linnakangas 1688 CBC 20 : conn_opts = PQconninfoParse(connection_string, &err_msg);
3695 heikki.linnakangas 1689 GIC 20 : if (conn_opts == NULL)
366 tgl 1690 UIC 0 : pg_fatal("%s", err_msg);
3695 heikki.linnakangas 1691 ECB :
3695 heikki.linnakangas 1692 GIC 800 : for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
3695 heikki.linnakangas 1693 ECB : {
2435 noah 1694 GIC 780 : if (conn_opt->val != NULL && conn_opt->val[0] != '\0' &&
1695 18 : strcmp(conn_opt->keyword, "dbname") != 0)
3695 heikki.linnakangas 1696 12 : argcount++;
1697 : }
1698 :
1699 20 : keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
1700 20 : values = pg_malloc0((argcount + 1) * sizeof(*values));
1701 :
1702 800 : for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
3695 heikki.linnakangas 1703 ECB : {
2435 noah 1704 GIC 780 : if (conn_opt->val != NULL && conn_opt->val[0] != '\0' &&
2435 noah 1705 CBC 18 : strcmp(conn_opt->keyword, "dbname") != 0)
3695 heikki.linnakangas 1706 EUB : {
3695 heikki.linnakangas 1707 GIC 12 : keywords[i] = conn_opt->keyword;
1708 12 : values[i] = conn_opt->val;
3695 heikki.linnakangas 1709 CBC 12 : i++;
1710 : }
3695 heikki.linnakangas 1711 ECB : }
1712 : }
1713 : else
1714 : {
3695 heikki.linnakangas 1715 LBC 0 : keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
3695 heikki.linnakangas 1716 UIC 0 : values = pg_malloc0((argcount + 1) * sizeof(*values));
3695 heikki.linnakangas 1717 ECB : }
1718 :
3695 heikki.linnakangas 1719 GIC 20 : if (pghost)
3695 heikki.linnakangas 1720 ECB : {
3695 heikki.linnakangas 1721 CBC 1 : keywords[i] = "host";
3695 heikki.linnakangas 1722 GBC 1 : values[i] = pghost;
3695 heikki.linnakangas 1723 GIC 1 : i++;
3695 heikki.linnakangas 1724 ECB : }
3695 heikki.linnakangas 1725 GIC 20 : if (pgport)
3695 heikki.linnakangas 1726 ECB : {
3695 heikki.linnakangas 1727 CBC 4 : keywords[i] = "port";
3695 heikki.linnakangas 1728 GBC 4 : values[i] = pgport;
3695 heikki.linnakangas 1729 GIC 4 : i++;
1730 : }
1731 20 : if (pguser)
1732 : {
3695 heikki.linnakangas 1733 CBC 8 : keywords[i] = "user";
1734 8 : values[i] = pguser;
3695 heikki.linnakangas 1735 GIC 8 : i++;
1736 : }
948 tgl 1737 20 : if (password)
1738 : {
3695 heikki.linnakangas 1739 UIC 0 : keywords[i] = "password";
1740 0 : values[i] = password;
1741 0 : i++;
3695 heikki.linnakangas 1742 ECB : }
3695 heikki.linnakangas 1743 GIC 20 : if (dbname)
3695 heikki.linnakangas 1744 ECB : {
3695 heikki.linnakangas 1745 CBC 20 : keywords[i] = "dbname";
3695 heikki.linnakangas 1746 GIC 20 : values[i] = dbname;
1747 20 : i++;
3695 heikki.linnakangas 1748 ECB : }
3695 heikki.linnakangas 1749 CBC 20 : keywords[i] = "fallback_application_name";
3695 heikki.linnakangas 1750 GIC 20 : values[i] = progname;
1751 20 : i++;
1752 :
5754 tgl 1753 20 : new_pass = false;
4811 mail 1754 20 : conn = PQconnectdbParams(keywords, values, true);
4811 mail 1755 ECB :
7530 peter_e 1756 CBC 20 : if (!conn)
366 tgl 1757 UIC 0 : pg_fatal("could not connect to database \"%s\"", dbname);
7530 peter_e 1758 ECB :
7530 peter_e 1759 GIC 20 : if (PQstatus(conn) == CONNECTION_BAD &&
5600 tgl 1760 UIC 0 : PQconnectionNeedsPassword(conn) &&
948 1761 0 : !password &&
1762 : prompt_password != TRI_NO)
1763 : {
7530 peter_e 1764 LBC 0 : PQfinish(conn);
948 tgl 1765 0 : password = simple_prompt("Password: ", false);
5754 tgl 1766 UIC 0 : new_pass = true;
7530 peter_e 1767 ECB : }
5754 tgl 1768 GIC 20 : } while (new_pass);
7530 peter_e 1769 ECB :
1770 : /* check to see that the backend connection was successfully made */
7530 peter_e 1771 CBC 20 : if (PQstatus(conn) == CONNECTION_BAD)
1772 : {
6484 tgl 1773 LBC 0 : if (fail_on_error)
366 tgl 1774 UIC 0 : pg_fatal("%s", PQerrorMessage(conn));
6484 tgl 1775 ECB : else
1776 : {
6484 tgl 1777 UIC 0 : PQfinish(conn);
3695 heikki.linnakangas 1778 ECB :
3695 heikki.linnakangas 1779 UIC 0 : free(keywords);
1780 0 : free(values);
1781 0 : PQconninfoFree(conn_opts);
1782 :
6484 tgl 1783 0 : return NULL;
1784 : }
1785 : }
1786 :
1787 : /*
1788 : * Ok, connected successfully. Remember the options used, in the form of a
1789 : * connection string.
1790 : */
3695 heikki.linnakangas 1791 GIC 20 : connstr = constructConnStr(keywords, values);
1792 :
3695 heikki.linnakangas 1793 CBC 20 : free(keywords);
3695 heikki.linnakangas 1794 GIC 20 : free(values);
1795 20 : PQconninfoFree(conn_opts);
1796 :
3695 heikki.linnakangas 1797 ECB : /* Check version */
7231 tgl 1798 GIC 20 : remoteversion_str = PQparameterStatus(conn, "server_version");
1799 20 : if (!remoteversion_str)
366 tgl 1800 LBC 0 : pg_fatal("could not get server version");
3666 heikki.linnakangas 1801 CBC 20 : server_version = PQserverVersion(conn);
1802 20 : if (server_version == 0)
366 tgl 1803 UIC 0 : pg_fatal("could not parse server version \"%s\"",
366 tgl 1804 ECB : remoteversion_str);
7530 peter_e 1805 :
3666 heikki.linnakangas 1806 CBC 20 : my_version = PG_VERSION_NUM;
1807 :
1808 : /*
1809 : * We allow the server to be back to 9.2, and up to any minor release of
1810 : * our own major version. (See also version check in pg_dump.c.)
1811 : */
6565 tgl 1812 GIC 20 : if (my_version != server_version
481 tgl 1813 UIC 0 : && (server_version < 90200 ||
5474 1814 0 : (server_version / 100) > (my_version / 100)))
1815 : {
1469 peter 1816 0 : pg_log_error("aborting because of server version mismatch");
366 tgl 1817 0 : pg_log_error_detail("server version: %s; %s version: %s",
1818 : remoteversion_str, progname, PG_VERSION);
4070 rhaas 1819 LBC 0 : exit_nicely(1);
1820 : }
1821 :
1868 noah 1822 GIC 20 : PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL));
1823 :
7530 peter_e 1824 20 : return conn;
1825 : }
1826 :
3695 heikki.linnakangas 1827 ECB : /* ----------
1828 : * Construct a connection string from the given keyword/value pairs. It is
1829 : * used to pass the connection options to the pg_dump subprocess.
1830 : *
1831 : * The following parameters are excluded:
1832 : * dbname - varies in each pg_dump invocation
3695 heikki.linnakangas 1833 EUB : * password - it's not secure to pass a password on the command line
1834 : * fallback_application_name - we'll let pg_dump set it
1835 : * ----------
1836 : */
1837 : static char *
3695 heikki.linnakangas 1838 GIC 20 : constructConnStr(const char **keywords, const char **values)
1839 : {
1840 20 : PQExpBuffer buf = createPQExpBuffer();
3695 heikki.linnakangas 1841 ECB : char *connstr;
1842 : int i;
3695 heikki.linnakangas 1843 CBC 20 : bool firstkeyword = true;
3695 heikki.linnakangas 1844 ECB :
1845 : /* Construct a new connection string in key='value' format. */
3695 heikki.linnakangas 1846 CBC 85 : for (i = 0; keywords[i] != NULL; i++)
3695 heikki.linnakangas 1847 ECB : {
3695 heikki.linnakangas 1848 CBC 65 : if (strcmp(keywords[i], "dbname") == 0 ||
3695 heikki.linnakangas 1849 GIC 45 : strcmp(keywords[i], "password") == 0 ||
1850 45 : strcmp(keywords[i], "fallback_application_name") == 0)
1851 40 : continue;
1852 :
1853 25 : if (!firstkeyword)
1854 12 : appendPQExpBufferChar(buf, ' ');
1855 25 : firstkeyword = false;
3695 heikki.linnakangas 1856 CBC 25 : appendPQExpBuffer(buf, "%s=", keywords[i]);
2435 noah 1857 GIC 25 : appendConnStrVal(buf, values[i]);
3695 heikki.linnakangas 1858 ECB : }
1859 :
3695 heikki.linnakangas 1860 GBC 20 : connstr = pg_strdup(buf->data);
3695 heikki.linnakangas 1861 GIC 20 : destroyPQExpBuffer(buf);
3695 heikki.linnakangas 1862 CBC 20 : return connstr;
1863 : }
7530 peter_e 1864 ECB :
1865 : /*
1866 : * Run a query, return the results, exit program on failure.
1867 : */
1868 : static PGresult *
7530 peter_e 1869 CBC 214 : executeQuery(PGconn *conn, const char *query)
7530 peter_e 1870 ECB : {
1871 : PGresult *res;
1872 :
1469 peter 1873 GIC 214 : pg_log_info("executing %s", query);
7254 tgl 1874 ECB :
7530 peter_e 1875 CBC 214 : res = PQexec(conn, query);
7530 peter_e 1876 GIC 428 : if (!res ||
7530 peter_e 1877 CBC 214 : PQresultStatus(res) != PGRES_TUPLES_OK)
7530 peter_e 1878 ECB : {
1469 peter 1879 LBC 0 : pg_log_error("query failed: %s", PQerrorMessage(conn));
366 tgl 1880 UIC 0 : pg_log_error_detail("Query was: %s", query);
7530 peter_e 1881 0 : PQfinish(conn);
4070 rhaas 1882 0 : exit_nicely(1);
1883 : }
1884 :
7530 peter_e 1885 GBC 214 : return res;
7530 peter_e 1886 EUB : }
1887 :
1888 : /*
6461 tgl 1889 ECB : * As above for a SQL command (which returns nothing).
1890 : */
1891 : static void
6461 tgl 1892 CBC 1 : executeCommand(PGconn *conn, const char *query)
6461 tgl 1893 ECB : {
1894 : PGresult *res;
1895 :
1469 peter 1896 GIC 1 : pg_log_info("executing %s", query);
6461 tgl 1897 ECB :
6461 tgl 1898 CBC 1 : res = PQexec(conn, query);
1899 2 : if (!res ||
6461 tgl 1900 GIC 1 : PQresultStatus(res) != PGRES_COMMAND_OK)
6461 tgl 1901 ECB : {
1469 peter 1902 UIC 0 : pg_log_error("query failed: %s", PQerrorMessage(conn));
366 tgl 1903 LBC 0 : pg_log_error_detail("Query was: %s", query);
6461 1904 0 : PQfinish(conn);
4070 rhaas 1905 0 : exit_nicely(1);
1906 : }
6461 tgl 1907 ECB :
6461 tgl 1908 GIC 1 : PQclear(res);
6461 tgl 1909 GBC 1 : }
6461 tgl 1910 EUB :
6880 bruce 1911 :
1912 : /*
6880 bruce 1913 ECB : * dumpTimestamp
1914 : */
1915 : static void
3087 tgl 1916 CBC 4 : dumpTimestamp(const char *msg)
6880 bruce 1917 ECB : {
1918 : char buf[64];
6797 bruce 1919 CBC 4 : time_t now = time(NULL);
6880 bruce 1920 ECB :
3087 tgl 1921 CBC 4 : if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&now)) != 0)
5918 bruce 1922 GIC 4 : fprintf(OPF, "-- %s %s\n\n", msg, buf);
6880 bruce 1923 CBC 4 : }
1924 :
1925 : /*
1926 : * Helper function for rolenamehash hash table.
1927 : */
1928 : static uint32
230 rhaas 1929 UNC 0 : hash_string_pointer(char *s)
1930 : {
1931 0 : unsigned char *ss = (unsigned char *) s;
1932 :
1933 0 : return hash_bytes(ss, strlen(s));
1934 : }
|