1 /*-------------------------------------------------------------------------
5 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
11 *-------------------------------------------------------------------------
14 #include "postgres_fe.h"
23 #include "getopt_long.h"
25 #ifndef HAVE_INT_OPTRESET
29 #include "dumputils.h"
30 #include "pg_backup.h"
32 /* version string we expect back from pg_dump */
33 #define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
36 static const char *progname
;
38 static void help(void);
40 static void dumpRoles(PGconn
*conn
);
41 static void dumpRoleMembership(PGconn
*conn
);
42 static void dumpGroups(PGconn
*conn
);
43 static void dumpTablespaces(PGconn
*conn
);
44 static void dumpCreateDB(PGconn
*conn
);
45 static void dumpDatabaseConfig(PGconn
*conn
, const char *dbname
);
46 static void dumpUserConfig(PGconn
*conn
, const char *username
);
47 static void makeAlterConfigCommand(PGconn
*conn
, const char *arrayitem
,
48 const char *type
, const char *name
);
49 static void dumpDatabases(PGconn
*conn
);
50 static void dumpTimestamp(char *msg
);
51 static void doShellQuoting(PQExpBuffer buf
, const char *str
);
53 static int runPgDump(const char *dbname
);
54 static PGconn
*connectDatabase(const char *dbname
, const char *pghost
, const char *pgport
,
55 const char *pguser
, enum trivalue prompt_password
, bool fail_on_error
);
56 static PGresult
*executeQuery(PGconn
*conn
, const char *query
);
57 static void executeCommand(PGconn
*conn
, const char *query
);
59 static char pg_dump_bin
[MAXPGPATH
];
60 static PQExpBuffer pgdumpopts
;
61 static bool output_clean
= false;
62 static bool skip_acls
= false;
63 static bool verbose
= false;
65 static int disable_dollar_quoting
= 0;
66 static int disable_triggers
= 0;
67 static int no_tablespaces
= 0;
68 static int use_setsessauth
= 0;
69 static int server_version
;
72 static char *filename
= NULL
;
74 static int binary_upgrade
= 0;
77 main(int argc
, char *argv
[])
83 char *use_role
= NULL
;
84 enum trivalue prompt_password
= TRI_DEFAULT
;
85 bool data_only
= false;
86 bool globals_only
= false;
87 bool roles_only
= false;
88 bool tablespaces_only
= false;
89 bool schema_only
= false;
92 const char *std_strings
;
96 struct option long_options
[] = {
97 {"binary-upgrade", no_argument
, &binary_upgrade
, 1}, /* not documented */
98 {"data-only", no_argument
, NULL
, 'a'},
99 {"clean", no_argument
, NULL
, 'c'},
100 {"inserts", no_argument
, NULL
, 'd'},
101 {"attribute-inserts", no_argument
, NULL
, 'D'},
102 {"column-inserts", no_argument
, NULL
, 'D'},
103 {"file", required_argument
, NULL
, 'f'},
104 {"globals-only", no_argument
, NULL
, 'g'},
105 {"host", required_argument
, NULL
, 'h'},
106 {"ignore-version", no_argument
, NULL
, 'i'},
107 {"database", required_argument
, NULL
, 'l'},
108 {"oids", no_argument
, NULL
, 'o'},
109 {"no-owner", no_argument
, NULL
, 'O'},
110 {"port", required_argument
, NULL
, 'p'},
111 {"roles-only", no_argument
, NULL
, 'r'},
112 {"schema-only", no_argument
, NULL
, 's'},
113 {"superuser", required_argument
, NULL
, 'S'},
114 {"tablespaces-only", no_argument
, NULL
, 't'},
115 {"username", required_argument
, NULL
, 'U'},
116 {"verbose", no_argument
, NULL
, 'v'},
117 {"no-password", no_argument
, NULL
, 'w'},
118 {"password", no_argument
, NULL
, 'W'},
119 {"no-privileges", no_argument
, NULL
, 'x'},
120 {"no-acl", no_argument
, NULL
, 'x'},
123 * the following options don't have an equivalent short option letter
125 {"disable-dollar-quoting", no_argument
, &disable_dollar_quoting
, 1},
126 {"disable-triggers", no_argument
, &disable_triggers
, 1},
127 {"lock-wait-timeout", required_argument
, NULL
, 2},
128 {"no-tablespaces", no_argument
, &no_tablespaces
, 1},
129 {"role", required_argument
, NULL
, 3},
130 {"use-set-session-authorization", no_argument
, &use_setsessauth
, 1},
137 set_pglocale_pgservice(argv
[0], PG_TEXTDOMAIN("pg_dump"));
139 progname
= get_progname(argv
[0]);
143 if (strcmp(argv
[1], "--help") == 0 || strcmp(argv
[1], "-?") == 0)
148 if (strcmp(argv
[1], "--version") == 0 || strcmp(argv
[1], "-V") == 0)
150 puts("pg_dumpall (PostgreSQL) " PG_VERSION
);
155 if ((ret
= find_other_exec(argv
[0], "pg_dump", PGDUMP_VERSIONSTR
,
158 char full_path
[MAXPGPATH
];
160 if (find_my_exec(argv
[0], full_path
) < 0)
161 strlcpy(full_path
, progname
, sizeof(full_path
));
165 _("The program \"pg_dump\" is needed by %s "
166 "but was not found in the\n"
167 "same directory as \"%s\".\n"
168 "Check your installation.\n"),
169 progname
, full_path
);
172 _("The program \"pg_dump\" was found by \"%s\"\n"
173 "but was not the same version as %s.\n"
174 "Check your installation.\n"),
175 full_path
, progname
);
179 pgdumpopts
= createPQExpBuffer();
181 while ((c
= getopt_long(argc
, argv
, "acdDf:gh:il:oOp:rsS:tU:vwWxX:", long_options
, &optindex
)) != -1)
187 appendPQExpBuffer(pgdumpopts
, " -a");
196 appendPQExpBuffer(pgdumpopts
, " -%c", c
);
201 appendPQExpBuffer(pgdumpopts
, " -f ");
202 doShellQuoting(pgdumpopts
, filename
);
211 appendPQExpBuffer(pgdumpopts
, " -h ");
212 doShellQuoting(pgdumpopts
, pghost
);
216 /* ignored, deprecated option */
224 appendPQExpBuffer(pgdumpopts
, " -o");
228 appendPQExpBuffer(pgdumpopts
, " -O");
233 appendPQExpBuffer(pgdumpopts
, " -p ");
234 doShellQuoting(pgdumpopts
, pgport
);
243 appendPQExpBuffer(pgdumpopts
, " -s");
247 appendPQExpBuffer(pgdumpopts
, " -S ");
248 doShellQuoting(pgdumpopts
, optarg
);
252 tablespaces_only
= true;
257 appendPQExpBuffer(pgdumpopts
, " -U ");
258 doShellQuoting(pgdumpopts
, pguser
);
263 appendPQExpBuffer(pgdumpopts
, " -v");
267 prompt_password
= TRI_NO
;
268 appendPQExpBuffer(pgdumpopts
, " -w");
272 prompt_password
= TRI_YES
;
273 appendPQExpBuffer(pgdumpopts
, " -W");
278 appendPQExpBuffer(pgdumpopts
, " -x");
282 /* -X is a deprecated alternative to long options */
283 if (strcmp(optarg
, "disable-dollar-quoting") == 0)
284 disable_dollar_quoting
= 1;
285 else if (strcmp(optarg
, "disable-triggers") == 0)
286 disable_triggers
= 1;
287 else if (strcmp(optarg
, "no-tablespaces") == 0)
289 else if (strcmp(optarg
, "use-set-session-authorization") == 0)
294 _("%s: invalid -X option -- %s\n"),
296 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), progname
);
305 appendPQExpBuffer(pgdumpopts
, " --lock-wait-timeout ");
306 doShellQuoting(pgdumpopts
, optarg
);
311 appendPQExpBuffer(pgdumpopts
, " --role ");
312 doShellQuoting(pgdumpopts
, use_role
);
316 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"), progname
);
321 /* Add long options to the pg_dump argument list */
323 appendPQExpBuffer(pgdumpopts
, " --binary-upgrade");
324 if (disable_dollar_quoting
)
325 appendPQExpBuffer(pgdumpopts
, " --disable-dollar-quoting");
326 if (disable_triggers
)
327 appendPQExpBuffer(pgdumpopts
, " --disable-triggers");
329 appendPQExpBuffer(pgdumpopts
, " --no-tablespaces");
331 appendPQExpBuffer(pgdumpopts
, " --use-set-session-authorization");
335 fprintf(stderr
, _("%s: too many command-line arguments (first is \"%s\")\n"),
336 progname
, argv
[optind
]);
337 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
342 /* Make sure the user hasn't specified a mix of globals-only options */
343 if (globals_only
&& roles_only
)
345 fprintf(stderr
, _("%s: options -g/--globals-only and -r/--roles-only cannot be used together\n"),
347 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
352 if (globals_only
&& tablespaces_only
)
354 fprintf(stderr
, _("%s: options -g/--globals-only and -t/--tablespaces-only cannot be used together\n"),
356 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
361 if (roles_only
&& tablespaces_only
)
363 fprintf(stderr
, _("%s: options -r/--roles-only and -t/--tablespaces-only cannot be used together\n"),
365 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
371 * If there was a database specified on the command line, use that,
372 * otherwise try to connect to database "postgres", and failing that
373 * "template1". "postgres" is the preferred choice for 8.1 and later
374 * servers, but it usually will not exist on older ones.
378 conn
= connectDatabase(pgdb
, pghost
, pgport
, pguser
,
379 prompt_password
, false);
383 fprintf(stderr
, _("%s: could not connect to database \"%s\"\n"),
390 conn
= connectDatabase("postgres", pghost
, pgport
, pguser
,
391 prompt_password
, false);
393 conn
= connectDatabase("template1", pghost
, pgport
, pguser
,
394 prompt_password
, true);
398 fprintf(stderr
, _("%s: could not connect to databases \"postgres\" or \"template1\"\n"
399 "Please specify an alternative database.\n"),
401 fprintf(stderr
, _("Try \"%s --help\" for more information.\n"),
408 * Open the output file if required, otherwise use stdout
412 OPF
= fopen(filename
, PG_BINARY_W
);
415 fprintf(stderr
, _("%s: could not open the output file \"%s\": %s\n"),
416 progname
, filename
, strerror(errno
));
424 * Get the active encoding and the standard_conforming_strings setting, so
425 * we know how to escape strings.
427 encoding
= PQclientEncoding(conn
);
428 std_strings
= PQparameterStatus(conn
, "standard_conforming_strings");
432 /* Set the role if requested */
433 if (use_role
&& server_version
>= 80100)
435 PQExpBuffer query
= createPQExpBuffer();
437 appendPQExpBuffer(query
, "SET ROLE %s", fmtId(use_role
));
438 executeCommand(conn
, query
->data
);
439 destroyPQExpBuffer(query
);
442 fprintf(OPF
, "--\n-- PostgreSQL database cluster dump\n--\n\n");
444 dumpTimestamp("Started on");
446 fprintf(OPF
, "\\connect postgres\n\n");
450 /* Replicate encoding and std_strings in output */
451 fprintf(OPF
, "SET client_encoding = '%s';\n",
452 pg_encoding_to_char(encoding
));
453 fprintf(OPF
, "SET standard_conforming_strings = %s;\n", std_strings
);
454 if (strcmp(std_strings
, "off") == 0)
455 fprintf(OPF
, "SET escape_string_warning = 'off';\n");
458 if (!tablespaces_only
)
460 /* Dump roles (users) */
463 /* Dump role memberships --- need different method for pre-8.1 */
464 if (server_version
>= 80100)
465 dumpRoleMembership(conn
);
470 if (!roles_only
&& !no_tablespaces
)
472 /* Dump tablespaces */
473 if (server_version
>= 80000)
474 dumpTablespaces(conn
);
477 /* Dump CREATE DATABASE commands */
478 if (!globals_only
&& !roles_only
&& !tablespaces_only
)
482 if (!globals_only
&& !roles_only
&& !tablespaces_only
)
488 dumpTimestamp("Completed on");
489 fprintf(OPF
, "--\n-- PostgreSQL database cluster dump complete\n--\n\n");
502 printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname
);
503 printf(_("Usage:\n"));
504 printf(_(" %s [OPTION]...\n"), progname
);
506 printf(_("\nGeneral options:\n"));
507 printf(_(" -f, --file=FILENAME output file name\n"));
508 printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
509 printf(_(" --help show this help, then exit\n"));
510 printf(_(" --version output version information, then exit\n"));
511 printf(_("\nOptions controlling the output content:\n"));
512 printf(_(" -a, --data-only dump only the data, not the schema\n"));
513 printf(_(" -c, --clean clean (drop) databases before recreating\n"));
514 printf(_(" -d, --inserts dump data as INSERT commands, rather than COPY\n"));
515 printf(_(" -D, --column-inserts dump data as INSERT commands with column names\n"));
516 printf(_(" -g, --globals-only dump only global objects, no databases\n"));
517 printf(_(" -o, --oids include OIDs in dump\n"));
518 printf(_(" -O, --no-owner skip restoration of object ownership\n"));
519 printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n"));
520 printf(_(" -s, --schema-only dump only the schema, no data\n"));
521 printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n"));
522 printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n"));
523 printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
524 printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
525 printf(_(" --disable-triggers disable triggers during data-only restore\n"));
526 printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
527 printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
528 printf(_(" --use-set-session-authorization\n"
529 " use SET SESSION AUTHORIZATION commands instead of\n"
530 " ALTER OWNER commands to set ownership\n"));
532 printf(_("\nConnection options:\n"));
533 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
534 printf(_(" -l, --database=DBNAME alternative default database\n"));
535 printf(_(" -p, --port=PORT database server port number\n"));
536 printf(_(" -U, --username=NAME connect as specified database user\n"));
537 printf(_(" -w, --no-password never prompt for password\n"));
538 printf(_(" -W, --password force password prompt (should happen automatically)\n"));
540 printf(_("\nIf -f/--file is not used, then the SQL script will be written to the standard\n"
542 printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
551 dumpRoles(PGconn
*conn
)
553 PQExpBuffer buf
= createPQExpBuffer();
568 /* note: rolconfig is dumped later */
569 if (server_version
>= 80200)
570 printfPQExpBuffer(buf
,
571 "SELECT rolname, rolsuper, rolinherit, "
572 "rolcreaterole, rolcreatedb, rolcatupdate, "
573 "rolcanlogin, rolconnlimit, rolpassword, "
575 "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment "
578 else if (server_version
>= 80100)
579 printfPQExpBuffer(buf
,
580 "SELECT rolname, rolsuper, rolinherit, "
581 "rolcreaterole, rolcreatedb, rolcatupdate, "
582 "rolcanlogin, rolconnlimit, rolpassword, "
583 "rolvaliduntil, null as rolcomment "
587 printfPQExpBuffer(buf
,
588 "SELECT usename as rolname, "
589 "usesuper as rolsuper, "
590 "true as rolinherit, "
591 "usesuper as rolcreaterole, "
592 "usecreatedb as rolcreatedb, "
593 "usecatupd as rolcatupdate, "
594 "true as rolcanlogin, "
595 "-1 as rolconnlimit, "
596 "passwd as rolpassword, "
597 "valuntil as rolvaliduntil, "
598 "null as rolcomment "
601 "SELECT groname as rolname, "
602 "false as rolsuper, "
603 "true as rolinherit, "
604 "false as rolcreaterole, "
605 "false as rolcreatedb, "
606 "false as rolcatupdate, "
607 "false as rolcanlogin, "
608 "-1 as rolconnlimit, "
609 "null::text as rolpassword, "
610 "null::abstime as rolvaliduntil, "
611 "null as rolcomment "
613 "WHERE NOT EXISTS (SELECT 1 FROM pg_shadow "
614 " WHERE usename = groname) "
617 res
= executeQuery(conn
, buf
->data
);
619 i_rolname
= PQfnumber(res
, "rolname");
620 i_rolsuper
= PQfnumber(res
, "rolsuper");
621 i_rolinherit
= PQfnumber(res
, "rolinherit");
622 i_rolcreaterole
= PQfnumber(res
, "rolcreaterole");
623 i_rolcreatedb
= PQfnumber(res
, "rolcreatedb");
624 i_rolcatupdate
= PQfnumber(res
, "rolcatupdate");
625 i_rolcanlogin
= PQfnumber(res
, "rolcanlogin");
626 i_rolconnlimit
= PQfnumber(res
, "rolconnlimit");
627 i_rolpassword
= PQfnumber(res
, "rolpassword");
628 i_rolvaliduntil
= PQfnumber(res
, "rolvaliduntil");
629 i_rolcomment
= PQfnumber(res
, "rolcomment");
631 if (PQntuples(res
) > 0)
632 fprintf(OPF
, "--\n-- Roles\n--\n\n");
634 for (i
= 0; i
< PQntuples(res
); i
++)
636 const char *rolename
;
638 rolename
= PQgetvalue(res
, i
, i_rolname
);
640 resetPQExpBuffer(buf
);
643 appendPQExpBuffer(buf
, "DROP ROLE %s;\n", fmtId(rolename
));
646 * We dump CREATE ROLE followed by ALTER ROLE to ensure that the role
647 * will acquire the right properties even if it already exists. (The
648 * above DROP may therefore seem redundant, but it isn't really,
649 * because this technique doesn't get rid of role memberships.)
651 appendPQExpBuffer(buf
, "CREATE ROLE %s;\n", fmtId(rolename
));
652 appendPQExpBuffer(buf
, "ALTER ROLE %s WITH", fmtId(rolename
));
654 if (strcmp(PQgetvalue(res
, i
, i_rolsuper
), "t") == 0)
655 appendPQExpBuffer(buf
, " SUPERUSER");
657 appendPQExpBuffer(buf
, " NOSUPERUSER");
659 if (strcmp(PQgetvalue(res
, i
, i_rolinherit
), "t") == 0)
660 appendPQExpBuffer(buf
, " INHERIT");
662 appendPQExpBuffer(buf
, " NOINHERIT");
664 if (strcmp(PQgetvalue(res
, i
, i_rolcreaterole
), "t") == 0)
665 appendPQExpBuffer(buf
, " CREATEROLE");
667 appendPQExpBuffer(buf
, " NOCREATEROLE");
669 if (strcmp(PQgetvalue(res
, i
, i_rolcreatedb
), "t") == 0)
670 appendPQExpBuffer(buf
, " CREATEDB");
672 appendPQExpBuffer(buf
, " NOCREATEDB");
674 if (strcmp(PQgetvalue(res
, i
, i_rolcanlogin
), "t") == 0)
675 appendPQExpBuffer(buf
, " LOGIN");
677 appendPQExpBuffer(buf
, " NOLOGIN");
679 if (strcmp(PQgetvalue(res
, i
, i_rolconnlimit
), "-1") != 0)
680 appendPQExpBuffer(buf
, " CONNECTION LIMIT %s",
681 PQgetvalue(res
, i
, i_rolconnlimit
));
683 if (!PQgetisnull(res
, i
, i_rolpassword
))
685 appendPQExpBuffer(buf
, " PASSWORD ");
686 appendStringLiteralConn(buf
, PQgetvalue(res
, i
, i_rolpassword
), conn
);
689 if (!PQgetisnull(res
, i
, i_rolvaliduntil
))
690 appendPQExpBuffer(buf
, " VALID UNTIL '%s'",
691 PQgetvalue(res
, i
, i_rolvaliduntil
));
693 appendPQExpBuffer(buf
, ";\n");
695 if (!PQgetisnull(res
, i
, i_rolcomment
))
697 appendPQExpBuffer(buf
, "COMMENT ON ROLE %s IS ", fmtId(rolename
));
698 appendStringLiteralConn(buf
, PQgetvalue(res
, i
, i_rolcomment
), conn
);
699 appendPQExpBuffer(buf
, ";\n");
702 fprintf(OPF
, "%s", buf
->data
);
704 if (server_version
>= 70300)
705 dumpUserConfig(conn
, rolename
);
710 fprintf(OPF
, "\n\n");
712 destroyPQExpBuffer(buf
);
717 * Dump role memberships. This code is used for 8.1 and later servers.
719 * Note: we expect dumpRoles already created all the roles, but there is
723 dumpRoleMembership(PGconn
*conn
)
728 res
= executeQuery(conn
, "SELECT ur.rolname AS roleid, "
729 "um.rolname AS member, "
731 "ug.rolname AS grantor "
732 "FROM pg_auth_members a "
733 "LEFT JOIN pg_authid ur on ur.oid = a.roleid "
734 "LEFT JOIN pg_authid um on um.oid = a.member "
735 "LEFT JOIN pg_authid ug on ug.oid = a.grantor "
738 if (PQntuples(res
) > 0)
739 fprintf(OPF
, "--\n-- Role memberships\n--\n\n");
741 for (i
= 0; i
< PQntuples(res
); i
++)
743 char *roleid
= PQgetvalue(res
, i
, 0);
744 char *member
= PQgetvalue(res
, i
, 1);
745 char *option
= PQgetvalue(res
, i
, 2);
747 fprintf(OPF
, "GRANT %s", fmtId(roleid
));
748 fprintf(OPF
, " TO %s", fmtId(member
));
750 fprintf(OPF
, " WITH ADMIN OPTION");
753 * We don't track the grantor very carefully in the backend, so cope
754 * with the possibility that it has been dropped.
756 if (!PQgetisnull(res
, i
, 3))
758 char *grantor
= PQgetvalue(res
, i
, 3);
760 fprintf(OPF
, " GRANTED BY %s", fmtId(grantor
));
767 fprintf(OPF
, "\n\n");
771 * Dump group memberships from a pre-8.1 server. It's annoying that we
772 * can't share any useful amount of code with the post-8.1 case, but
773 * the catalog representations are too different.
775 * Note: we expect dumpRoles already created all the roles, but there is
779 dumpGroups(PGconn
*conn
)
781 PQExpBuffer buf
= createPQExpBuffer();
785 res
= executeQuery(conn
,
786 "SELECT groname, grolist FROM pg_group ORDER BY 1");
788 if (PQntuples(res
) > 0)
789 fprintf(OPF
, "--\n-- Role memberships\n--\n\n");
791 for (i
= 0; i
< PQntuples(res
); i
++)
793 char *groname
= PQgetvalue(res
, i
, 0);
794 char *grolist
= PQgetvalue(res
, i
, 1);
799 * Array representation is {1,2,3} ... convert to (1,2,3)
801 if (strlen(grolist
) < 3)
804 grolist
= strdup(grolist
);
806 grolist
[strlen(grolist
) - 1] = ')';
807 printfPQExpBuffer(buf
,
808 "SELECT usename FROM pg_shadow "
809 "WHERE usesysid IN %s ORDER BY 1",
813 res2
= executeQuery(conn
, buf
->data
);
815 for (j
= 0; j
< PQntuples(res2
); j
++)
817 char *usename
= PQgetvalue(res2
, j
, 0);
820 * Don't try to grant a role to itself; can happen if old
821 * installation has identically named user and group.
823 if (strcmp(groname
, usename
) == 0)
826 fprintf(OPF
, "GRANT %s", fmtId(groname
));
827 fprintf(OPF
, " TO %s;\n", fmtId(usename
));
834 destroyPQExpBuffer(buf
);
836 fprintf(OPF
, "\n\n");
843 dumpTablespaces(PGconn
*conn
)
849 * Get all tablespaces except built-in ones (which we assume are named
852 if (server_version
>= 80200)
853 res
= executeQuery(conn
, "SELECT spcname, "
854 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
855 "spclocation, spcacl, "
856 "pg_catalog.shobj_description(oid, 'pg_tablespace') "
857 "FROM pg_catalog.pg_tablespace "
858 "WHERE spcname !~ '^pg_' "
861 res
= executeQuery(conn
, "SELECT spcname, "
862 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
863 "spclocation, spcacl, "
865 "FROM pg_catalog.pg_tablespace "
866 "WHERE spcname !~ '^pg_' "
869 if (PQntuples(res
) > 0)
870 fprintf(OPF
, "--\n-- Tablespaces\n--\n\n");
872 for (i
= 0; i
< PQntuples(res
); i
++)
874 PQExpBuffer buf
= createPQExpBuffer();
875 char *spcname
= PQgetvalue(res
, i
, 0);
876 char *spcowner
= PQgetvalue(res
, i
, 1);
877 char *spclocation
= PQgetvalue(res
, i
, 2);
878 char *spcacl
= PQgetvalue(res
, i
, 3);
879 char *spccomment
= PQgetvalue(res
, i
, 4);
882 /* needed for buildACLCommands() */
883 fspcname
= strdup(fmtId(spcname
));
886 appendPQExpBuffer(buf
, "DROP TABLESPACE %s;\n", fspcname
);
888 appendPQExpBuffer(buf
, "CREATE TABLESPACE %s", fspcname
);
889 appendPQExpBuffer(buf
, " OWNER %s", fmtId(spcowner
));
891 appendPQExpBuffer(buf
, " LOCATION ");
892 appendStringLiteralConn(buf
, spclocation
, conn
);
893 appendPQExpBuffer(buf
, ";\n");
896 !buildACLCommands(fspcname
, NULL
, "TABLESPACE", spcacl
, spcowner
,
897 server_version
, buf
))
899 fprintf(stderr
, _("%s: could not parse ACL list (%s) for tablespace \"%s\"\n"),
900 progname
, spcacl
, fspcname
);
905 if (spccomment
&& strlen(spccomment
))
907 appendPQExpBuffer(buf
, "COMMENT ON TABLESPACE %s IS ", fspcname
);
908 appendStringLiteralConn(buf
, spccomment
, conn
);
909 appendPQExpBuffer(buf
, ";\n");
912 fprintf(OPF
, "%s", buf
->data
);
915 destroyPQExpBuffer(buf
);
919 fprintf(OPF
, "\n\n");
923 * Dump commands to create each database.
925 * To minimize the number of reconnections (and possibly ensuing
926 * password prompts) required by the output script, we emit all CREATE
927 * DATABASE commands during the initial phase of the script, and then
928 * run pg_dump for each database to dump the contents of that
929 * database. We skip databases marked not datallowconn, since we'd be
930 * unable to connect to them anyway (and besides, we don't want to
934 dumpCreateDB(PGconn
*conn
)
936 PQExpBuffer buf
= createPQExpBuffer();
940 fprintf(OPF
, "--\n-- Database creation\n--\n\n");
942 if (server_version
>= 80400)
943 res
= executeQuery(conn
,
945 "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
946 "pg_encoding_to_char(d.encoding), "
947 "datcollate, datctype, datfrozenxid, "
948 "datistemplate, datacl, datconnlimit, "
949 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
950 "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
951 "WHERE datallowconn ORDER BY 1");
952 else if (server_version
>= 80100)
953 res
= executeQuery(conn
,
955 "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
956 "pg_encoding_to_char(d.encoding), "
957 "null::text AS datcollate, null::text AS datctype, datfrozenxid, "
958 "datistemplate, datacl, datconnlimit, "
959 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
960 "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
961 "WHERE datallowconn ORDER BY 1");
962 else if (server_version
>= 80000)
963 res
= executeQuery(conn
,
965 "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
966 "pg_encoding_to_char(d.encoding), "
967 "null::text AS datcollate, null::text AS datctype, datfrozenxid, "
968 "datistemplate, datacl, -1 as datconnlimit, "
969 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
970 "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
971 "WHERE datallowconn ORDER BY 1");
972 else if (server_version
>= 70300)
973 res
= executeQuery(conn
,
975 "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
976 "pg_encoding_to_char(d.encoding), "
977 "null::text AS datcollate, null::text AS datctype, datfrozenxid, "
978 "datistemplate, datacl, -1 as datconnlimit, "
979 "'pg_default' AS dattablespace "
980 "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
981 "WHERE datallowconn ORDER BY 1");
982 else if (server_version
>= 70100)
983 res
= executeQuery(conn
,
986 "(select usename from pg_shadow where usesysid=datdba), "
987 "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
988 "pg_encoding_to_char(d.encoding), "
989 "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid"
990 "datistemplate, '' as datacl, -1 as datconnlimit, "
991 "'pg_default' AS dattablespace "
992 "FROM pg_database d "
993 "WHERE datallowconn ORDER BY 1");
997 * Note: 7.0 fails to cope with sub-select in COALESCE, so just deal
998 * with getting a NULL by not printing any OWNER clause.
1000 res
= executeQuery(conn
,
1002 "(select usename from pg_shadow where usesysid=datdba), "
1003 "pg_encoding_to_char(d.encoding), "
1004 "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid"
1005 "'f' as datistemplate, "
1006 "'' as datacl, -1 as datconnlimit, "
1007 "'pg_default' AS dattablespace "
1008 "FROM pg_database d "
1012 for (i
= 0; i
< PQntuples(res
); i
++)
1014 char *dbname
= PQgetvalue(res
, i
, 0);
1015 char *dbowner
= PQgetvalue(res
, i
, 1);
1016 char *dbencoding
= PQgetvalue(res
, i
, 2);
1017 char *dbcollate
= PQgetvalue(res
, i
, 3);
1018 char *dbctype
= PQgetvalue(res
, i
, 4);
1019 uint32 dbfrozenxid
= atooid(PQgetvalue(res
, i
, 5));
1020 char *dbistemplate
= PQgetvalue(res
, i
, 6);
1021 char *dbacl
= PQgetvalue(res
, i
, 7);
1022 char *dbconnlimit
= PQgetvalue(res
, i
, 8);
1023 char *dbtablespace
= PQgetvalue(res
, i
, 9);
1026 fdbname
= strdup(fmtId(dbname
));
1028 resetPQExpBuffer(buf
);
1031 * Skip the CREATE DATABASE commands for "template1" and "postgres",
1032 * since they are presumably already there in the destination cluster.
1033 * We do want to emit their ACLs and config options if any, however.
1035 if (strcmp(dbname
, "template1") != 0 &&
1036 strcmp(dbname
, "postgres") != 0)
1039 appendPQExpBuffer(buf
, "DROP DATABASE %s;\n", fdbname
);
1041 appendPQExpBuffer(buf
, "CREATE DATABASE %s", fdbname
);
1043 appendPQExpBuffer(buf
, " WITH TEMPLATE = template0");
1045 if (strlen(dbowner
) != 0)
1046 appendPQExpBuffer(buf
, " OWNER = %s", fmtId(dbowner
));
1048 appendPQExpBuffer(buf
, " ENCODING = ");
1049 appendStringLiteralConn(buf
, dbencoding
, conn
);
1051 if (strlen(dbcollate
) != 0)
1053 appendPQExpBuffer(buf
, " COLLATE = ");
1054 appendStringLiteralConn(buf
, dbcollate
, conn
);
1057 if (strlen(dbctype
) != 0)
1059 appendPQExpBuffer(buf
, " CTYPE = ");
1060 appendStringLiteralConn(buf
, dbctype
, conn
);
1064 * Output tablespace if it isn't the default. For default, it
1065 * uses the default from the template database. If tablespace is
1066 * specified and tablespace creation failed earlier, (e.g. no such
1067 * directory), the database creation will fail too. One solution
1068 * would be to use 'SET default_tablespace' like we do in pg_dump
1069 * for setting non-default database locations.
1071 if (strcmp(dbtablespace
, "pg_default") != 0 && !no_tablespaces
)
1072 appendPQExpBuffer(buf
, " TABLESPACE = %s",
1073 fmtId(dbtablespace
));
1075 if (strcmp(dbconnlimit
, "-1") != 0)
1076 appendPQExpBuffer(buf
, " CONNECTION LIMIT = %s",
1079 appendPQExpBuffer(buf
, ";\n");
1081 if (strcmp(dbistemplate
, "t") == 0)
1083 appendPQExpBuffer(buf
, "UPDATE pg_database SET datistemplate = 't' WHERE datname = ");
1084 appendStringLiteralConn(buf
, dbname
, conn
);
1085 appendPQExpBuffer(buf
, ";\n");
1090 appendPQExpBuffer(buf
, "\n-- For binary upgrade, set datfrozenxid.\n");
1091 appendPQExpBuffer(buf
, "UPDATE pg_database\n"
1092 "SET datfrozenxid = '%u'\n"
1093 "WHERE datname = '%s';\n",
1094 dbfrozenxid
, fdbname
);
1099 !buildACLCommands(fdbname
, NULL
, "DATABASE", dbacl
, dbowner
,
1100 server_version
, buf
))
1102 fprintf(stderr
, _("%s: could not parse ACL list (%s) for database \"%s\"\n"),
1103 progname
, dbacl
, fdbname
);
1108 fprintf(OPF
, "%s", buf
->data
);
1110 if (server_version
>= 70300)
1111 dumpDatabaseConfig(conn
, dbname
);
1117 destroyPQExpBuffer(buf
);
1119 fprintf(OPF
, "\n\n");
1125 * Dump database-specific configuration
1128 dumpDatabaseConfig(PGconn
*conn
, const char *dbname
)
1130 PQExpBuffer buf
= createPQExpBuffer();
1137 printfPQExpBuffer(buf
, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count
);
1138 appendStringLiteralConn(buf
, dbname
, conn
);
1139 appendPQExpBuffer(buf
, ";");
1141 res
= executeQuery(conn
, buf
->data
);
1142 if (!PQgetisnull(res
, 0, 0))
1144 makeAlterConfigCommand(conn
, PQgetvalue(res
, 0, 0),
1145 "DATABASE", dbname
);
1156 destroyPQExpBuffer(buf
);
1162 * Dump user-specific configuration
1165 dumpUserConfig(PGconn
*conn
, const char *username
)
1167 PQExpBuffer buf
= createPQExpBuffer();
1174 if (server_version
>= 80100)
1175 printfPQExpBuffer(buf
, "SELECT rolconfig[%d] FROM pg_authid WHERE rolname = ", count
);
1177 printfPQExpBuffer(buf
, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count
);
1178 appendStringLiteralConn(buf
, username
, conn
);
1180 res
= executeQuery(conn
, buf
->data
);
1181 if (PQntuples(res
) == 1 &&
1182 !PQgetisnull(res
, 0, 0))
1184 makeAlterConfigCommand(conn
, PQgetvalue(res
, 0, 0),
1196 destroyPQExpBuffer(buf
);
1202 * Helper function for dumpXXXConfig().
1205 makeAlterConfigCommand(PGconn
*conn
, const char *arrayitem
,
1206 const char *type
, const char *name
)
1210 PQExpBuffer buf
= createPQExpBuffer();
1212 mine
= strdup(arrayitem
);
1213 pos
= strchr(mine
, '=');
1218 appendPQExpBuffer(buf
, "ALTER %s %s ", type
, fmtId(name
));
1219 appendPQExpBuffer(buf
, "SET %s TO ", fmtId(mine
));
1222 * Some GUC variable names are 'LIST' type and hence must not be quoted.
1224 if (pg_strcasecmp(mine
, "DateStyle") == 0
1225 || pg_strcasecmp(mine
, "search_path") == 0)
1226 appendPQExpBuffer(buf
, "%s", pos
+ 1);
1228 appendStringLiteralConn(buf
, pos
+ 1, conn
);
1229 appendPQExpBuffer(buf
, ";\n");
1231 fprintf(OPF
, "%s", buf
->data
);
1232 destroyPQExpBuffer(buf
);
1239 * Dump contents of databases.
1242 dumpDatabases(PGconn
*conn
)
1247 if (server_version
>= 70100)
1248 res
= executeQuery(conn
, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1");
1250 res
= executeQuery(conn
, "SELECT datname FROM pg_database ORDER BY 1");
1252 for (i
= 0; i
< PQntuples(res
); i
++)
1256 char *dbname
= PQgetvalue(res
, i
, 0);
1259 fprintf(stderr
, _("%s: dumping database \"%s\"...\n"), progname
, dbname
);
1261 fprintf(OPF
, "\\connect %s\n\n", fmtId(dbname
));
1266 ret
= runPgDump(dbname
);
1269 fprintf(stderr
, _("%s: pg_dump failed on database \"%s\", exiting\n"), progname
, dbname
);
1275 OPF
= fopen(filename
, PG_BINARY_A
);
1278 fprintf(stderr
, _("%s: could not re-open the output file \"%s\": %s\n"),
1279 progname
, filename
, strerror(errno
));
1292 * Run pg_dump on dbname.
1295 runPgDump(const char *dbname
)
1297 PQExpBuffer cmd
= createPQExpBuffer();
1300 appendPQExpBuffer(cmd
, SYSTEMQUOTE
"\"%s\" %s", pg_dump_bin
,
1304 * If we have a filename, use the undocumented plain-append pg_dump
1308 appendPQExpBuffer(cmd
, " -Fa ");
1310 appendPQExpBuffer(cmd
, " -Fp ");
1312 doShellQuoting(cmd
, dbname
);
1314 appendPQExpBuffer(cmd
, "%s", SYSTEMQUOTE
);
1317 fprintf(stderr
, _("%s: running \"%s\"\n"), progname
, cmd
->data
);
1322 ret
= system(cmd
->data
);
1324 destroyPQExpBuffer(cmd
);
1331 * Make a database connection with the given parameters. An
1332 * interactive password prompt is automatically issued if required.
1334 * If fail_on_error is false, we return NULL without printing any message
1335 * on failure, but preserve any prompted password for the next try.
1338 connectDatabase(const char *dbname
, const char *pghost
, const char *pgport
,
1339 const char *pguser
, enum trivalue prompt_password
, bool fail_on_error
)
1343 const char *remoteversion_str
;
1345 static char *password
= NULL
;
1347 if (prompt_password
== TRI_YES
&& !password
)
1348 password
= simple_prompt("Password: ", 100, false);
1351 * Start the connection. Loop until we have a password if requested by
1357 conn
= PQsetdbLogin(pghost
, pgport
, NULL
, NULL
, dbname
, pguser
, password
);
1361 fprintf(stderr
, _("%s: could not connect to database \"%s\"\n"),
1366 if (PQstatus(conn
) == CONNECTION_BAD
&&
1367 PQconnectionNeedsPassword(conn
) &&
1369 prompt_password
!= TRI_NO
)
1372 password
= simple_prompt("Password: ", 100, false);
1377 /* check to see that the backend connection was successfully made */
1378 if (PQstatus(conn
) == CONNECTION_BAD
)
1383 _("%s: could not connect to database \"%s\": %s\n"),
1384 progname
, dbname
, PQerrorMessage(conn
));
1394 remoteversion_str
= PQparameterStatus(conn
, "server_version");
1395 if (!remoteversion_str
)
1397 fprintf(stderr
, _("%s: could not get server version\n"), progname
);
1400 server_version
= parse_version(remoteversion_str
);
1401 if (server_version
< 0)
1403 fprintf(stderr
, _("%s: could not parse server version \"%s\"\n"),
1404 progname
, remoteversion_str
);
1408 my_version
= parse_version(PG_VERSION
);
1411 fprintf(stderr
, _("%s: could not parse version \"%s\"\n"),
1412 progname
, PG_VERSION
);
1417 * We allow the server to be back to 7.0, and up to any minor release
1418 * of our own major version. (See also version check in pg_dump.c.)
1420 if (my_version
!= server_version
1421 && (server_version
< 70000 ||
1422 (server_version
/ 100) > (my_version
/ 100)))
1424 fprintf(stderr
, _("server version: %s; %s version: %s\n"),
1425 remoteversion_str
, progname
, PG_VERSION
);
1426 fprintf(stderr
, _("aborting because of server version mismatch\n"));
1431 * On 7.3 and later, make sure we are not fooled by non-system schemas in
1434 if (server_version
>= 70300)
1435 executeCommand(conn
, "SET search_path = pg_catalog");
1442 * Run a query, return the results, exit program on failure.
1445 executeQuery(PGconn
*conn
, const char *query
)
1450 fprintf(stderr
, _("%s: executing %s\n"), progname
, query
);
1452 res
= PQexec(conn
, query
);
1454 PQresultStatus(res
) != PGRES_TUPLES_OK
)
1456 fprintf(stderr
, _("%s: query failed: %s"),
1457 progname
, PQerrorMessage(conn
));
1458 fprintf(stderr
, _("%s: query was: %s\n"),
1468 * As above for a SQL command (which returns nothing).
1471 executeCommand(PGconn
*conn
, const char *query
)
1476 fprintf(stderr
, _("%s: executing %s\n"), progname
, query
);
1478 res
= PQexec(conn
, query
);
1480 PQresultStatus(res
) != PGRES_COMMAND_OK
)
1482 fprintf(stderr
, _("%s: query failed: %s"),
1483 progname
, PQerrorMessage(conn
));
1484 fprintf(stderr
, _("%s: query was: %s\n"),
1498 dumpTimestamp(char *msg
)
1501 time_t now
= time(NULL
);
1504 * We don't print the timezone on Win32, because the names are long and
1505 * localized, which means they may contain characters in various random
1506 * encodings; this has been seen to cause encoding errors when reading the
1509 if (strftime(buf
, sizeof(buf
),
1511 "%Y-%m-%d %H:%M:%S %Z",
1513 "%Y-%m-%d %H:%M:%S",
1515 localtime(&now
)) != 0)
1516 fprintf(OPF
, "-- %s %s\n\n", msg
, buf
);
1521 * Append the given string to the shell command being built in the buffer,
1522 * with suitable shell-style quoting.
1525 doShellQuoting(PQExpBuffer buf
, const char *str
)
1530 appendPQExpBufferChar(buf
, '\'');
1531 for (p
= str
; *p
; p
++)
1534 appendPQExpBuffer(buf
, "'\"'\"'");
1536 appendPQExpBufferChar(buf
, *p
);
1538 appendPQExpBufferChar(buf
, '\'');
1542 appendPQExpBufferChar(buf
, '"');
1543 for (p
= str
; *p
; p
++)
1546 appendPQExpBuffer(buf
, "\\\"");
1548 appendPQExpBufferChar(buf
, *p
);
1550 appendPQExpBufferChar(buf
, '"');