1 /*-------------------------------------------------------------------------
5 * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
8 * pg_dumpall forces all pg_dump output to be text, since it also outputs
9 * text into the same output stream.
11 * src/bin/pg_dump/pg_dumpall.c
13 *-------------------------------------------------------------------------
16 #include "postgres_fe.h"
21 #include "getopt_long.h"
23 #include "dumputils.h"
24 #include "pg_backup.h"
25 #include "common/file_utils.h"
26 #include "fe_utils/string_utils.h"
28 /* version string we expect back from pg_dump */
29 #define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
32 static void help(void);
34 static void dropRoles(PGconn *conn);
35 static void dumpRoles(PGconn *conn);
36 static void dumpRoleMembership(PGconn *conn);
37 static void dumpGroups(PGconn *conn);
38 static void dropTablespaces(PGconn *conn);
39 static void dumpTablespaces(PGconn *conn);
40 static void dropDBs(PGconn *conn);
41 static void dumpUserConfig(PGconn *conn, const char *username);
42 static void dumpDatabases(PGconn *conn);
43 static void dumpTimestamp(const char *msg);
44 static int runPgDump(const char *dbname, const char *create_opts);
45 static void buildShSecLabels(PGconn *conn,
46 const char *catalog_name, Oid objectId,
47 const char *objtype, const char *objname,
49 static PGconn *connectDatabase(const char *dbname, const char *connstr, const char *pghost, const char *pgport,
50 const char *pguser, trivalue prompt_password, bool fail_on_error);
51 static char *constructConnStr(const char **keywords, const char **values);
52 static PGresult *executeQuery(PGconn *conn, const char *query);
53 static void executeCommand(PGconn *conn, const char *query);
55 static char pg_dump_bin[MAXPGPATH];
56 static const char *progname;
57 static PQExpBuffer pgdumpopts;
58 static char *connstr = "";
59 static bool output_clean = false;
60 static bool skip_acls = false;
61 static bool verbose = false;
62 static bool dosync = true;
64 static int binary_upgrade = 0;
65 static int column_inserts = 0;
66 static int disable_dollar_quoting = 0;
67 static int disable_triggers = 0;
68 static int if_exists = 0;
69 static int inserts = 0;
70 static int no_tablespaces = 0;
71 static int use_setsessauth = 0;
72 static int no_comments = 0;
73 static int no_publications = 0;
74 static int no_security_labels = 0;
75 static int no_subscriptions = 0;
76 static int no_unlogged_table_data = 0;
77 static int no_role_passwords = 0;
78 static int server_version;
79 static int load_via_partition_root = 0;
81 static char role_catalog[10];
82 #define PG_AUTHID "pg_authid"
83 #define PG_ROLES "pg_roles "
86 static char *filename = NULL;
88 #define exit_nicely(code) exit(code)
91 main(int argc, char *argv[])
93 static struct option long_options[] = {
94 {"data-only", no_argument, NULL, 'a'},
95 {"clean", no_argument, NULL, 'c'},
96 {"encoding", required_argument, NULL, 'E'},
97 {"file", required_argument, NULL, 'f'},
98 {"globals-only", no_argument, NULL, 'g'},
99 {"host", required_argument, NULL, 'h'},
100 {"dbname", required_argument, NULL, 'd'},
101 {"database", required_argument, NULL, 'l'},
102 {"oids", no_argument, NULL, 'o'},
103 {"no-owner", no_argument, NULL, 'O'},
104 {"port", required_argument, NULL, 'p'},
105 {"roles-only", no_argument, NULL, 'r'},
106 {"schema-only", no_argument, NULL, 's'},
107 {"superuser", required_argument, NULL, 'S'},
108 {"tablespaces-only", no_argument, NULL, 't'},
109 {"username", required_argument, NULL, 'U'},
110 {"verbose", no_argument, NULL, 'v'},
111 {"no-password", no_argument, NULL, 'w'},
112 {"password", no_argument, NULL, 'W'},
113 {"no-privileges", no_argument, NULL, 'x'},
114 {"no-acl", no_argument, NULL, 'x'},
117 * the following options don't have an equivalent short option letter
119 {"attribute-inserts", no_argument, &column_inserts, 1},
120 {"binary-upgrade", no_argument, &binary_upgrade, 1},
121 {"column-inserts", no_argument, &column_inserts, 1},
122 {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
123 {"disable-triggers", no_argument, &disable_triggers, 1},
124 {"if-exists", no_argument, &if_exists, 1},
125 {"inserts", no_argument, &inserts, 1},
126 {"lock-wait-timeout", required_argument, NULL, 2},
127 {"no-tablespaces", no_argument, &no_tablespaces, 1},
128 {"quote-all-identifiers", no_argument, "e_all_identifiers, 1},
129 {"load-via-partition-root", no_argument, &load_via_partition_root, 1},
130 {"role", required_argument, NULL, 3},
131 {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
132 {"no-comments", no_argument, &no_comments, 1},
133 {"no-publications", no_argument, &no_publications, 1},
134 {"no-role-passwords", no_argument, &no_role_passwords, 1},
135 {"no-security-labels", no_argument, &no_security_labels, 1},
136 {"no-subscriptions", no_argument, &no_subscriptions, 1},
137 {"no-sync", no_argument, NULL, 4},
138 {"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
147 char *use_role = NULL;
148 const char *dumpencoding = NULL;
149 trivalue prompt_password = TRI_DEFAULT;
150 bool data_only = false;
151 bool globals_only = false;
152 bool roles_only = false;
153 bool tablespaces_only = false;
156 const char *std_strings;
161 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
163 progname = get_progname(argv[0]);
167 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
172 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
174 puts("pg_dumpall (PostgreSQL) " PG_VERSION);
179 if ((ret = find_other_exec(argv[0], "pg_dump", PGDUMP_VERSIONSTR,
182 char full_path[MAXPGPATH];
184 if (find_my_exec(argv[0], full_path) < 0)
185 strlcpy(full_path, progname, sizeof(full_path));
189 _("The program \"pg_dump\" is needed by %s "
190 "but was not found in the\n"
191 "same directory as \"%s\".\n"
192 "Check your installation.\n"),
193 progname, full_path);
196 _("The program \"pg_dump\" was found by \"%s\"\n"
197 "but was not the same version as %s.\n"
198 "Check your installation.\n"),
199 full_path, progname);
203 pgdumpopts = createPQExpBuffer();
205 while ((c = getopt_long(argc, argv, "acd:E:f:gh:l:oOp:rsS:tU:vwWx", long_options, &optindex)) != -1)
211 appendPQExpBufferStr(pgdumpopts, " -a");
219 connstr = pg_strdup(optarg);
223 dumpencoding = pg_strdup(optarg);
224 appendPQExpBufferStr(pgdumpopts, " -E ");
225 appendShellString(pgdumpopts, optarg);
229 filename = pg_strdup(optarg);
230 appendPQExpBufferStr(pgdumpopts, " -f ");
231 appendShellString(pgdumpopts, filename);
239 pghost = pg_strdup(optarg);
243 pgdb = pg_strdup(optarg);
247 appendPQExpBufferStr(pgdumpopts, " -o");
251 appendPQExpBufferStr(pgdumpopts, " -O");
255 pgport = pg_strdup(optarg);
263 appendPQExpBufferStr(pgdumpopts, " -s");
267 appendPQExpBufferStr(pgdumpopts, " -S ");
268 appendShellString(pgdumpopts, optarg);
272 tablespaces_only = true;
276 pguser = pg_strdup(optarg);
281 appendPQExpBufferStr(pgdumpopts, " -v");
285 prompt_password = TRI_NO;
286 appendPQExpBufferStr(pgdumpopts, " -w");
290 prompt_password = TRI_YES;
291 appendPQExpBufferStr(pgdumpopts, " -W");
296 appendPQExpBufferStr(pgdumpopts, " -x");
303 appendPQExpBufferStr(pgdumpopts, " --lock-wait-timeout ");
304 appendShellString(pgdumpopts, optarg);
308 use_role = pg_strdup(optarg);
309 appendPQExpBufferStr(pgdumpopts, " --role ");
310 appendShellString(pgdumpopts, use_role);
315 appendPQExpBufferStr(pgdumpopts, " --no-sync");
319 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
324 /* Complain if any arguments remain */
327 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
328 progname, argv[optind]);
329 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
334 /* Make sure the user hasn't specified a mix of globals-only options */
335 if (globals_only && roles_only)
337 fprintf(stderr, _("%s: options -g/--globals-only and -r/--roles-only cannot be used together\n"),
339 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
344 if (globals_only && tablespaces_only)
346 fprintf(stderr, _("%s: options -g/--globals-only and -t/--tablespaces-only cannot be used together\n"),
348 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
353 if (if_exists && !output_clean)
355 fprintf(stderr, _("%s: option --if-exists requires option -c/--clean\n"),
360 if (roles_only && tablespaces_only)
362 fprintf(stderr, _("%s: options -r/--roles-only and -t/--tablespaces-only cannot be used together\n"),
364 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
370 * If password values are not required in the dump, switch to using
371 * pg_roles which is equally useful, just more likely to have unrestricted
372 * access than pg_authid.
374 if (no_role_passwords)
375 sprintf(role_catalog, "%s", PG_ROLES);
377 sprintf(role_catalog, "%s", PG_AUTHID);
379 /* Add long options to the pg_dump argument list */
381 appendPQExpBufferStr(pgdumpopts, " --binary-upgrade");
383 appendPQExpBufferStr(pgdumpopts, " --column-inserts");
384 if (disable_dollar_quoting)
385 appendPQExpBufferStr(pgdumpopts, " --disable-dollar-quoting");
386 if (disable_triggers)
387 appendPQExpBufferStr(pgdumpopts, " --disable-triggers");
389 appendPQExpBufferStr(pgdumpopts, " --inserts");
391 appendPQExpBufferStr(pgdumpopts, " --no-tablespaces");
392 if (quote_all_identifiers)
393 appendPQExpBufferStr(pgdumpopts, " --quote-all-identifiers");
394 if (load_via_partition_root)
395 appendPQExpBufferStr(pgdumpopts, " --load-via-partition-root");
397 appendPQExpBufferStr(pgdumpopts, " --use-set-session-authorization");
399 appendPQExpBufferStr(pgdumpopts, " --no-comments");
401 appendPQExpBufferStr(pgdumpopts, " --no-publications");
402 if (no_security_labels)
403 appendPQExpBufferStr(pgdumpopts, " --no-security-labels");
404 if (no_subscriptions)
405 appendPQExpBufferStr(pgdumpopts, " --no-subscriptions");
406 if (no_unlogged_table_data)
407 appendPQExpBufferStr(pgdumpopts, " --no-unlogged-table-data");
410 * If there was a database specified on the command line, use that,
411 * otherwise try to connect to database "postgres", and failing that
412 * "template1". "postgres" is the preferred choice for 8.1 and later
413 * servers, but it usually will not exist on older ones.
417 conn = connectDatabase(pgdb, connstr, pghost, pgport, pguser,
418 prompt_password, false);
422 fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
429 conn = connectDatabase("postgres", connstr, pghost, pgport, pguser,
430 prompt_password, false);
432 conn = connectDatabase("template1", connstr, pghost, pgport, pguser,
433 prompt_password, true);
437 fprintf(stderr, _("%s: could not connect to databases \"postgres\" or \"template1\"\n"
438 "Please specify an alternative database.\n"),
440 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
447 * Open the output file if required, otherwise use stdout
451 OPF = fopen(filename, PG_BINARY_W);
454 fprintf(stderr, _("%s: could not open the output file \"%s\": %s\n"),
455 progname, filename, strerror(errno));
463 * Set the client encoding if requested.
467 if (PQsetClientEncoding(conn, dumpencoding) < 0)
469 fprintf(stderr, _("%s: invalid client encoding \"%s\" specified\n"),
470 progname, dumpencoding);
476 * Get the active encoding and the standard_conforming_strings setting, so
477 * we know how to escape strings.
479 encoding = PQclientEncoding(conn);
480 std_strings = PQparameterStatus(conn, "standard_conforming_strings");
484 /* Set the role if requested */
485 if (use_role && server_version >= 80100)
487 PQExpBuffer query = createPQExpBuffer();
489 appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
490 executeCommand(conn, query->data);
491 destroyPQExpBuffer(query);
494 /* Force quoting of all identifiers if requested. */
495 if (quote_all_identifiers && server_version >= 90100)
496 executeCommand(conn, "SET quote_all_identifiers = true");
498 fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n");
500 dumpTimestamp("Started on");
503 * We used to emit \connect postgres here, but that served no purpose
504 * other than to break things for installations without a postgres
505 * database. Everything we're restoring here is a global, so whichever
506 * database we're connected to at the moment is fine.
509 /* Restore will need to write to the target cluster */
510 fprintf(OPF, "SET default_transaction_read_only = off;\n\n");
512 /* Replicate encoding and std_strings in output */
513 fprintf(OPF, "SET client_encoding = '%s';\n",
514 pg_encoding_to_char(encoding));
515 fprintf(OPF, "SET standard_conforming_strings = %s;\n", std_strings);
516 if (strcmp(std_strings, "off") == 0)
517 fprintf(OPF, "SET escape_string_warning = off;\n");
523 * If asked to --clean, do that first. We can avoid detailed
524 * dependency analysis because databases never depend on each other,
525 * and tablespaces never depend on each other. Roles could have
526 * grants to each other, but DROP ROLE will clean those up silently.
530 if (!globals_only && !roles_only && !tablespaces_only)
533 if (!roles_only && !no_tablespaces)
534 dropTablespaces(conn);
536 if (!tablespaces_only)
541 * Now create objects as requested. Be careful that option logic here
542 * is the same as for drops above.
544 if (!tablespaces_only)
546 /* Dump roles (users) */
549 /* Dump role memberships --- need different method for pre-8.1 */
550 if (server_version >= 80100)
551 dumpRoleMembership(conn);
556 /* Dump tablespaces */
557 if (!roles_only && !no_tablespaces)
558 dumpTablespaces(conn);
561 if (!globals_only && !roles_only && !tablespaces_only)
567 dumpTimestamp("Completed on");
568 fprintf(OPF, "--\n-- PostgreSQL database cluster dump complete\n--\n\n");
574 /* sync the resulting file, errors are not fatal */
576 (void) fsync_fname(filename, false, progname);
586 printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname);
587 printf(_("Usage:\n"));
588 printf(_(" %s [OPTION]...\n"), progname);
590 printf(_("\nGeneral options:\n"));
591 printf(_(" -f, --file=FILENAME output file name\n"));
592 printf(_(" -v, --verbose verbose mode\n"));
593 printf(_(" -V, --version output version information, then exit\n"));
594 printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
595 printf(_(" -?, --help show this help, then exit\n"));
596 printf(_("\nOptions controlling the output content:\n"));
597 printf(_(" -a, --data-only dump only the data, not the schema\n"));
598 printf(_(" -c, --clean clean (drop) databases before recreating\n"));
599 printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
600 printf(_(" -g, --globals-only dump only global objects, no databases\n"));
601 printf(_(" -o, --oids include OIDs in dump\n"));
602 printf(_(" -O, --no-owner skip restoration of object ownership\n"));
603 printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n"));
604 printf(_(" -s, --schema-only dump only the schema, no data\n"));
605 printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n"));
606 printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n"));
607 printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
608 printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
609 printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
610 printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
611 printf(_(" --disable-triggers disable triggers during data-only restore\n"));
612 printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
613 printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
614 printf(_(" --no-comments do not dump comments\n"));
615 printf(_(" --no-publications do not dump publications\n"));
616 printf(_(" --no-role-passwords do not dump passwords for roles\n"));
617 printf(_(" --no-security-labels do not dump security label assignments\n"));
618 printf(_(" --no-subscriptions do not dump subscriptions\n"));
619 printf(_(" --no-sync do not wait for changes to be written safely to disk\n"));
620 printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
621 printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
622 printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
623 printf(_(" --load-via-partition-root load partitions via the root table\n"));
624 printf(_(" --use-set-session-authorization\n"
625 " use SET SESSION AUTHORIZATION commands instead of\n"
626 " ALTER OWNER commands to set ownership\n"));
628 printf(_("\nConnection options:\n"));
629 printf(_(" -d, --dbname=CONNSTR connect using connection string\n"));
630 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
631 printf(_(" -l, --database=DBNAME alternative default database\n"));
632 printf(_(" -p, --port=PORT database server port number\n"));
633 printf(_(" -U, --username=NAME connect as specified database user\n"));
634 printf(_(" -w, --no-password never prompt for password\n"));
635 printf(_(" -W, --password force password prompt (should happen automatically)\n"));
636 printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
638 printf(_("\nIf -f/--file is not used, then the SQL script will be written to the standard\n"
640 printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
648 dropRoles(PGconn *conn)
650 PQExpBuffer buf = createPQExpBuffer();
655 if (server_version >= 90600)
656 printfPQExpBuffer(buf,
659 "WHERE rolname !~ '^pg_' "
660 "ORDER BY 1", role_catalog);
661 else if (server_version >= 80100)
662 printfPQExpBuffer(buf,
665 "ORDER BY 1", role_catalog);
667 printfPQExpBuffer(buf,
668 "SELECT usename as rolname "
671 "SELECT groname as rolname "
675 res = executeQuery(conn, buf->data);
677 i_rolname = PQfnumber(res, "rolname");
679 if (PQntuples(res) > 0)
680 fprintf(OPF, "--\n-- Drop roles\n--\n\n");
682 for (i = 0; i < PQntuples(res); i++)
684 const char *rolename;
686 rolename = PQgetvalue(res, i, i_rolname);
688 fprintf(OPF, "DROP ROLE %s%s;\n",
689 if_exists ? "IF EXISTS " : "",
694 destroyPQExpBuffer(buf);
696 fprintf(OPF, "\n\n");
703 dumpRoles(PGconn *conn)
705 PQExpBuffer buf = createPQExpBuffer();
723 /* note: rolconfig is dumped later */
724 if (server_version >= 90600)
725 printfPQExpBuffer(buf,
726 "SELECT oid, rolname, rolsuper, rolinherit, "
727 "rolcreaterole, rolcreatedb, "
728 "rolcanlogin, rolconnlimit, rolpassword, "
729 "rolvaliduntil, rolreplication, rolbypassrls, "
730 "pg_catalog.shobj_description(oid, '%s') as rolcomment, "
731 "rolname = current_user AS is_current_user "
733 "WHERE rolname !~ '^pg_' "
734 "ORDER BY 2", role_catalog, role_catalog);
735 else if (server_version >= 90500)
736 printfPQExpBuffer(buf,
737 "SELECT oid, rolname, rolsuper, rolinherit, "
738 "rolcreaterole, rolcreatedb, "
739 "rolcanlogin, rolconnlimit, rolpassword, "
740 "rolvaliduntil, rolreplication, rolbypassrls, "
741 "pg_catalog.shobj_description(oid, '%s') as rolcomment, "
742 "rolname = current_user AS is_current_user "
744 "ORDER BY 2", role_catalog, role_catalog);
745 else if (server_version >= 90100)
746 printfPQExpBuffer(buf,
747 "SELECT oid, rolname, rolsuper, rolinherit, "
748 "rolcreaterole, rolcreatedb, "
749 "rolcanlogin, rolconnlimit, rolpassword, "
750 "rolvaliduntil, rolreplication, "
751 "false as rolbypassrls, "
752 "pg_catalog.shobj_description(oid, '%s') as rolcomment, "
753 "rolname = current_user AS is_current_user "
755 "ORDER BY 2", role_catalog, role_catalog);
756 else if (server_version >= 80200)
757 printfPQExpBuffer(buf,
758 "SELECT oid, rolname, rolsuper, rolinherit, "
759 "rolcreaterole, rolcreatedb, "
760 "rolcanlogin, rolconnlimit, rolpassword, "
761 "rolvaliduntil, false as rolreplication, "
762 "false as rolbypassrls, "
763 "pg_catalog.shobj_description(oid, '%s') as rolcomment, "
764 "rolname = current_user AS is_current_user "
766 "ORDER BY 2", role_catalog, role_catalog);
767 else if (server_version >= 80100)
768 printfPQExpBuffer(buf,
769 "SELECT oid, rolname, rolsuper, rolinherit, "
770 "rolcreaterole, rolcreatedb, "
771 "rolcanlogin, rolconnlimit, rolpassword, "
772 "rolvaliduntil, false as rolreplication, "
773 "false as rolbypassrls, "
774 "null as rolcomment, "
775 "rolname = current_user AS is_current_user "
777 "ORDER BY 2", role_catalog);
779 printfPQExpBuffer(buf,
780 "SELECT 0 as oid, usename as rolname, "
781 "usesuper as rolsuper, "
782 "true as rolinherit, "
783 "usesuper as rolcreaterole, "
784 "usecreatedb as rolcreatedb, "
785 "true as rolcanlogin, "
786 "-1 as rolconnlimit, "
787 "passwd as rolpassword, "
788 "valuntil as rolvaliduntil, "
789 "false as rolreplication, "
790 "false as rolbypassrls, "
791 "null as rolcomment, "
792 "usename = current_user AS is_current_user "
795 "SELECT 0 as oid, groname as rolname, "
796 "false as rolsuper, "
797 "true as rolinherit, "
798 "false as rolcreaterole, "
799 "false as rolcreatedb, "
800 "false as rolcanlogin, "
801 "-1 as rolconnlimit, "
802 "null::text as rolpassword, "
803 "null::abstime as rolvaliduntil, "
804 "false as rolreplication, "
805 "false as rolbypassrls, "
806 "null as rolcomment, "
807 "false AS is_current_user "
809 "WHERE NOT EXISTS (SELECT 1 FROM pg_shadow "
810 " WHERE usename = groname) "
813 res = executeQuery(conn, buf->data);
815 i_oid = PQfnumber(res, "oid");
816 i_rolname = PQfnumber(res, "rolname");
817 i_rolsuper = PQfnumber(res, "rolsuper");
818 i_rolinherit = PQfnumber(res, "rolinherit");
819 i_rolcreaterole = PQfnumber(res, "rolcreaterole");
820 i_rolcreatedb = PQfnumber(res, "rolcreatedb");
821 i_rolcanlogin = PQfnumber(res, "rolcanlogin");
822 i_rolconnlimit = PQfnumber(res, "rolconnlimit");
823 i_rolpassword = PQfnumber(res, "rolpassword");
824 i_rolvaliduntil = PQfnumber(res, "rolvaliduntil");
825 i_rolreplication = PQfnumber(res, "rolreplication");
826 i_rolbypassrls = PQfnumber(res, "rolbypassrls");
827 i_rolcomment = PQfnumber(res, "rolcomment");
828 i_is_current_user = PQfnumber(res, "is_current_user");
830 if (PQntuples(res) > 0)
831 fprintf(OPF, "--\n-- Roles\n--\n\n");
833 for (i = 0; i < PQntuples(res); i++)
835 const char *rolename;
838 auth_oid = atooid(PQgetvalue(res, i, i_oid));
839 rolename = PQgetvalue(res, i, i_rolname);
841 if (strncmp(rolename, "pg_", 3) == 0)
843 fprintf(stderr, _("%s: role name starting with \"pg_\" skipped (%s)\n"),
848 resetPQExpBuffer(buf);
852 appendPQExpBufferStr(buf, "\n-- For binary upgrade, must preserve pg_authid.oid\n");
853 appendPQExpBuffer(buf,
854 "SELECT pg_catalog.binary_upgrade_set_next_pg_authid_oid('%u'::pg_catalog.oid);\n\n",
859 * We dump CREATE ROLE followed by ALTER ROLE to ensure that the role
860 * will acquire the right properties even if it already exists (ie, it
861 * won't hurt for the CREATE to fail). This is particularly important
862 * for the role we are connected as, since even with --clean we will
863 * have failed to drop it. binary_upgrade cannot generate any errors,
864 * so we assume the current role is already created.
866 if (!binary_upgrade ||
867 strcmp(PQgetvalue(res, i, i_is_current_user), "f") == 0)
868 appendPQExpBuffer(buf, "CREATE ROLE %s;\n", fmtId(rolename));
869 appendPQExpBuffer(buf, "ALTER ROLE %s WITH", fmtId(rolename));
871 if (strcmp(PQgetvalue(res, i, i_rolsuper), "t") == 0)
872 appendPQExpBufferStr(buf, " SUPERUSER");
874 appendPQExpBufferStr(buf, " NOSUPERUSER");
876 if (strcmp(PQgetvalue(res, i, i_rolinherit), "t") == 0)
877 appendPQExpBufferStr(buf, " INHERIT");
879 appendPQExpBufferStr(buf, " NOINHERIT");
881 if (strcmp(PQgetvalue(res, i, i_rolcreaterole), "t") == 0)
882 appendPQExpBufferStr(buf, " CREATEROLE");
884 appendPQExpBufferStr(buf, " NOCREATEROLE");
886 if (strcmp(PQgetvalue(res, i, i_rolcreatedb), "t") == 0)
887 appendPQExpBufferStr(buf, " CREATEDB");
889 appendPQExpBufferStr(buf, " NOCREATEDB");
891 if (strcmp(PQgetvalue(res, i, i_rolcanlogin), "t") == 0)
892 appendPQExpBufferStr(buf, " LOGIN");
894 appendPQExpBufferStr(buf, " NOLOGIN");
896 if (strcmp(PQgetvalue(res, i, i_rolreplication), "t") == 0)
897 appendPQExpBufferStr(buf, " REPLICATION");
899 appendPQExpBufferStr(buf, " NOREPLICATION");
901 if (strcmp(PQgetvalue(res, i, i_rolbypassrls), "t") == 0)
902 appendPQExpBufferStr(buf, " BYPASSRLS");
904 appendPQExpBufferStr(buf, " NOBYPASSRLS");
906 if (strcmp(PQgetvalue(res, i, i_rolconnlimit), "-1") != 0)
907 appendPQExpBuffer(buf, " CONNECTION LIMIT %s",
908 PQgetvalue(res, i, i_rolconnlimit));
911 if (!PQgetisnull(res, i, i_rolpassword) && !no_role_passwords)
913 appendPQExpBufferStr(buf, " PASSWORD ");
914 appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolpassword), conn);
917 if (!PQgetisnull(res, i, i_rolvaliduntil))
918 appendPQExpBuffer(buf, " VALID UNTIL '%s'",
919 PQgetvalue(res, i, i_rolvaliduntil));
921 appendPQExpBufferStr(buf, ";\n");
923 if (!no_comments && !PQgetisnull(res, i, i_rolcomment))
925 appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
926 appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolcomment), conn);
927 appendPQExpBufferStr(buf, ";\n");
930 if (!no_security_labels && server_version >= 90200)
931 buildShSecLabels(conn, "pg_authid", auth_oid,
935 fprintf(OPF, "%s", buf->data);
939 * Dump configuration settings for roles after all roles have been dumped.
940 * We do it this way because config settings for roles could mention the
941 * names of other roles.
943 for (i = 0; i < PQntuples(res); i++)
944 dumpUserConfig(conn, PQgetvalue(res, i, i_rolname));
948 fprintf(OPF, "\n\n");
950 destroyPQExpBuffer(buf);
955 * Dump role memberships. This code is used for 8.1 and later servers.
957 * Note: we expect dumpRoles already created all the roles, but there is
961 dumpRoleMembership(PGconn *conn)
963 PQExpBuffer buf = createPQExpBuffer();
967 printfPQExpBuffer(buf, "SELECT ur.rolname AS roleid, "
968 "um.rolname AS member, "
970 "ug.rolname AS grantor "
971 "FROM pg_auth_members a "
972 "LEFT JOIN %s ur on ur.oid = a.roleid "
973 "LEFT JOIN %s um on um.oid = a.member "
974 "LEFT JOIN %s ug on ug.oid = a.grantor "
975 "WHERE NOT (ur.rolname ~ '^pg_' AND um.rolname ~ '^pg_')"
976 "ORDER BY 1,2,3", role_catalog, role_catalog, role_catalog);
977 res = executeQuery(conn, buf->data);
979 if (PQntuples(res) > 0)
980 fprintf(OPF, "--\n-- Role memberships\n--\n\n");
982 for (i = 0; i < PQntuples(res); i++)
984 char *roleid = PQgetvalue(res, i, 0);
985 char *member = PQgetvalue(res, i, 1);
986 char *option = PQgetvalue(res, i, 2);
988 fprintf(OPF, "GRANT %s", fmtId(roleid));
989 fprintf(OPF, " TO %s", fmtId(member));
991 fprintf(OPF, " WITH ADMIN OPTION");
994 * We don't track the grantor very carefully in the backend, so cope
995 * with the possibility that it has been dropped.
997 if (!PQgetisnull(res, i, 3))
999 char *grantor = PQgetvalue(res, i, 3);
1001 fprintf(OPF, " GRANTED BY %s", fmtId(grantor));
1003 fprintf(OPF, ";\n");
1007 destroyPQExpBuffer(buf);
1009 fprintf(OPF, "\n\n");
1013 * Dump group memberships from a pre-8.1 server. It's annoying that we
1014 * can't share any useful amount of code with the post-8.1 case, but
1015 * the catalog representations are too different.
1017 * Note: we expect dumpRoles already created all the roles, but there is
1018 * no membership yet.
1021 dumpGroups(PGconn *conn)
1023 PQExpBuffer buf = createPQExpBuffer();
1027 res = executeQuery(conn,
1028 "SELECT groname, grolist FROM pg_group ORDER BY 1");
1030 if (PQntuples(res) > 0)
1031 fprintf(OPF, "--\n-- Role memberships\n--\n\n");
1033 for (i = 0; i < PQntuples(res); i++)
1035 char *groname = PQgetvalue(res, i, 0);
1036 char *grolist = PQgetvalue(res, i, 1);
1041 * Array representation is {1,2,3} ... convert to (1,2,3)
1043 if (strlen(grolist) < 3)
1046 grolist = pg_strdup(grolist);
1048 grolist[strlen(grolist) - 1] = ')';
1049 printfPQExpBuffer(buf,
1050 "SELECT usename FROM pg_shadow "
1051 "WHERE usesysid IN %s ORDER BY 1",
1055 res2 = executeQuery(conn, buf->data);
1057 for (j = 0; j < PQntuples(res2); j++)
1059 char *usename = PQgetvalue(res2, j, 0);
1062 * Don't try to grant a role to itself; can happen if old
1063 * installation has identically named user and group.
1065 if (strcmp(groname, usename) == 0)
1068 fprintf(OPF, "GRANT %s", fmtId(groname));
1069 fprintf(OPF, " TO %s;\n", fmtId(usename));
1076 destroyPQExpBuffer(buf);
1078 fprintf(OPF, "\n\n");
1086 dropTablespaces(PGconn *conn)
1092 * Get all tablespaces except built-in ones (which we assume are named
1095 res = executeQuery(conn, "SELECT spcname "
1096 "FROM pg_catalog.pg_tablespace "
1097 "WHERE spcname !~ '^pg_' "
1100 if (PQntuples(res) > 0)
1101 fprintf(OPF, "--\n-- Drop tablespaces\n--\n\n");
1103 for (i = 0; i < PQntuples(res); i++)
1105 char *spcname = PQgetvalue(res, i, 0);
1107 fprintf(OPF, "DROP TABLESPACE %s%s;\n",
1108 if_exists ? "IF EXISTS " : "",
1114 fprintf(OPF, "\n\n");
1121 dumpTablespaces(PGconn *conn)
1127 * Get all tablespaces except built-in ones (which we assume are named
1130 * For the tablespace ACLs, as of 9.6, we extract both the positive (as
1131 * spcacl) and negative (as rspcacl) ACLs, relative to the default ACL for
1132 * tablespaces, which are then passed to buildACLCommands() below.
1134 * See buildACLQueries() and buildACLCommands().
1136 * Note that we do not support initial privileges (pg_init_privs) on
1139 if (server_version >= 90600)
1140 res = executeQuery(conn, "SELECT oid, spcname, "
1141 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
1142 "pg_catalog.pg_tablespace_location(oid), "
1143 "(SELECT pg_catalog.array_agg(acl) FROM (SELECT pg_catalog.unnest(coalesce(spcacl,pg_catalog.acldefault('t',spcowner))) AS acl "
1144 "EXCEPT SELECT pg_catalog.unnest(pg_catalog.acldefault('t',spcowner))) as foo)"
1146 "(SELECT pg_catalog.array_agg(acl) FROM (SELECT pg_catalog.unnest(pg_catalog.acldefault('t',spcowner)) AS acl "
1147 "EXCEPT SELECT pg_catalog.unnest(coalesce(spcacl,pg_catalog.acldefault('t',spcowner)))) as foo)"
1149 "array_to_string(spcoptions, ', '),"
1150 "pg_catalog.shobj_description(oid, 'pg_tablespace') "
1151 "FROM pg_catalog.pg_tablespace "
1152 "WHERE spcname !~ '^pg_' "
1154 else if (server_version >= 90200)
1155 res = executeQuery(conn, "SELECT oid, spcname, "
1156 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
1157 "pg_catalog.pg_tablespace_location(oid), "
1158 "spcacl, '' as rspcacl, "
1159 "array_to_string(spcoptions, ', '),"
1160 "pg_catalog.shobj_description(oid, 'pg_tablespace') "
1161 "FROM pg_catalog.pg_tablespace "
1162 "WHERE spcname !~ '^pg_' "
1164 else if (server_version >= 90000)
1165 res = executeQuery(conn, "SELECT oid, spcname, "
1166 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
1167 "spclocation, spcacl, '' as rspcacl, "
1168 "array_to_string(spcoptions, ', '),"
1169 "pg_catalog.shobj_description(oid, 'pg_tablespace') "
1170 "FROM pg_catalog.pg_tablespace "
1171 "WHERE spcname !~ '^pg_' "
1173 else if (server_version >= 80200)
1174 res = executeQuery(conn, "SELECT oid, spcname, "
1175 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
1176 "spclocation, spcacl, '' as rspcacl, null, "
1177 "pg_catalog.shobj_description(oid, 'pg_tablespace') "
1178 "FROM pg_catalog.pg_tablespace "
1179 "WHERE spcname !~ '^pg_' "
1182 res = executeQuery(conn, "SELECT oid, spcname, "
1183 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
1184 "spclocation, spcacl, '' as rspcacl, "
1186 "FROM pg_catalog.pg_tablespace "
1187 "WHERE spcname !~ '^pg_' "
1190 if (PQntuples(res) > 0)
1191 fprintf(OPF, "--\n-- Tablespaces\n--\n\n");
1193 for (i = 0; i < PQntuples(res); i++)
1195 PQExpBuffer buf = createPQExpBuffer();
1196 Oid spcoid = atooid(PQgetvalue(res, i, 0));
1197 char *spcname = PQgetvalue(res, i, 1);
1198 char *spcowner = PQgetvalue(res, i, 2);
1199 char *spclocation = PQgetvalue(res, i, 3);
1200 char *spcacl = PQgetvalue(res, i, 4);
1201 char *rspcacl = PQgetvalue(res, i, 5);
1202 char *spcoptions = PQgetvalue(res, i, 6);
1203 char *spccomment = PQgetvalue(res, i, 7);
1206 /* needed for buildACLCommands() */
1207 fspcname = pg_strdup(fmtId(spcname));
1209 appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname);
1210 appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
1212 appendPQExpBufferStr(buf, " LOCATION ");
1213 appendStringLiteralConn(buf, spclocation, conn);
1214 appendPQExpBufferStr(buf, ";\n");
1216 if (spcoptions && spcoptions[0] != '\0')
1217 appendPQExpBuffer(buf, "ALTER TABLESPACE %s SET (%s);\n",
1218 fspcname, spcoptions);
1221 !buildACLCommands(fspcname, NULL, NULL, "TABLESPACE",
1223 spcowner, "", server_version, buf))
1225 fprintf(stderr, _("%s: could not parse ACL list (%s) for tablespace \"%s\"\n"),
1226 progname, spcacl, spcname);
1231 if (!no_comments && spccomment && spccomment[0] != '\0')
1233 appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
1234 appendStringLiteralConn(buf, spccomment, conn);
1235 appendPQExpBufferStr(buf, ";\n");
1238 if (!no_security_labels && server_version >= 90200)
1239 buildShSecLabels(conn, "pg_tablespace", spcoid,
1240 "TABLESPACE", spcname,
1243 fprintf(OPF, "%s", buf->data);
1246 destroyPQExpBuffer(buf);
1250 fprintf(OPF, "\n\n");
1255 * Dump commands to drop each database.
1258 dropDBs(PGconn *conn)
1264 * Skip databases marked not datallowconn, since we'd be unable to connect
1265 * to them anyway. This must agree with dumpDatabases().
1267 res = executeQuery(conn,
1269 "FROM pg_database d "
1270 "WHERE datallowconn "
1271 "ORDER BY datname");
1273 if (PQntuples(res) > 0)
1274 fprintf(OPF, "--\n-- Drop databases (except postgres and template1)\n--\n\n");
1276 for (i = 0; i < PQntuples(res); i++)
1278 char *dbname = PQgetvalue(res, i, 0);
1281 * Skip "postgres" and "template1"; dumpDatabases() will deal with
1282 * them specially. Also, be sure to skip "template0", even if for
1283 * some reason it's not marked !datallowconn.
1285 if (strcmp(dbname, "template1") != 0 &&
1286 strcmp(dbname, "template0") != 0 &&
1287 strcmp(dbname, "postgres") != 0)
1289 fprintf(OPF, "DROP DATABASE %s%s;\n",
1290 if_exists ? "IF EXISTS " : "",
1297 fprintf(OPF, "\n\n");
1302 * Dump user-specific configuration
1305 dumpUserConfig(PGconn *conn, const char *username)
1307 PQExpBuffer buf = createPQExpBuffer();
1314 if (server_version >= 90000)
1315 printfPQExpBuffer(buf, "SELECT setconfig[%d] FROM pg_db_role_setting WHERE "
1316 "setdatabase = 0 AND setrole = "
1317 "(SELECT oid FROM %s WHERE rolname = ", count, role_catalog);
1318 else if (server_version >= 80100)
1319 printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM %s WHERE rolname = ", count, role_catalog);
1321 printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
1322 appendStringLiteralConn(buf, username, conn);
1323 if (server_version >= 90000)
1324 appendPQExpBufferChar(buf, ')');
1326 res = executeQuery(conn, buf->data);
1327 if (PQntuples(res) == 1 &&
1328 !PQgetisnull(res, 0, 0))
1330 resetPQExpBuffer(buf);
1331 makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
1332 "ROLE", username, NULL, NULL,
1334 fprintf(OPF, "%s", buf->data);
1345 destroyPQExpBuffer(buf);
1350 * Dump contents of databases.
1353 dumpDatabases(PGconn *conn)
1359 * Skip databases marked not datallowconn, since we'd be unable to connect
1360 * to them anyway. This must agree with dropDBs().
1362 * We arrange for template1 to be processed first, then we process other
1363 * DBs in alphabetical order. If we just did them all alphabetically, we
1364 * might find ourselves trying to drop the "postgres" database while still
1365 * connected to it. This makes trying to run the restore script while
1366 * connected to "template1" a bad idea, but there's no fixed order that
1367 * doesn't have some failure mode with --clean.
1369 res = executeQuery(conn,
1371 "FROM pg_database d "
1372 "WHERE datallowconn "
1373 "ORDER BY (datname <> 'template1'), datname");
1375 for (i = 0; i < PQntuples(res); i++)
1377 char *dbname = PQgetvalue(res, i, 0);
1378 const char *create_opts;
1381 /* Skip template0, even if it's not marked !datallowconn. */
1382 if (strcmp(dbname, "template0") == 0)
1386 fprintf(stderr, _("%s: dumping database \"%s\"...\n"), progname, dbname);
1389 * We assume that "template1" and "postgres" already exist in the
1390 * target installation. dropDBs() won't have removed them, for fear
1391 * of removing the DB the restore script is initially connected to. If
1392 * --clean was specified, tell pg_dump to drop and recreate them;
1393 * otherwise we'll merely restore their contents. Other databases
1394 * should simply be created.
1396 if (strcmp(dbname, "template1") == 0 || strcmp(dbname, "postgres") == 0)
1399 create_opts = "--clean --create";
1403 /* Since pg_dump won't emit a \connect command, we must */
1404 fprintf(OPF, "\\connect %s\n\n", dbname);
1408 create_opts = "--create";
1413 ret = runPgDump(dbname, create_opts);
1416 fprintf(stderr, _("%s: pg_dump failed on database \"%s\", exiting\n"), progname, dbname);
1422 OPF = fopen(filename, PG_BINARY_A);
1425 fprintf(stderr, _("%s: could not re-open the output file \"%s\": %s\n"),
1426 progname, filename, strerror(errno));
1439 * Run pg_dump on dbname, with specified options.
1442 runPgDump(const char *dbname, const char *create_opts)
1444 PQExpBuffer connstrbuf = createPQExpBuffer();
1445 PQExpBuffer cmd = createPQExpBuffer();
1448 appendPQExpBuffer(cmd, "\"%s\" %s %s", pg_dump_bin,
1449 pgdumpopts->data, create_opts);
1452 * If we have a filename, use the undocumented plain-append pg_dump
1456 appendPQExpBufferStr(cmd, " -Fa ");
1458 appendPQExpBufferStr(cmd, " -Fp ");
1461 * Append the database name to the already-constructed stem of connection
1464 appendPQExpBuffer(connstrbuf, "%s dbname=", connstr);
1465 appendConnStrVal(connstrbuf, dbname);
1467 appendShellString(cmd, connstrbuf->data);
1470 fprintf(stderr, _("%s: running \"%s\"\n"), progname, cmd->data);
1475 ret = system(cmd->data);
1477 destroyPQExpBuffer(cmd);
1478 destroyPQExpBuffer(connstrbuf);
1486 * Build SECURITY LABEL command(s) for a shared object
1488 * The caller has to provide object type and identity in two separate formats:
1489 * catalog_name (e.g., "pg_database") and object OID, as well as
1490 * type name (e.g., "DATABASE") and object name (not pre-quoted).
1492 * The command(s) are appended to "buffer".
1495 buildShSecLabels(PGconn *conn, const char *catalog_name, Oid objectId,
1496 const char *objtype, const char *objname,
1499 PQExpBuffer sql = createPQExpBuffer();
1502 buildShSecLabelQuery(conn, catalog_name, objectId, sql);
1503 res = executeQuery(conn, sql->data);
1504 emitShSecLabels(conn, res, buffer, objtype, objname);
1507 destroyPQExpBuffer(sql);
1511 * Make a database connection with the given parameters. An
1512 * interactive password prompt is automatically issued if required.
1514 * If fail_on_error is false, we return NULL without printing any message
1515 * on failure, but preserve any prompted password for the next try.
1517 * On success, the global variable 'connstr' is set to a connection string
1518 * containing the options used.
1521 connectDatabase(const char *dbname, const char *connection_string,
1522 const char *pghost, const char *pgport, const char *pguser,
1523 trivalue prompt_password, bool fail_on_error)
1527 const char *remoteversion_str;
1529 const char **keywords = NULL;
1530 const char **values = NULL;
1531 PQconninfoOption *conn_opts = NULL;
1532 static bool have_password = false;
1533 static char password[100];
1535 if (prompt_password == TRI_YES && !have_password)
1537 simple_prompt("Password: ", password, sizeof(password), false);
1538 have_password = true;
1542 * Start the connection. Loop until we have a password if requested by
1548 PQconninfoOption *conn_opt;
1549 char *err_msg = NULL;
1557 PQconninfoFree(conn_opts);
1560 * Merge the connection info inputs given in form of connection string
1561 * and other options. Explicitly discard any dbname value in the
1562 * connection string; otherwise, PQconnectdbParams() would interpret
1563 * that value as being itself a connection string.
1565 if (connection_string)
1567 conn_opts = PQconninfoParse(connection_string, &err_msg);
1568 if (conn_opts == NULL)
1570 fprintf(stderr, "%s: %s", progname, err_msg);
1574 for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
1576 if (conn_opt->val != NULL && conn_opt->val[0] != '\0' &&
1577 strcmp(conn_opt->keyword, "dbname") != 0)
1581 keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
1582 values = pg_malloc0((argcount + 1) * sizeof(*values));
1584 for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
1586 if (conn_opt->val != NULL && conn_opt->val[0] != '\0' &&
1587 strcmp(conn_opt->keyword, "dbname") != 0)
1589 keywords[i] = conn_opt->keyword;
1590 values[i] = conn_opt->val;
1597 keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
1598 values = pg_malloc0((argcount + 1) * sizeof(*values));
1603 keywords[i] = "host";
1609 keywords[i] = "port";
1615 keywords[i] = "user";
1621 keywords[i] = "password";
1622 values[i] = password;
1627 keywords[i] = "dbname";
1631 keywords[i] = "fallback_application_name";
1632 values[i] = progname;
1636 conn = PQconnectdbParams(keywords, values, true);
1640 fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
1645 if (PQstatus(conn) == CONNECTION_BAD &&
1646 PQconnectionNeedsPassword(conn) &&
1648 prompt_password != TRI_NO)
1651 simple_prompt("Password: ", password, sizeof(password), false);
1652 have_password = true;
1657 /* check to see that the backend connection was successfully made */
1658 if (PQstatus(conn) == CONNECTION_BAD)
1663 _("%s: could not connect to database \"%s\": %s\n"),
1664 progname, dbname, PQerrorMessage(conn));
1673 PQconninfoFree(conn_opts);
1680 * Ok, connected successfully. Remember the options used, in the form of a
1681 * connection string.
1683 connstr = constructConnStr(keywords, values);
1687 PQconninfoFree(conn_opts);
1690 remoteversion_str = PQparameterStatus(conn, "server_version");
1691 if (!remoteversion_str)
1693 fprintf(stderr, _("%s: could not get server version\n"), progname);
1696 server_version = PQserverVersion(conn);
1697 if (server_version == 0)
1699 fprintf(stderr, _("%s: could not parse server version \"%s\"\n"),
1700 progname, remoteversion_str);
1704 my_version = PG_VERSION_NUM;
1707 * We allow the server to be back to 8.0, and up to any minor release of
1708 * our own major version. (See also version check in pg_dump.c.)
1710 if (my_version != server_version
1711 && (server_version < 80000 ||
1712 (server_version / 100) > (my_version / 100)))
1714 fprintf(stderr, _("server version: %s; %s version: %s\n"),
1715 remoteversion_str, progname, PG_VERSION);
1716 fprintf(stderr, _("aborting because of server version mismatch\n"));
1721 * Make sure we are not fooled by non-system schemas in the search path.
1723 executeCommand(conn, "SET search_path = pg_catalog");
1729 * Construct a connection string from the given keyword/value pairs. It is
1730 * used to pass the connection options to the pg_dump subprocess.
1732 * The following parameters are excluded:
1733 * dbname - varies in each pg_dump invocation
1734 * password - it's not secure to pass a password on the command line
1735 * fallback_application_name - we'll let pg_dump set it
1739 constructConnStr(const char **keywords, const char **values)
1741 PQExpBuffer buf = createPQExpBuffer();
1744 bool firstkeyword = true;
1746 /* Construct a new connection string in key='value' format. */
1747 for (i = 0; keywords[i] != NULL; i++)
1749 if (strcmp(keywords[i], "dbname") == 0 ||
1750 strcmp(keywords[i], "password") == 0 ||
1751 strcmp(keywords[i], "fallback_application_name") == 0)
1755 appendPQExpBufferChar(buf, ' ');
1756 firstkeyword = false;
1757 appendPQExpBuffer(buf, "%s=", keywords[i]);
1758 appendConnStrVal(buf, values[i]);
1761 connstr = pg_strdup(buf->data);
1762 destroyPQExpBuffer(buf);
1767 * Run a query, return the results, exit program on failure.
1770 executeQuery(PGconn *conn, const char *query)
1775 fprintf(stderr, _("%s: executing %s\n"), progname, query);
1777 res = PQexec(conn, query);
1779 PQresultStatus(res) != PGRES_TUPLES_OK)
1781 fprintf(stderr, _("%s: query failed: %s"),
1782 progname, PQerrorMessage(conn));
1783 fprintf(stderr, _("%s: query was: %s\n"),
1793 * As above for a SQL command (which returns nothing).
1796 executeCommand(PGconn *conn, const char *query)
1801 fprintf(stderr, _("%s: executing %s\n"), progname, query);
1803 res = PQexec(conn, query);
1805 PQresultStatus(res) != PGRES_COMMAND_OK)
1807 fprintf(stderr, _("%s: query failed: %s"),
1808 progname, PQerrorMessage(conn));
1809 fprintf(stderr, _("%s: query was: %s\n"),
1823 dumpTimestamp(const char *msg)
1826 time_t now = time(NULL);
1828 if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&now)) != 0)
1829 fprintf(OPF, "-- %s %s\n\n", msg, buf);