PostgreSQL Source Code  git master
pg_dumpall.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * pg_dumpall.c
4  *
5  * Portions Copyright (c) 1996-2022, 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/logging.h"
25 #include "common/string.h"
26 #include "dumputils.h"
27 #include "fe_utils/string_utils.h"
28 #include "getopt_long.h"
29 #include "pg_backup.h"
30 
31 /* version string we expect back from pg_dump */
32 #define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
33 
34 
35 static void help(void);
36 
37 static void dropRoles(PGconn *conn);
38 static void dumpRoles(PGconn *conn);
39 static void dumpRoleMembership(PGconn *conn);
40 static void dumpRoleGUCPrivs(PGconn *conn);
41 static void dropTablespaces(PGconn *conn);
42 static void dumpTablespaces(PGconn *conn);
43 static void dropDBs(PGconn *conn);
44 static void dumpUserConfig(PGconn *conn, const char *username);
45 static void dumpDatabases(PGconn *conn);
46 static void dumpTimestamp(const char *msg);
47 static int runPgDump(const char *dbname, const char *create_opts);
48 static void buildShSecLabels(PGconn *conn,
49  const char *catalog_name, Oid objectId,
50  const char *objtype, const char *objname,
51  PQExpBuffer buffer);
52 static PGconn *connectDatabase(const char *dbname, const char *connstr, const char *pghost, const char *pgport,
53  const char *pguser, trivalue prompt_password, bool fail_on_error);
54 static char *constructConnStr(const char **keywords, const char **values);
55 static PGresult *executeQuery(PGconn *conn, const char *query);
56 static void executeCommand(PGconn *conn, const char *query);
57 static void expand_dbname_patterns(PGconn *conn, SimpleStringList *patterns,
58  SimpleStringList *names);
59 
60 static char pg_dump_bin[MAXPGPATH];
61 static const char *progname;
63 static char *connstr = "";
64 static bool output_clean = false;
65 static bool skip_acls = false;
66 static bool verbose = false;
67 static bool dosync = true;
68 
69 static int binary_upgrade = 0;
70 static int column_inserts = 0;
71 static int disable_dollar_quoting = 0;
72 static int disable_triggers = 0;
73 static int if_exists = 0;
74 static int inserts = 0;
75 static int no_table_access_method = 0;
76 static int no_tablespaces = 0;
77 static int use_setsessauth = 0;
78 static int no_comments = 0;
79 static int no_publications = 0;
80 static int no_security_labels = 0;
81 static int no_subscriptions = 0;
82 static int no_toast_compression = 0;
83 static int no_unlogged_table_data = 0;
84 static int no_role_passwords = 0;
85 static int server_version;
86 static int load_via_partition_root = 0;
87 static int on_conflict_do_nothing = 0;
88 
89 static char role_catalog[10];
90 #define PG_AUTHID "pg_authid"
91 #define PG_ROLES "pg_roles "
92 
93 static FILE *OPF;
94 static char *filename = NULL;
95 
98 
99 #define exit_nicely(code) exit(code)
100 
101 int
102 main(int argc, char *argv[])
103 {
104  static struct option long_options[] = {
105  {"data-only", no_argument, NULL, 'a'},
106  {"clean", no_argument, NULL, 'c'},
107  {"encoding", required_argument, NULL, 'E'},
108  {"file", required_argument, NULL, 'f'},
109  {"globals-only", no_argument, NULL, 'g'},
110  {"host", required_argument, NULL, 'h'},
111  {"dbname", required_argument, NULL, 'd'},
112  {"database", required_argument, NULL, 'l'},
113  {"no-owner", no_argument, NULL, 'O'},
114  {"port", required_argument, NULL, 'p'},
115  {"roles-only", no_argument, NULL, 'r'},
116  {"schema-only", no_argument, NULL, 's'},
117  {"superuser", required_argument, NULL, 'S'},
118  {"tablespaces-only", no_argument, NULL, 't'},
119  {"username", required_argument, NULL, 'U'},
120  {"verbose", no_argument, NULL, 'v'},
121  {"no-password", no_argument, NULL, 'w'},
122  {"password", no_argument, NULL, 'W'},
123  {"no-privileges", no_argument, NULL, 'x'},
124  {"no-acl", no_argument, NULL, 'x'},
125 
126  /*
127  * the following options don't have an equivalent short option letter
128  */
129  {"attribute-inserts", no_argument, &column_inserts, 1},
130  {"binary-upgrade", no_argument, &binary_upgrade, 1},
131  {"column-inserts", no_argument, &column_inserts, 1},
132  {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
133  {"disable-triggers", no_argument, &disable_triggers, 1},
134  {"exclude-database", required_argument, NULL, 6},
135  {"extra-float-digits", required_argument, NULL, 5},
136  {"if-exists", no_argument, &if_exists, 1},
137  {"inserts", no_argument, &inserts, 1},
138  {"lock-wait-timeout", required_argument, NULL, 2},
139  {"no-table-access-method", no_argument, &no_table_access_method, 1},
140  {"no-tablespaces", no_argument, &no_tablespaces, 1},
141  {"quote-all-identifiers", no_argument, &quote_all_identifiers, 1},
142  {"load-via-partition-root", no_argument, &load_via_partition_root, 1},
143  {"role", required_argument, NULL, 3},
144  {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
145  {"no-comments", no_argument, &no_comments, 1},
146  {"no-publications", no_argument, &no_publications, 1},
147  {"no-role-passwords", no_argument, &no_role_passwords, 1},
148  {"no-security-labels", no_argument, &no_security_labels, 1},
149  {"no-subscriptions", no_argument, &no_subscriptions, 1},
150  {"no-sync", no_argument, NULL, 4},
151  {"no-toast-compression", no_argument, &no_toast_compression, 1},
152  {"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
153  {"on-conflict-do-nothing", no_argument, &on_conflict_do_nothing, 1},
154  {"rows-per-insert", required_argument, NULL, 7},
155 
156  {NULL, 0, NULL, 0}
157  };
158 
159  char *pghost = NULL;
160  char *pgport = NULL;
161  char *pguser = NULL;
162  char *pgdb = NULL;
163  char *use_role = NULL;
164  const char *dumpencoding = NULL;
165  trivalue prompt_password = TRI_DEFAULT;
166  bool data_only = false;
167  bool globals_only = false;
168  bool roles_only = false;
169  bool tablespaces_only = false;
170  PGconn *conn;
171  int encoding;
172  const char *std_strings;
173  int c,
174  ret;
175  int optindex;
176 
177  pg_logging_init(argv[0]);
179  set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
180  progname = get_progname(argv[0]);
181 
182  if (argc > 1)
183  {
184  if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
185  {
186  help();
187  exit_nicely(0);
188  }
189  if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
190  {
191  puts("pg_dumpall (PostgreSQL) " PG_VERSION);
192  exit_nicely(0);
193  }
194  }
195 
196  if ((ret = find_other_exec(argv[0], "pg_dump", PGDUMP_VERSIONSTR,
197  pg_dump_bin)) < 0)
198  {
199  char full_path[MAXPGPATH];
200 
201  if (find_my_exec(argv[0], full_path) < 0)
202  strlcpy(full_path, progname, sizeof(full_path));
203 
204  if (ret == -1)
205  pg_fatal("program \"%s\" is needed by %s but was not found in the same directory as \"%s\"",
206  "pg_dump", progname, full_path);
207  else
208  pg_fatal("program \"%s\" was found by \"%s\" but was not the same version as %s",
209  "pg_dump", full_path, progname);
210  }
211 
213 
214  while ((c = getopt_long(argc, argv, "acd:E:f:gh:l:Op:rsS:tU:vwWx", long_options, &optindex)) != -1)
215  {
216  switch (c)
217  {
218  case 'a':
219  data_only = true;
221  break;
222 
223  case 'c':
224  output_clean = true;
225  break;
226 
227  case 'd':
229  break;
230 
231  case 'E':
232  dumpencoding = pg_strdup(optarg);
235  break;
236 
237  case 'f':
241  break;
242 
243  case 'g':
244  globals_only = true;
245  break;
246 
247  case 'h':
249  break;
250 
251  case 'l':
252  pgdb = pg_strdup(optarg);
253  break;
254 
255  case 'O':
257  break;
258 
259  case 'p':
261  break;
262 
263  case 'r':
264  roles_only = true;
265  break;
266 
267  case 's':
269  break;
270 
271  case 'S':
274  break;
275 
276  case 't':
277  tablespaces_only = true;
278  break;
279 
280  case 'U':
281  pguser = pg_strdup(optarg);
282  break;
283 
284  case 'v':
285  verbose = true;
288  break;
289 
290  case 'w':
291  prompt_password = TRI_NO;
293  break;
294 
295  case 'W':
296  prompt_password = TRI_YES;
298  break;
299 
300  case 'x':
301  skip_acls = true;
303  break;
304 
305  case 0:
306  break;
307 
308  case 2:
309  appendPQExpBufferStr(pgdumpopts, " --lock-wait-timeout ");
311  break;
312 
313  case 3:
314  use_role = pg_strdup(optarg);
315  appendPQExpBufferStr(pgdumpopts, " --role ");
316  appendShellString(pgdumpopts, use_role);
317  break;
318 
319  case 4:
320  dosync = false;
321  appendPQExpBufferStr(pgdumpopts, " --no-sync");
322  break;
323 
324  case 5:
325  appendPQExpBufferStr(pgdumpopts, " --extra-float-digits ");
327  break;
328 
329  case 6:
331  break;
332 
333  case 7:
334  appendPQExpBufferStr(pgdumpopts, " --rows-per-insert ");
336  break;
337 
338  default:
339  /* getopt_long already emitted a complaint */
340  pg_log_error_hint("Try \"%s --help\" for more information.", progname);
341  exit_nicely(1);
342  }
343  }
344 
345  /* Complain if any arguments remain */
346  if (optind < argc)
347  {
348  pg_log_error("too many command-line arguments (first is \"%s\")",
349  argv[optind]);
350  pg_log_error_hint("Try \"%s --help\" for more information.", progname);
351  exit_nicely(1);
352  }
353 
354  if (database_exclude_patterns.head != NULL &&
355  (globals_only || roles_only || tablespaces_only))
356  {
357  pg_log_error("option --exclude-database cannot be used together with -g/--globals-only, -r/--roles-only, or -t/--tablespaces-only");
358  pg_log_error_hint("Try \"%s --help\" for more information.", progname);
359  exit_nicely(1);
360  }
361 
362  /* Make sure the user hasn't specified a mix of globals-only options */
363  if (globals_only && roles_only)
364  {
365  pg_log_error("options -g/--globals-only and -r/--roles-only cannot be used together");
366  pg_log_error_hint("Try \"%s --help\" for more information.", progname);
367  exit_nicely(1);
368  }
369 
370  if (globals_only && tablespaces_only)
371  {
372  pg_log_error("options -g/--globals-only and -t/--tablespaces-only cannot be used together");
373  pg_log_error_hint("Try \"%s --help\" for more information.", progname);
374  exit_nicely(1);
375  }
376 
377  if (if_exists && !output_clean)
378  pg_fatal("option --if-exists requires option -c/--clean");
379 
380  if (roles_only && tablespaces_only)
381  {
382  pg_log_error("options -r/--roles-only and -t/--tablespaces-only cannot be used together");
383  pg_log_error_hint("Try \"%s --help\" for more information.", progname);
384  exit_nicely(1);
385  }
386 
387  /*
388  * If password values are not required in the dump, switch to using
389  * pg_roles which is equally useful, just more likely to have unrestricted
390  * access than pg_authid.
391  */
392  if (no_role_passwords)
393  sprintf(role_catalog, "%s", PG_ROLES);
394  else
396 
397  /* Add long options to the pg_dump argument list */
398  if (binary_upgrade)
399  appendPQExpBufferStr(pgdumpopts, " --binary-upgrade");
400  if (column_inserts)
401  appendPQExpBufferStr(pgdumpopts, " --column-inserts");
403  appendPQExpBufferStr(pgdumpopts, " --disable-dollar-quoting");
404  if (disable_triggers)
405  appendPQExpBufferStr(pgdumpopts, " --disable-triggers");
406  if (inserts)
407  appendPQExpBufferStr(pgdumpopts, " --inserts");
409  appendPQExpBufferStr(pgdumpopts, " --no-table-access-method");
410  if (no_tablespaces)
411  appendPQExpBufferStr(pgdumpopts, " --no-tablespaces");
413  appendPQExpBufferStr(pgdumpopts, " --quote-all-identifiers");
415  appendPQExpBufferStr(pgdumpopts, " --load-via-partition-root");
416  if (use_setsessauth)
417  appendPQExpBufferStr(pgdumpopts, " --use-set-session-authorization");
418  if (no_comments)
419  appendPQExpBufferStr(pgdumpopts, " --no-comments");
420  if (no_publications)
421  appendPQExpBufferStr(pgdumpopts, " --no-publications");
422  if (no_security_labels)
423  appendPQExpBufferStr(pgdumpopts, " --no-security-labels");
424  if (no_subscriptions)
425  appendPQExpBufferStr(pgdumpopts, " --no-subscriptions");
427  appendPQExpBufferStr(pgdumpopts, " --no-toast-compression");
429  appendPQExpBufferStr(pgdumpopts, " --no-unlogged-table-data");
431  appendPQExpBufferStr(pgdumpopts, " --on-conflict-do-nothing");
432 
433  /*
434  * If there was a database specified on the command line, use that,
435  * otherwise try to connect to database "postgres", and failing that
436  * "template1".
437  */
438  if (pgdb)
439  {
440  conn = connectDatabase(pgdb, connstr, pghost, pgport, pguser,
441  prompt_password, false);
442 
443  if (!conn)
444  pg_fatal("could not connect to database \"%s\"", pgdb);
445  }
446  else
447  {
448  conn = connectDatabase("postgres", connstr, pghost, pgport, pguser,
449  prompt_password, false);
450  if (!conn)
451  conn = connectDatabase("template1", connstr, pghost, pgport, pguser,
452  prompt_password, true);
453 
454  if (!conn)
455  {
456  pg_log_error("could not connect to databases \"postgres\" or \"template1\"\n"
457  "Please specify an alternative database.");
458  pg_log_error_hint("Try \"%s --help\" for more information.", progname);
459  exit_nicely(1);
460  }
461  }
462 
463  /*
464  * Get a list of database names that match the exclude patterns
465  */
468 
469  /*
470  * Open the output file if required, otherwise use stdout
471  */
472  if (filename)
473  {
474  OPF = fopen(filename, PG_BINARY_W);
475  if (!OPF)
476  pg_fatal("could not open output file \"%s\": %m",
477  filename);
478  }
479  else
480  OPF = stdout;
481 
482  /*
483  * Set the client encoding if requested.
484  */
485  if (dumpencoding)
486  {
487  if (PQsetClientEncoding(conn, dumpencoding) < 0)
488  pg_fatal("invalid client encoding \"%s\" specified",
489  dumpencoding);
490  }
491 
492  /*
493  * Get the active encoding and the standard_conforming_strings setting, so
494  * we know how to escape strings.
495  */
497  std_strings = PQparameterStatus(conn, "standard_conforming_strings");
498  if (!std_strings)
499  std_strings = "off";
500 
501  /* Set the role if requested */
502  if (use_role)
503  {
504  PQExpBuffer query = createPQExpBuffer();
505 
506  appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
507  executeCommand(conn, query->data);
508  destroyPQExpBuffer(query);
509  }
510 
511  /* Force quoting of all identifiers if requested. */
513  executeCommand(conn, "SET quote_all_identifiers = true");
514 
515  fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n");
516  if (verbose)
517  dumpTimestamp("Started on");
518 
519  /*
520  * We used to emit \connect postgres here, but that served no purpose
521  * other than to break things for installations without a postgres
522  * database. Everything we're restoring here is a global, so whichever
523  * database we're connected to at the moment is fine.
524  */
525 
526  /* Restore will need to write to the target cluster */
527  fprintf(OPF, "SET default_transaction_read_only = off;\n\n");
528 
529  /* Replicate encoding and std_strings in output */
530  fprintf(OPF, "SET client_encoding = '%s';\n",
532  fprintf(OPF, "SET standard_conforming_strings = %s;\n", std_strings);
533  if (strcmp(std_strings, "off") == 0)
534  fprintf(OPF, "SET escape_string_warning = off;\n");
535  fprintf(OPF, "\n");
536 
537  if (!data_only)
538  {
539  /*
540  * If asked to --clean, do that first. We can avoid detailed
541  * dependency analysis because databases never depend on each other,
542  * and tablespaces never depend on each other. Roles could have
543  * grants to each other, but DROP ROLE will clean those up silently.
544  */
545  if (output_clean)
546  {
547  if (!globals_only && !roles_only && !tablespaces_only)
548  dropDBs(conn);
549 
550  if (!roles_only && !no_tablespaces)
552 
553  if (!tablespaces_only)
554  dropRoles(conn);
555  }
556 
557  /*
558  * Now create objects as requested. Be careful that option logic here
559  * is the same as for drops above.
560  */
561  if (!tablespaces_only)
562  {
563  /* Dump roles (users) */
564  dumpRoles(conn);
565 
566  /* Dump role memberships */
568 
569  /* Dump role GUC privileges */
570  if (server_version >= 150000 && !skip_acls)
572  }
573 
574  /* Dump tablespaces */
575  if (!roles_only && !no_tablespaces)
577  }
578 
579  if (!globals_only && !roles_only && !tablespaces_only)
581 
582  PQfinish(conn);
583 
584  if (verbose)
585  dumpTimestamp("Completed on");
586  fprintf(OPF, "--\n-- PostgreSQL database cluster dump complete\n--\n\n");
587 
588  if (filename)
589  {
590  fclose(OPF);
591 
592  /* sync the resulting file, errors are not fatal */
593  if (dosync)
594  (void) fsync_fname(filename, false);
595  }
596 
597  exit_nicely(0);
598 }
599 
600 
601 static void
602 help(void)
603 {
604  printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname);
605  printf(_("Usage:\n"));
606  printf(_(" %s [OPTION]...\n"), progname);
607 
608  printf(_("\nGeneral options:\n"));
609  printf(_(" -f, --file=FILENAME output file name\n"));
610  printf(_(" -v, --verbose verbose mode\n"));
611  printf(_(" -V, --version output version information, then exit\n"));
612  printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
613  printf(_(" -?, --help show this help, then exit\n"));
614  printf(_("\nOptions controlling the output content:\n"));
615  printf(_(" -a, --data-only dump only the data, not the schema\n"));
616  printf(_(" -c, --clean clean (drop) databases before recreating\n"));
617  printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
618  printf(_(" -g, --globals-only dump only global objects, no databases\n"));
619  printf(_(" -O, --no-owner skip restoration of object ownership\n"));
620  printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n"));
621  printf(_(" -s, --schema-only dump only the schema, no data\n"));
622  printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n"));
623  printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n"));
624  printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
625  printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
626  printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
627  printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
628  printf(_(" --disable-triggers disable triggers during data-only restore\n"));
629  printf(_(" --exclude-database=PATTERN exclude databases whose name matches PATTERN\n"));
630  printf(_(" --extra-float-digits=NUM override default setting for extra_float_digits\n"));
631  printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
632  printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
633  printf(_(" --load-via-partition-root load partitions via the root table\n"));
634  printf(_(" --no-comments do not dump comments\n"));
635  printf(_(" --no-publications do not dump publications\n"));
636  printf(_(" --no-role-passwords do not dump passwords for roles\n"));
637  printf(_(" --no-security-labels do not dump security label assignments\n"));
638  printf(_(" --no-subscriptions do not dump subscriptions\n"));
639  printf(_(" --no-sync do not wait for changes to be written safely to disk\n"));
640  printf(_(" --no-table-access-method do not dump table access methods\n"));
641  printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
642  printf(_(" --no-toast-compression do not dump TOAST compression methods\n"));
643  printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
644  printf(_(" --on-conflict-do-nothing add ON CONFLICT DO NOTHING to INSERT commands\n"));
645  printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
646  printf(_(" --rows-per-insert=NROWS number of rows per INSERT; implies --inserts\n"));
647  printf(_(" --use-set-session-authorization\n"
648  " use SET SESSION AUTHORIZATION commands instead of\n"
649  " ALTER OWNER commands to set ownership\n"));
650 
651  printf(_("\nConnection options:\n"));
652  printf(_(" -d, --dbname=CONNSTR connect using connection string\n"));
653  printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
654  printf(_(" -l, --database=DBNAME alternative default database\n"));
655  printf(_(" -p, --port=PORT database server port number\n"));
656  printf(_(" -U, --username=NAME connect as specified database user\n"));
657  printf(_(" -w, --no-password never prompt for password\n"));
658  printf(_(" -W, --password force password prompt (should happen automatically)\n"));
659  printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
660 
661  printf(_("\nIf -f/--file is not used, then the SQL script will be written to the standard\n"
662  "output.\n\n"));
663  printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
664  printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
665 }
666 
667 
668 /*
669  * Drop roles
670  */
671 static void
673 {
675  PGresult *res;
676  int i_rolname;
677  int i;
678 
679  if (server_version >= 90600)
681  "SELECT rolname "
682  "FROM %s "
683  "WHERE rolname !~ '^pg_' "
684  "ORDER BY 1", role_catalog);
685  else
687  "SELECT rolname "
688  "FROM %s "
689  "ORDER BY 1", role_catalog);
690 
691  res = executeQuery(conn, buf->data);
692 
693  i_rolname = PQfnumber(res, "rolname");
694 
695  if (PQntuples(res) > 0)
696  fprintf(OPF, "--\n-- Drop roles\n--\n\n");
697 
698  for (i = 0; i < PQntuples(res); i++)
699  {
700  const char *rolename;
701 
702  rolename = PQgetvalue(res, i, i_rolname);
703 
704  fprintf(OPF, "DROP ROLE %s%s;\n",
705  if_exists ? "IF EXISTS " : "",
706  fmtId(rolename));
707  }
708 
709  PQclear(res);
711 
712  fprintf(OPF, "\n\n");
713 }
714 
715 /*
716  * Dump roles
717  */
718 static void
720 {
722  PGresult *res;
723  int i_oid,
724  i_rolname,
725  i_rolsuper,
726  i_rolinherit,
727  i_rolcreaterole,
728  i_rolcreatedb,
729  i_rolcanlogin,
730  i_rolconnlimit,
731  i_rolpassword,
732  i_rolvaliduntil,
733  i_rolreplication,
734  i_rolbypassrls,
735  i_rolcomment,
736  i_is_current_user;
737  int i;
738 
739  /* note: rolconfig is dumped later */
740  if (server_version >= 90600)
742  "SELECT oid, rolname, rolsuper, rolinherit, "
743  "rolcreaterole, rolcreatedb, "
744  "rolcanlogin, rolconnlimit, rolpassword, "
745  "rolvaliduntil, rolreplication, rolbypassrls, "
746  "pg_catalog.shobj_description(oid, '%s') as rolcomment, "
747  "rolname = current_user AS is_current_user "
748  "FROM %s "
749  "WHERE rolname !~ '^pg_' "
750  "ORDER BY 2", role_catalog, role_catalog);
751  else if (server_version >= 90500)
753  "SELECT oid, rolname, rolsuper, rolinherit, "
754  "rolcreaterole, rolcreatedb, "
755  "rolcanlogin, rolconnlimit, rolpassword, "
756  "rolvaliduntil, rolreplication, rolbypassrls, "
757  "pg_catalog.shobj_description(oid, '%s') as rolcomment, "
758  "rolname = current_user AS is_current_user "
759  "FROM %s "
760  "ORDER BY 2", role_catalog, role_catalog);
761  else
763  "SELECT oid, rolname, rolsuper, rolinherit, "
764  "rolcreaterole, rolcreatedb, "
765  "rolcanlogin, rolconnlimit, rolpassword, "
766  "rolvaliduntil, rolreplication, "
767  "false as rolbypassrls, "
768  "pg_catalog.shobj_description(oid, '%s') as rolcomment, "
769  "rolname = current_user AS is_current_user "
770  "FROM %s "
771  "ORDER BY 2", role_catalog, role_catalog);
772 
773  res = executeQuery(conn, buf->data);
774 
775  i_oid = PQfnumber(res, "oid");
776  i_rolname = PQfnumber(res, "rolname");
777  i_rolsuper = PQfnumber(res, "rolsuper");
778  i_rolinherit = PQfnumber(res, "rolinherit");
779  i_rolcreaterole = PQfnumber(res, "rolcreaterole");
780  i_rolcreatedb = PQfnumber(res, "rolcreatedb");
781  i_rolcanlogin = PQfnumber(res, "rolcanlogin");
782  i_rolconnlimit = PQfnumber(res, "rolconnlimit");
783  i_rolpassword = PQfnumber(res, "rolpassword");
784  i_rolvaliduntil = PQfnumber(res, "rolvaliduntil");
785  i_rolreplication = PQfnumber(res, "rolreplication");
786  i_rolbypassrls = PQfnumber(res, "rolbypassrls");
787  i_rolcomment = PQfnumber(res, "rolcomment");
788  i_is_current_user = PQfnumber(res, "is_current_user");
789 
790  if (PQntuples(res) > 0)
791  fprintf(OPF, "--\n-- Roles\n--\n\n");
792 
793  for (i = 0; i < PQntuples(res); i++)
794  {
795  const char *rolename;
796  Oid auth_oid;
797 
798  auth_oid = atooid(PQgetvalue(res, i, i_oid));
799  rolename = PQgetvalue(res, i, i_rolname);
800 
801  if (strncmp(rolename, "pg_", 3) == 0)
802  {
803  pg_log_warning("role name starting with \"pg_\" skipped (%s)",
804  rolename);
805  continue;
806  }
807 
809 
810  if (binary_upgrade)
811  {
812  appendPQExpBufferStr(buf, "\n-- For binary upgrade, must preserve pg_authid.oid\n");
814  "SELECT pg_catalog.binary_upgrade_set_next_pg_authid_oid('%u'::pg_catalog.oid);\n\n",
815  auth_oid);
816  }
817 
818  /*
819  * We dump CREATE ROLE followed by ALTER ROLE to ensure that the role
820  * will acquire the right properties even if it already exists (ie, it
821  * won't hurt for the CREATE to fail). This is particularly important
822  * for the role we are connected as, since even with --clean we will
823  * have failed to drop it. binary_upgrade cannot generate any errors,
824  * so we assume the current role is already created.
825  */
826  if (!binary_upgrade ||
827  strcmp(PQgetvalue(res, i, i_is_current_user), "f") == 0)
828  appendPQExpBuffer(buf, "CREATE ROLE %s;\n", fmtId(rolename));
829  appendPQExpBuffer(buf, "ALTER ROLE %s WITH", fmtId(rolename));
830 
831  if (strcmp(PQgetvalue(res, i, i_rolsuper), "t") == 0)
832  appendPQExpBufferStr(buf, " SUPERUSER");
833  else
834  appendPQExpBufferStr(buf, " NOSUPERUSER");
835 
836  if (strcmp(PQgetvalue(res, i, i_rolinherit), "t") == 0)
837  appendPQExpBufferStr(buf, " INHERIT");
838  else
839  appendPQExpBufferStr(buf, " NOINHERIT");
840 
841  if (strcmp(PQgetvalue(res, i, i_rolcreaterole), "t") == 0)
842  appendPQExpBufferStr(buf, " CREATEROLE");
843  else
844  appendPQExpBufferStr(buf, " NOCREATEROLE");
845 
846  if (strcmp(PQgetvalue(res, i, i_rolcreatedb), "t") == 0)
847  appendPQExpBufferStr(buf, " CREATEDB");
848  else
849  appendPQExpBufferStr(buf, " NOCREATEDB");
850 
851  if (strcmp(PQgetvalue(res, i, i_rolcanlogin), "t") == 0)
852  appendPQExpBufferStr(buf, " LOGIN");
853  else
854  appendPQExpBufferStr(buf, " NOLOGIN");
855 
856  if (strcmp(PQgetvalue(res, i, i_rolreplication), "t") == 0)
857  appendPQExpBufferStr(buf, " REPLICATION");
858  else
859  appendPQExpBufferStr(buf, " NOREPLICATION");
860 
861  if (strcmp(PQgetvalue(res, i, i_rolbypassrls), "t") == 0)
862  appendPQExpBufferStr(buf, " BYPASSRLS");
863  else
864  appendPQExpBufferStr(buf, " NOBYPASSRLS");
865 
866  if (strcmp(PQgetvalue(res, i, i_rolconnlimit), "-1") != 0)
867  appendPQExpBuffer(buf, " CONNECTION LIMIT %s",
868  PQgetvalue(res, i, i_rolconnlimit));
869 
870 
871  if (!PQgetisnull(res, i, i_rolpassword) && !no_role_passwords)
872  {
873  appendPQExpBufferStr(buf, " PASSWORD ");
874  appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolpassword), conn);
875  }
876 
877  if (!PQgetisnull(res, i, i_rolvaliduntil))
878  appendPQExpBuffer(buf, " VALID UNTIL '%s'",
879  PQgetvalue(res, i, i_rolvaliduntil));
880 
881  appendPQExpBufferStr(buf, ";\n");
882 
883  if (!no_comments && !PQgetisnull(res, i, i_rolcomment))
884  {
885  appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
886  appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolcomment), conn);
887  appendPQExpBufferStr(buf, ";\n");
888  }
889 
890  if (!no_security_labels)
891  buildShSecLabels(conn, "pg_authid", auth_oid,
892  "ROLE", rolename,
893  buf);
894 
895  fprintf(OPF, "%s", buf->data);
896  }
897 
898  /*
899  * Dump configuration settings for roles after all roles have been dumped.
900  * We do it this way because config settings for roles could mention the
901  * names of other roles.
902  */
903  if (PQntuples(res) > 0)
904  fprintf(OPF, "\n--\n-- User Configurations\n--\n");
905 
906  for (i = 0; i < PQntuples(res); i++)
907  dumpUserConfig(conn, PQgetvalue(res, i, i_rolname));
908 
909  PQclear(res);
910 
911  fprintf(OPF, "\n\n");
912 
914 }
915 
916 
917 /*
918  * Dump role memberships.
919  *
920  * Note: we expect dumpRoles already created all the roles, but there is
921  * no membership yet.
922  */
923 static void
925 {
927  PGresult *res;
928  int i;
929 
930  printfPQExpBuffer(buf, "SELECT ur.rolname AS roleid, "
931  "um.rolname AS member, "
932  "a.admin_option, "
933  "ug.rolname AS grantor "
934  "FROM pg_auth_members a "
935  "LEFT JOIN %s ur on ur.oid = a.roleid "
936  "LEFT JOIN %s um on um.oid = a.member "
937  "LEFT JOIN %s ug on ug.oid = a.grantor "
938  "WHERE NOT (ur.rolname ~ '^pg_' AND um.rolname ~ '^pg_')"
939  "ORDER BY 1,2,3", role_catalog, role_catalog, role_catalog);
940  res = executeQuery(conn, buf->data);
941 
942  if (PQntuples(res) > 0)
943  fprintf(OPF, "--\n-- Role memberships\n--\n\n");
944 
945  for (i = 0; i < PQntuples(res); i++)
946  {
947  char *roleid = PQgetvalue(res, i, 0);
948  char *member = PQgetvalue(res, i, 1);
949  char *option = PQgetvalue(res, i, 2);
950 
951  fprintf(OPF, "GRANT %s", fmtId(roleid));
952  fprintf(OPF, " TO %s", fmtId(member));
953  if (*option == 't')
954  fprintf(OPF, " WITH ADMIN OPTION");
955 
956  /*
957  * We don't track the grantor very carefully in the backend, so cope
958  * with the possibility that it has been dropped.
959  */
960  if (!PQgetisnull(res, i, 3))
961  {
962  char *grantor = PQgetvalue(res, i, 3);
963 
964  fprintf(OPF, " GRANTED BY %s", fmtId(grantor));
965  }
966  fprintf(OPF, ";\n");
967  }
968 
969  PQclear(res);
971 
972  fprintf(OPF, "\n\n");
973 }
974 
975 
976 /*
977  * Dump role configuration parameter privileges. This code is used for 15.0
978  * and later servers.
979  *
980  * Note: we expect dumpRoles already created all the roles, but there are
981  * no per-role configuration parameter privileges yet.
982  */
983 static void
985 {
986  PGresult *res;
987  int i;
988 
989  /*
990  * Get all parameters that have non-default acls defined.
991  */
992  res = executeQuery(conn, "SELECT parname, "
993  "pg_catalog.pg_get_userbyid(" CppAsString2(BOOTSTRAP_SUPERUSERID) ") AS parowner, "
994  "paracl, "
995  "pg_catalog.acldefault('p', " CppAsString2(BOOTSTRAP_SUPERUSERID) ") AS acldefault "
996  "FROM pg_catalog.pg_parameter_acl "
997  "ORDER BY 1");
998 
999  if (PQntuples(res) > 0)
1000  fprintf(OPF, "--\n-- Role privileges on configuration parameters\n--\n\n");
1001 
1002  for (i = 0; i < PQntuples(res); i++)
1003  {
1005  char *parname = PQgetvalue(res, i, 0);
1006  char *parowner = PQgetvalue(res, i, 1);
1007  char *paracl = PQgetvalue(res, i, 2);
1008  char *acldefault = PQgetvalue(res, i, 3);
1009  char *fparname;
1010 
1011  /* needed for buildACLCommands() */
1012  fparname = pg_strdup(fmtId(parname));
1013 
1014  if (!buildACLCommands(fparname, NULL, NULL, "PARAMETER",
1015  paracl, acldefault,
1016  parowner, "", server_version, buf))
1017  {
1018  pg_log_error("could not parse ACL list (%s) for parameter \"%s\"",
1019  paracl, parname);
1020  PQfinish(conn);
1021  exit_nicely(1);
1022  }
1023 
1024  fprintf(OPF, "%s", buf->data);
1025 
1026  free(fparname);
1028  }
1029 
1030  PQclear(res);
1031  fprintf(OPF, "\n\n");
1032 }
1033 
1034 
1035 /*
1036  * Drop tablespaces.
1037  */
1038 static void
1040 {
1041  PGresult *res;
1042  int i;
1043 
1044  /*
1045  * Get all tablespaces except built-in ones (which we assume are named
1046  * pg_xxx)
1047  */
1048  res = executeQuery(conn, "SELECT spcname "
1049  "FROM pg_catalog.pg_tablespace "
1050  "WHERE spcname !~ '^pg_' "
1051  "ORDER BY 1");
1052 
1053  if (PQntuples(res) > 0)
1054  fprintf(OPF, "--\n-- Drop tablespaces\n--\n\n");
1055 
1056  for (i = 0; i < PQntuples(res); i++)
1057  {
1058  char *spcname = PQgetvalue(res, i, 0);
1059 
1060  fprintf(OPF, "DROP TABLESPACE %s%s;\n",
1061  if_exists ? "IF EXISTS " : "",
1062  fmtId(spcname));
1063  }
1064 
1065  PQclear(res);
1066 
1067  fprintf(OPF, "\n\n");
1068 }
1069 
1070 /*
1071  * Dump tablespaces.
1072  */
1073 static void
1075 {
1076  PGresult *res;
1077  int i;
1078 
1079  /*
1080  * Get all tablespaces except built-in ones (which we assume are named
1081  * pg_xxx)
1082  */
1083  res = executeQuery(conn, "SELECT oid, spcname, "
1084  "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
1085  "pg_catalog.pg_tablespace_location(oid), "
1086  "spcacl, acldefault('t', spcowner) AS acldefault, "
1087  "array_to_string(spcoptions, ', '),"
1088  "pg_catalog.shobj_description(oid, 'pg_tablespace') "
1089  "FROM pg_catalog.pg_tablespace "
1090  "WHERE spcname !~ '^pg_' "
1091  "ORDER BY 1");
1092 
1093  if (PQntuples(res) > 0)
1094  fprintf(OPF, "--\n-- Tablespaces\n--\n\n");
1095 
1096  for (i = 0; i < PQntuples(res); i++)
1097  {
1099  Oid spcoid = atooid(PQgetvalue(res, i, 0));
1100  char *spcname = PQgetvalue(res, i, 1);
1101  char *spcowner = PQgetvalue(res, i, 2);
1102  char *spclocation = PQgetvalue(res, i, 3);
1103  char *spcacl = PQgetvalue(res, i, 4);
1104  char *acldefault = PQgetvalue(res, i, 5);
1105  char *spcoptions = PQgetvalue(res, i, 6);
1106  char *spccomment = PQgetvalue(res, i, 7);
1107  char *fspcname;
1108 
1109  /* needed for buildACLCommands() */
1110  fspcname = pg_strdup(fmtId(spcname));
1111 
1112  if (binary_upgrade)
1113  {
1114  appendPQExpBufferStr(buf, "\n-- For binary upgrade, must preserve pg_tablespace oid\n");
1115  appendPQExpBuffer(buf, "SELECT pg_catalog.binary_upgrade_set_next_pg_tablespace_oid('%u'::pg_catalog.oid);\n", spcoid);
1116  }
1117 
1118  appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname);
1119  appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
1120 
1121  appendPQExpBufferStr(buf, " LOCATION ");
1122  appendStringLiteralConn(buf, spclocation, conn);
1123  appendPQExpBufferStr(buf, ";\n");
1124 
1125  if (spcoptions && spcoptions[0] != '\0')
1126  appendPQExpBuffer(buf, "ALTER TABLESPACE %s SET (%s);\n",
1127  fspcname, spcoptions);
1128 
1129  /* tablespaces can't have initprivs */
1130 
1131  if (!skip_acls &&
1132  !buildACLCommands(fspcname, NULL, NULL, "TABLESPACE",
1133  spcacl, acldefault,
1134  spcowner, "", server_version, buf))
1135  {
1136  pg_log_error("could not parse ACL list (%s) for tablespace \"%s\"",
1137  spcacl, spcname);
1138  PQfinish(conn);
1139  exit_nicely(1);
1140  }
1141 
1142  if (!no_comments && spccomment && spccomment[0] != '\0')
1143  {
1144  appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
1145  appendStringLiteralConn(buf, spccomment, conn);
1146  appendPQExpBufferStr(buf, ";\n");
1147  }
1148 
1149  if (!no_security_labels)
1150  buildShSecLabels(conn, "pg_tablespace", spcoid,
1151  "TABLESPACE", spcname,
1152  buf);
1153 
1154  fprintf(OPF, "%s", buf->data);
1155 
1156  free(fspcname);
1158  }
1159 
1160  PQclear(res);
1161  fprintf(OPF, "\n\n");
1162 }
1163 
1164 
1165 /*
1166  * Dump commands to drop each database.
1167  */
1168 static void
1170 {
1171  PGresult *res;
1172  int i;
1173 
1174  /*
1175  * Skip databases marked not datallowconn, since we'd be unable to connect
1176  * to them anyway. This must agree with dumpDatabases().
1177  */
1178  res = executeQuery(conn,
1179  "SELECT datname "
1180  "FROM pg_database d "
1181  "WHERE datallowconn "
1182  "ORDER BY datname");
1183 
1184  if (PQntuples(res) > 0)
1185  fprintf(OPF, "--\n-- Drop databases (except postgres and template1)\n--\n\n");
1186 
1187  for (i = 0; i < PQntuples(res); i++)
1188  {
1189  char *dbname = PQgetvalue(res, i, 0);
1190 
1191  /*
1192  * Skip "postgres" and "template1"; dumpDatabases() will deal with
1193  * them specially. Also, be sure to skip "template0", even if for
1194  * some reason it's not marked !datallowconn.
1195  */
1196  if (strcmp(dbname, "template1") != 0 &&
1197  strcmp(dbname, "template0") != 0 &&
1198  strcmp(dbname, "postgres") != 0)
1199  {
1200  fprintf(OPF, "DROP DATABASE %s%s;\n",
1201  if_exists ? "IF EXISTS " : "",
1202  fmtId(dbname));
1203  }
1204  }
1205 
1206  PQclear(res);
1207 
1208  fprintf(OPF, "\n\n");
1209 }
1210 
1211 
1212 /*
1213  * Dump user-specific configuration
1214  */
1215 static void
1217 {
1219  PGresult *res;
1220 
1221  printfPQExpBuffer(buf, "SELECT unnest(setconfig) FROM pg_db_role_setting "
1222  "WHERE setdatabase = 0 AND setrole = "
1223  "(SELECT oid FROM %s WHERE rolname = ",
1224  role_catalog);
1226  appendPQExpBufferChar(buf, ')');
1227 
1228  res = executeQuery(conn, buf->data);
1229 
1230  if (PQntuples(res) > 0)
1231  fprintf(OPF, "\n--\n-- User Config \"%s\"\n--\n\n", username);
1232 
1233  for (int i = 0; i < PQntuples(res); i++)
1234  {
1237  "ROLE", username, NULL, NULL,
1238  buf);
1239  fprintf(OPF, "%s", buf->data);
1240  }
1241 
1242  PQclear(res);
1243 
1245 }
1246 
1247 /*
1248  * Find a list of database names that match the given patterns.
1249  * See also expand_table_name_patterns() in pg_dump.c
1250  */
1251 static void
1253  SimpleStringList *patterns,
1254  SimpleStringList *names)
1255 {
1256  PQExpBuffer query;
1257  PGresult *res;
1258 
1259  if (patterns->head == NULL)
1260  return; /* nothing to do */
1261 
1262  query = createPQExpBuffer();
1263 
1264  /*
1265  * The loop below runs multiple SELECTs, which might sometimes result in
1266  * duplicate entries in the name list, but we don't care, since all we're
1267  * going to do is test membership of the list.
1268  */
1269 
1270  for (SimpleStringListCell *cell = patterns->head; cell; cell = cell->next)
1271  {
1272  int dotcnt;
1273 
1274  appendPQExpBufferStr(query,
1275  "SELECT datname FROM pg_catalog.pg_database n\n");
1276  processSQLNamePattern(conn, query, cell->val, false,
1277  false, NULL, "datname", NULL, NULL, NULL,
1278  &dotcnt);
1279 
1280  if (dotcnt > 0)
1281  {
1282  pg_log_error("improper qualified name (too many dotted names): %s",
1283  cell->val);
1284  PQfinish(conn);
1285  exit_nicely(1);
1286  }
1287 
1288  res = executeQuery(conn, query->data);
1289  for (int i = 0; i < PQntuples(res); i++)
1290  {
1292  }
1293 
1294  PQclear(res);
1295  resetPQExpBuffer(query);
1296  }
1297 
1298  destroyPQExpBuffer(query);
1299 }
1300 
1301 /*
1302  * Dump contents of databases.
1303  */
1304 static void
1306 {
1307  PGresult *res;
1308  int i;
1309 
1310  /*
1311  * Skip databases marked not datallowconn, since we'd be unable to connect
1312  * to them anyway. This must agree with dropDBs().
1313  *
1314  * We arrange for template1 to be processed first, then we process other
1315  * DBs in alphabetical order. If we just did them all alphabetically, we
1316  * might find ourselves trying to drop the "postgres" database while still
1317  * connected to it. This makes trying to run the restore script while
1318  * connected to "template1" a bad idea, but there's no fixed order that
1319  * doesn't have some failure mode with --clean.
1320  */
1321  res = executeQuery(conn,
1322  "SELECT datname "
1323  "FROM pg_database d "
1324  "WHERE datallowconn "
1325  "ORDER BY (datname <> 'template1'), datname");
1326 
1327  if (PQntuples(res) > 0)
1328  fprintf(OPF, "--\n-- Databases\n--\n\n");
1329 
1330  for (i = 0; i < PQntuples(res); i++)
1331  {
1332  char *dbname = PQgetvalue(res, i, 0);
1333  const char *create_opts;
1334  int ret;
1335 
1336  /* Skip template0, even if it's not marked !datallowconn. */
1337  if (strcmp(dbname, "template0") == 0)
1338  continue;
1339 
1340  /* Skip any explicitly excluded database */
1342  {
1343  pg_log_info("excluding database \"%s\"", dbname);
1344  continue;
1345  }
1346 
1347  pg_log_info("dumping database \"%s\"", dbname);
1348 
1349  fprintf(OPF, "--\n-- Database \"%s\" dump\n--\n\n", dbname);
1350 
1351  /*
1352  * We assume that "template1" and "postgres" already exist in the
1353  * target installation. dropDBs() won't have removed them, for fear
1354  * of removing the DB the restore script is initially connected to. If
1355  * --clean was specified, tell pg_dump to drop and recreate them;
1356  * otherwise we'll merely restore their contents. Other databases
1357  * should simply be created.
1358  */
1359  if (strcmp(dbname, "template1") == 0 || strcmp(dbname, "postgres") == 0)
1360  {
1361  if (output_clean)
1362  create_opts = "--clean --create";
1363  else
1364  {
1365  create_opts = "";
1366  /* Since pg_dump won't emit a \connect command, we must */
1367  fprintf(OPF, "\\connect %s\n\n", dbname);
1368  }
1369  }
1370  else
1371  create_opts = "--create";
1372 
1373  if (filename)
1374  fclose(OPF);
1375 
1376  ret = runPgDump(dbname, create_opts);
1377  if (ret != 0)
1378  pg_fatal("pg_dump failed on database \"%s\", exiting", dbname);
1379 
1380  if (filename)
1381  {
1382  OPF = fopen(filename, PG_BINARY_A);
1383  if (!OPF)
1384  pg_fatal("could not re-open the output file \"%s\": %m",
1385  filename);
1386  }
1387  }
1388 
1389  PQclear(res);
1390 }
1391 
1392 
1393 
1394 /*
1395  * Run pg_dump on dbname, with specified options.
1396  */
1397 static int
1398 runPgDump(const char *dbname, const char *create_opts)
1399 {
1400  PQExpBuffer connstrbuf = createPQExpBuffer();
1402  int ret;
1403 
1404  appendPQExpBuffer(cmd, "\"%s\" %s %s", pg_dump_bin,
1405  pgdumpopts->data, create_opts);
1406 
1407  /*
1408  * If we have a filename, use the undocumented plain-append pg_dump
1409  * format.
1410  */
1411  if (filename)
1412  appendPQExpBufferStr(cmd, " -Fa ");
1413  else
1414  appendPQExpBufferStr(cmd, " -Fp ");
1415 
1416  /*
1417  * Append the database name to the already-constructed stem of connection
1418  * string.
1419  */
1420  appendPQExpBuffer(connstrbuf, "%s dbname=", connstr);
1421  appendConnStrVal(connstrbuf, dbname);
1422 
1423  appendShellString(cmd, connstrbuf->data);
1424 
1425  pg_log_info("running \"%s\"", cmd->data);
1426 
1427  fflush(stdout);
1428  fflush(stderr);
1429 
1430  ret = system(cmd->data);
1431 
1432  destroyPQExpBuffer(cmd);
1433  destroyPQExpBuffer(connstrbuf);
1434 
1435  return ret;
1436 }
1437 
1438 /*
1439  * buildShSecLabels
1440  *
1441  * Build SECURITY LABEL command(s) for a shared object
1442  *
1443  * The caller has to provide object type and identity in two separate formats:
1444  * catalog_name (e.g., "pg_database") and object OID, as well as
1445  * type name (e.g., "DATABASE") and object name (not pre-quoted).
1446  *
1447  * The command(s) are appended to "buffer".
1448  */
1449 static void
1450 buildShSecLabels(PGconn *conn, const char *catalog_name, Oid objectId,
1451  const char *objtype, const char *objname,
1452  PQExpBuffer buffer)
1453 {
1455  PGresult *res;
1456 
1457  buildShSecLabelQuery(catalog_name, objectId, sql);
1458  res = executeQuery(conn, sql->data);
1459  emitShSecLabels(conn, res, buffer, objtype, objname);
1460 
1461  PQclear(res);
1462  destroyPQExpBuffer(sql);
1463 }
1464 
1465 /*
1466  * Make a database connection with the given parameters. An
1467  * interactive password prompt is automatically issued if required.
1468  *
1469  * If fail_on_error is false, we return NULL without printing any message
1470  * on failure, but preserve any prompted password for the next try.
1471  *
1472  * On success, the global variable 'connstr' is set to a connection string
1473  * containing the options used.
1474  */
1475 static PGconn *
1476 connectDatabase(const char *dbname, const char *connection_string,
1477  const char *pghost, const char *pgport, const char *pguser,
1478  trivalue prompt_password, bool fail_on_error)
1479 {
1480  PGconn *conn;
1481  bool new_pass;
1482  const char *remoteversion_str;
1483  int my_version;
1484  const char **keywords = NULL;
1485  const char **values = NULL;
1486  PQconninfoOption *conn_opts = NULL;
1487  static char *password = NULL;
1488 
1489  if (prompt_password == TRI_YES && !password)
1490  password = simple_prompt("Password: ", false);
1491 
1492  /*
1493  * Start the connection. Loop until we have a password if requested by
1494  * backend.
1495  */
1496  do
1497  {
1498  int argcount = 6;
1499  PQconninfoOption *conn_opt;
1500  char *err_msg = NULL;
1501  int i = 0;
1502 
1503  if (keywords)
1504  free(keywords);
1505  if (values)
1506  free(values);
1507  if (conn_opts)
1508  PQconninfoFree(conn_opts);
1509 
1510  /*
1511  * Merge the connection info inputs given in form of connection string
1512  * and other options. Explicitly discard any dbname value in the
1513  * connection string; otherwise, PQconnectdbParams() would interpret
1514  * that value as being itself a connection string.
1515  */
1516  if (connection_string)
1517  {
1518  conn_opts = PQconninfoParse(connection_string, &err_msg);
1519  if (conn_opts == NULL)
1520  pg_fatal("%s", err_msg);
1521 
1522  for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
1523  {
1524  if (conn_opt->val != NULL && conn_opt->val[0] != '\0' &&
1525  strcmp(conn_opt->keyword, "dbname") != 0)
1526  argcount++;
1527  }
1528 
1529  keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
1530  values = pg_malloc0((argcount + 1) * sizeof(*values));
1531 
1532  for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
1533  {
1534  if (conn_opt->val != NULL && conn_opt->val[0] != '\0' &&
1535  strcmp(conn_opt->keyword, "dbname") != 0)
1536  {
1537  keywords[i] = conn_opt->keyword;
1538  values[i] = conn_opt->val;
1539  i++;
1540  }
1541  }
1542  }
1543  else
1544  {
1545  keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
1546  values = pg_malloc0((argcount + 1) * sizeof(*values));
1547  }
1548 
1549  if (pghost)
1550  {
1551  keywords[i] = "host";
1552  values[i] = pghost;
1553  i++;
1554  }
1555  if (pgport)
1556  {
1557  keywords[i] = "port";
1558  values[i] = pgport;
1559  i++;
1560  }
1561  if (pguser)
1562  {
1563  keywords[i] = "user";
1564  values[i] = pguser;
1565  i++;
1566  }
1567  if (password)
1568  {
1569  keywords[i] = "password";
1570  values[i] = password;
1571  i++;
1572  }
1573  if (dbname)
1574  {
1575  keywords[i] = "dbname";
1576  values[i] = dbname;
1577  i++;
1578  }
1579  keywords[i] = "fallback_application_name";
1580  values[i] = progname;
1581  i++;
1582 
1583  new_pass = false;
1584  conn = PQconnectdbParams(keywords, values, true);
1585 
1586  if (!conn)
1587  pg_fatal("could not connect to database \"%s\"", dbname);
1588 
1589  if (PQstatus(conn) == CONNECTION_BAD &&
1591  !password &&
1592  prompt_password != TRI_NO)
1593  {
1594  PQfinish(conn);
1595  password = simple_prompt("Password: ", false);
1596  new_pass = true;
1597  }
1598  } while (new_pass);
1599 
1600  /* check to see that the backend connection was successfully made */
1601  if (PQstatus(conn) == CONNECTION_BAD)
1602  {
1603  if (fail_on_error)
1604  pg_fatal("%s", PQerrorMessage(conn));
1605  else
1606  {
1607  PQfinish(conn);
1608 
1609  free(keywords);
1610  free(values);
1611  PQconninfoFree(conn_opts);
1612 
1613  return NULL;
1614  }
1615  }
1616 
1617  /*
1618  * Ok, connected successfully. Remember the options used, in the form of a
1619  * connection string.
1620  */
1621  connstr = constructConnStr(keywords, values);
1622 
1623  free(keywords);
1624  free(values);
1625  PQconninfoFree(conn_opts);
1626 
1627  /* Check version */
1628  remoteversion_str = PQparameterStatus(conn, "server_version");
1629  if (!remoteversion_str)
1630  pg_fatal("could not get server version");
1632  if (server_version == 0)
1633  pg_fatal("could not parse server version \"%s\"",
1634  remoteversion_str);
1635 
1636  my_version = PG_VERSION_NUM;
1637 
1638  /*
1639  * We allow the server to be back to 9.2, and up to any minor release of
1640  * our own major version. (See also version check in pg_dump.c.)
1641  */
1642  if (my_version != server_version
1643  && (server_version < 90200 ||
1644  (server_version / 100) > (my_version / 100)))
1645  {
1646  pg_log_error("aborting because of server version mismatch");
1647  pg_log_error_detail("server version: %s; %s version: %s",
1648  remoteversion_str, progname, PG_VERSION);
1649  exit_nicely(1);
1650  }
1651 
1653 
1654  return conn;
1655 }
1656 
1657 /* ----------
1658  * Construct a connection string from the given keyword/value pairs. It is
1659  * used to pass the connection options to the pg_dump subprocess.
1660  *
1661  * The following parameters are excluded:
1662  * dbname - varies in each pg_dump invocation
1663  * password - it's not secure to pass a password on the command line
1664  * fallback_application_name - we'll let pg_dump set it
1665  * ----------
1666  */
1667 static char *
1668 constructConnStr(const char **keywords, const char **values)
1669 {
1671  char *connstr;
1672  int i;
1673  bool firstkeyword = true;
1674 
1675  /* Construct a new connection string in key='value' format. */
1676  for (i = 0; keywords[i] != NULL; i++)
1677  {
1678  if (strcmp(keywords[i], "dbname") == 0 ||
1679  strcmp(keywords[i], "password") == 0 ||
1680  strcmp(keywords[i], "fallback_application_name") == 0)
1681  continue;
1682 
1683  if (!firstkeyword)
1684  appendPQExpBufferChar(buf, ' ');
1685  firstkeyword = false;
1686  appendPQExpBuffer(buf, "%s=", keywords[i]);
1688  }
1689 
1690  connstr = pg_strdup(buf->data);
1692  return connstr;
1693 }
1694 
1695 /*
1696  * Run a query, return the results, exit program on failure.
1697  */
1698 static PGresult *
1699 executeQuery(PGconn *conn, const char *query)
1700 {
1701  PGresult *res;
1702 
1703  pg_log_info("executing %s", query);
1704 
1705  res = PQexec(conn, query);
1706  if (!res ||
1708  {
1709  pg_log_error("query failed: %s", PQerrorMessage(conn));
1710  pg_log_error_detail("Query was: %s", query);
1711  PQfinish(conn);
1712  exit_nicely(1);
1713  }
1714 
1715  return res;
1716 }
1717 
1718 /*
1719  * As above for a SQL command (which returns nothing).
1720  */
1721 static void
1722 executeCommand(PGconn *conn, const char *query)
1723 {
1724  PGresult *res;
1725 
1726  pg_log_info("executing %s", query);
1727 
1728  res = PQexec(conn, query);
1729  if (!res ||
1731  {
1732  pg_log_error("query failed: %s", PQerrorMessage(conn));
1733  pg_log_error_detail("Query was: %s", query);
1734  PQfinish(conn);
1735  exit_nicely(1);
1736  }
1737 
1738  PQclear(res);
1739 }
1740 
1741 
1742 /*
1743  * dumpTimestamp
1744  */
1745 static void
1746 dumpTimestamp(const char *msg)
1747 {
1748  char buf[64];
1749  time_t now = time(NULL);
1750 
1751  if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&now)) != 0)
1752  fprintf(OPF, "-- %s %s\n\n", msg, buf);
1753 }
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition: acl.c:743
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1538
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define PG_BINARY_A
Definition: c.h:1269
#define PG_TEXTDOMAIN(domain)
Definition: c.h:1212
#define CppAsString2(x)
Definition: c.h:289
#define PG_BINARY_W
Definition: c.h:1271
int find_my_exec(const char *argv0, char *retpath)
Definition: exec.c:140
void set_pglocale_pgservice(const char *argv0, const char *app)
Definition: exec.c:446
int find_other_exec(const char *argv0, const char *target, const char *versionstr, char *retpath)
Definition: exec.c:335
#define ALWAYS_SECURE_SEARCH_PATH_SQL
Definition: connect.h:25
bool buildACLCommands(const char *name, const char *subname, const char *nspname, const char *type, const char *acls, const char *baseacls, const char *owner, const char *prefix, int remoteVersion, PQExpBuffer sql)
Definition: dumputils.c:64
void buildShSecLabelQuery(const char *catalog_name, Oid objectId, PQExpBuffer sql)
Definition: dumputils.c:637
void makeAlterConfigCommand(PGconn *conn, const char *configitem, const char *type, const char *name, const char *type2, const char *name2, PQExpBuffer buf)
Definition: dumputils.c:823
void emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer, const char *objtype, const char *objname)
Definition: dumputils.c:655
#define PGDUMP_STRFTIME_FMT
Definition: dumputils.h:33
#define _(x)
Definition: elog.c:89
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:588
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:673
const char * PQparameterStatus(const PGconn *conn, const char *paramName)
Definition: fe-connect.c:6873
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6898
PQconninfoOption * PQconninfoParse(const char *conninfo, char **errmsg)
Definition: fe-connect.c:5501
PGconn * PQconnectdbParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:658
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6736
int PQconnectionNeedsPassword(const PGconn *conn)
Definition: fe-connect.c:6959
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6908
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:6855
int PQclientEncoding(const PGconn *conn)
Definition: fe-connect.c:6985
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4261
int PQsetClientEncoding(PGconn *conn, const char *encoding)
Definition: fe-connect.c:6993
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3270
void PQclear(PGresult *res)
Definition: fe-exec.c:718
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3340
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2273
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3735
int PQfnumber(const PGresult *res, const char *field_name)
Definition: fe-exec.c:3448
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3760
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex)
Definition: getopt_long.c:57
#define no_argument
Definition: getopt_long.h:24
#define required_argument
Definition: getopt_long.h:25
#define free(a)
Definition: header.h:65
int i
Definition: isn.c:73
@ CONNECTION_BAD
Definition: libpq-fe.h:61
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:97
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:100
static void const char fflush(stdout)
void pg_logging_increase_verbosity(void)
Definition: logging.c:182
void pg_logging_init(const char *argv0)
Definition: logging.c:83
void pg_logging_set_level(enum pg_log_level new_level)
Definition: logging.c:173
#define pg_log_error(...)
Definition: logging.h:106
#define pg_log_error_hint(...)
Definition: logging.h:112
#define pg_log_info(...)
Definition: logging.h:124
@ PG_LOG_WARNING
Definition: logging.h:38
#define pg_log_error_detail(...)
Definition: logging.h:109
#define pg_fatal(...)
#define MAXPGPATH
int32 encoding
Definition: pg_database.h:41
static void dumpTimestamp(const char *msg)
Definition: pg_dumpall.c:1746
static int if_exists
Definition: pg_dumpall.c:73
static int on_conflict_do_nothing
Definition: pg_dumpall.c:87
int main(int argc, char *argv[])
Definition: pg_dumpall.c:102
static void dropTablespaces(PGconn *conn)
Definition: pg_dumpall.c:1039
static void expand_dbname_patterns(PGconn *conn, SimpleStringList *patterns, SimpleStringList *names)
Definition: pg_dumpall.c:1252
static int no_role_passwords
Definition: pg_dumpall.c:84
static PQExpBuffer pgdumpopts
Definition: pg_dumpall.c:62
static int no_table_access_method
Definition: pg_dumpall.c:75
static int no_unlogged_table_data
Definition: pg_dumpall.c:83
#define PG_AUTHID
Definition: pg_dumpall.c:90
static int binary_upgrade
Definition: pg_dumpall.c:69
static int disable_triggers
Definition: pg_dumpall.c:72
static void dumpUserConfig(PGconn *conn, const char *username)
Definition: pg_dumpall.c:1216
static bool dosync
Definition: pg_dumpall.c:67
static char * connstr
Definition: pg_dumpall.c:63
static SimpleStringList database_exclude_patterns
Definition: pg_dumpall.c:96
static void dumpTablespaces(PGconn *conn)
Definition: pg_dumpall.c:1074
static void dumpRoleMembership(PGconn *conn)
Definition: pg_dumpall.c:924
#define exit_nicely(code)
Definition: pg_dumpall.c:99
static char pg_dump_bin[MAXPGPATH]
Definition: pg_dumpall.c:60
static SimpleStringList database_exclude_names
Definition: pg_dumpall.c:97
static FILE * OPF
Definition: pg_dumpall.c:93
static int no_comments
Definition: pg_dumpall.c:78
static char * constructConnStr(const char **keywords, const char **values)
Definition: pg_dumpall.c:1668
static int no_publications
Definition: pg_dumpall.c:79
static int no_security_labels
Definition: pg_dumpall.c:80
static void dumpDatabases(PGconn *conn)
Definition: pg_dumpall.c:1305
static int disable_dollar_quoting
Definition: pg_dumpall.c:71
static void buildShSecLabels(PGconn *conn, const char *catalog_name, Oid objectId, const char *objtype, const char *objname, PQExpBuffer buffer)
Definition: pg_dumpall.c:1450
static int no_tablespaces
Definition: pg_dumpall.c:76
static int no_toast_compression
Definition: pg_dumpall.c:82
#define PG_ROLES
Definition: pg_dumpall.c:91
static PGconn * connectDatabase(const char *dbname, const char *connstr, const char *pghost, const char *pgport, const char *pguser, trivalue prompt_password, bool fail_on_error)
Definition: pg_dumpall.c:1476
static int inserts
Definition: pg_dumpall.c:74
static void executeCommand(PGconn *conn, const char *query)
Definition: pg_dumpall.c:1722
static bool verbose
Definition: pg_dumpall.c:66
static int runPgDump(const char *dbname, const char *create_opts)
Definition: pg_dumpall.c:1398
static void dumpRoleGUCPrivs(PGconn *conn)
Definition: pg_dumpall.c:984
static void dumpRoles(PGconn *conn)
Definition: pg_dumpall.c:719
static PGresult * executeQuery(PGconn *conn, const char *query)
Definition: pg_dumpall.c:1699
static void help(void)
Definition: pg_dumpall.c:602
static int use_setsessauth
Definition: pg_dumpall.c:77
static int load_via_partition_root
Definition: pg_dumpall.c:86
static int column_inserts
Definition: pg_dumpall.c:70
static void dropRoles(PGconn *conn)
Definition: pg_dumpall.c:672
static void dropDBs(PGconn *conn)
Definition: pg_dumpall.c:1169
static int server_version
Definition: pg_dumpall.c:85
static char role_catalog[10]
Definition: pg_dumpall.c:89
static const char * progname
Definition: pg_dumpall.c:61
static bool output_clean
Definition: pg_dumpall.c:64
static int no_subscriptions
Definition: pg_dumpall.c:81
static char * filename
Definition: pg_dumpall.c:94
#define PGDUMP_VERSIONSTR
Definition: pg_dumpall.c:32
static bool skip_acls
Definition: pg_dumpall.c:65
PGDLLIMPORT int optind
Definition: getopt.c:50
PGDLLIMPORT char * optarg
Definition: getopt.c:52
static char * buf
Definition: pg_test_fsync.c:67
const char * pghost
Definition: pgbench.c:307
const char * username
Definition: pgbench.c:309
const char * pgport
Definition: pgbench.c:308
#define pg_log_warning(...)
Definition: pgfnames.c:24
#define sprintf
Definition: port.h:227
const char * get_progname(const char *argv0)
Definition: path.c:574
#define fprintf
Definition: port.h:229
#define printf(...)
Definition: port.h:231
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
unsigned int Oid
Definition: postgres_ext.h:31
#define atooid(x)
Definition: postgres_ext.h:42
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:74
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:116
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
char * c
bool quote_all_identifiers
Definition: ruleutils.c:323
bool simple_string_list_member(SimpleStringList *list, const char *val)
Definition: simple_list.c:87
void simple_string_list_append(SimpleStringList *list, const char *val)
Definition: simple_list.c:63
char * simple_prompt(const char *prompt, bool echo)
Definition: sprompt.c:38
static char * password
Definition: streamutil.c:53
char * connection_string
Definition: streamutil.c:47
char * dbname
Definition: streamutil.c:51
PGconn * conn
Definition: streamutil.c:54
void appendShellString(PQExpBuffer buf, const char *str)
Definition: string_utils.c:429
void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
Definition: string_utils.c:293
bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule, PQExpBuffer dbnamebuf, int *dotcnt)
Definition: string_utils.c:893
const char * fmtId(const char *rawid)
Definition: string_utils.c:64
void appendConnStrVal(PQExpBuffer buf, const char *str)
Definition: string_utils.c:545
struct SimpleStringListCell * next
Definition: simple_list.h:34
SimpleStringListCell * head
Definition: simple_list.h:42
trivalue
Definition: vacuumlo.c:35
@ TRI_YES
Definition: vacuumlo.c:38
@ TRI_DEFAULT
Definition: vacuumlo.c:36
@ TRI_NO
Definition: vacuumlo.c:37