00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "postgres_fe.h"
00017
00018 #include <time.h>
00019 #include <unistd.h>
00020
00021 #ifdef ENABLE_NLS
00022 #include <locale.h>
00023 #endif
00024
00025 #include "getopt_long.h"
00026
00027 #include "dumputils.h"
00028 #include "pg_backup.h"
00029
00030
00031 #define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
00032
00033
00034 static void help(void);
00035
00036 static void dropRoles(PGconn *conn);
00037 static void dumpRoles(PGconn *conn);
00038 static void dumpRoleMembership(PGconn *conn);
00039 static void dumpGroups(PGconn *conn);
00040 static void dropTablespaces(PGconn *conn);
00041 static void dumpTablespaces(PGconn *conn);
00042 static void dropDBs(PGconn *conn);
00043 static void dumpCreateDB(PGconn *conn);
00044 static void dumpDatabaseConfig(PGconn *conn, const char *dbname);
00045 static void dumpUserConfig(PGconn *conn, const char *username);
00046 static void dumpDbRoleConfig(PGconn *conn);
00047 static void makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
00048 const char *type, const char *name, const char *type2,
00049 const char *name2);
00050 static void dumpDatabases(PGconn *conn);
00051 static void dumpTimestamp(char *msg);
00052 static void doShellQuoting(PQExpBuffer buf, const char *str);
00053 static void doConnStrQuoting(PQExpBuffer buf, const char *str);
00054
00055 static int runPgDump(const char *dbname);
00056 static void buildShSecLabels(PGconn *conn, const char *catalog_name,
00057 uint32 objectId, PQExpBuffer buffer,
00058 const char *target, const char *objname);
00059 static PGconn *connectDatabase(const char *dbname, const char *connstr, const char *pghost, const char *pgport,
00060 const char *pguser, enum trivalue prompt_password, bool fail_on_error);
00061 static char *constructConnStr(const char **keywords, const char **values);
00062 static PGresult *executeQuery(PGconn *conn, const char *query);
00063 static void executeCommand(PGconn *conn, const char *query);
00064
00065 static char pg_dump_bin[MAXPGPATH];
00066 static const char *progname;
00067 static PQExpBuffer pgdumpopts;
00068 static char *connstr = "";
00069 static bool skip_acls = false;
00070 static bool verbose = false;
00071
00072 static int binary_upgrade = 0;
00073 static int column_inserts = 0;
00074 static int disable_dollar_quoting = 0;
00075 static int disable_triggers = 0;
00076 static int inserts = 0;
00077 static int no_tablespaces = 0;
00078 static int use_setsessauth = 0;
00079 static int no_security_labels = 0;
00080 static int no_unlogged_table_data = 0;
00081 static int server_version;
00082
00083 static FILE *OPF;
00084 static char *filename = NULL;
00085
00086 #define exit_nicely(code) exit(code)
00087
00088 int
00089 main(int argc, char *argv[])
00090 {
00091 static struct option long_options[] = {
00092 {"data-only", no_argument, NULL, 'a'},
00093 {"clean", no_argument, NULL, 'c'},
00094 {"file", required_argument, NULL, 'f'},
00095 {"globals-only", no_argument, NULL, 'g'},
00096 {"host", required_argument, NULL, 'h'},
00097 {"ignore-version", no_argument, NULL, 'i'},
00098 {"dbname", required_argument, NULL, 'd'},
00099 {"database", required_argument, NULL, 'l'},
00100 {"oids", no_argument, NULL, 'o'},
00101 {"no-owner", no_argument, NULL, 'O'},
00102 {"port", required_argument, NULL, 'p'},
00103 {"roles-only", no_argument, NULL, 'r'},
00104 {"schema-only", no_argument, NULL, 's'},
00105 {"superuser", required_argument, NULL, 'S'},
00106 {"tablespaces-only", no_argument, NULL, 't'},
00107 {"username", required_argument, NULL, 'U'},
00108 {"verbose", no_argument, NULL, 'v'},
00109 {"no-password", no_argument, NULL, 'w'},
00110 {"password", no_argument, NULL, 'W'},
00111 {"no-privileges", no_argument, NULL, 'x'},
00112 {"no-acl", no_argument, NULL, 'x'},
00113
00114
00115
00116
00117 {"attribute-inserts", no_argument, &column_inserts, 1},
00118 {"binary-upgrade", no_argument, &binary_upgrade, 1},
00119 {"column-inserts", no_argument, &column_inserts, 1},
00120 {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
00121 {"disable-triggers", no_argument, &disable_triggers, 1},
00122 {"inserts", no_argument, &inserts, 1},
00123 {"lock-wait-timeout", required_argument, NULL, 2},
00124 {"no-tablespaces", no_argument, &no_tablespaces, 1},
00125 {"quote-all-identifiers", no_argument, "e_all_identifiers, 1},
00126 {"role", required_argument, NULL, 3},
00127 {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
00128 {"no-security-labels", no_argument, &no_security_labels, 1},
00129 {"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
00130
00131 {NULL, 0, NULL, 0}
00132 };
00133
00134 char *pghost = NULL;
00135 char *pgport = NULL;
00136 char *pguser = NULL;
00137 char *pgdb = NULL;
00138 char *use_role = NULL;
00139 enum trivalue prompt_password = TRI_DEFAULT;
00140 bool data_only = false;
00141 bool globals_only = false;
00142 bool output_clean = false;
00143 bool roles_only = false;
00144 bool tablespaces_only = false;
00145 PGconn *conn;
00146 int encoding;
00147 const char *std_strings;
00148 int c,
00149 ret;
00150 int optindex;
00151
00152 set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
00153
00154 progname = get_progname(argv[0]);
00155
00156 if (argc > 1)
00157 {
00158 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
00159 {
00160 help();
00161 exit_nicely(0);
00162 }
00163 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
00164 {
00165 puts("pg_dumpall (PostgreSQL) " PG_VERSION);
00166 exit_nicely(0);
00167 }
00168 }
00169
00170 if ((ret = find_other_exec(argv[0], "pg_dump", PGDUMP_VERSIONSTR,
00171 pg_dump_bin)) < 0)
00172 {
00173 char full_path[MAXPGPATH];
00174
00175 if (find_my_exec(argv[0], full_path) < 0)
00176 strlcpy(full_path, progname, sizeof(full_path));
00177
00178 if (ret == -1)
00179 fprintf(stderr,
00180 _("The program \"pg_dump\" is needed by %s "
00181 "but was not found in the\n"
00182 "same directory as \"%s\".\n"
00183 "Check your installation.\n"),
00184 progname, full_path);
00185 else
00186 fprintf(stderr,
00187 _("The program \"pg_dump\" was found by \"%s\"\n"
00188 "but was not the same version as %s.\n"
00189 "Check your installation.\n"),
00190 full_path, progname);
00191 exit_nicely(1);
00192 }
00193
00194 pgdumpopts = createPQExpBuffer();
00195
00196 while ((c = getopt_long(argc, argv, "acd:f:gh:i:l:oOp:rsS:tU:vwWx", long_options, &optindex)) != -1)
00197 {
00198 switch (c)
00199 {
00200 case 'a':
00201 data_only = true;
00202 appendPQExpBuffer(pgdumpopts, " -a");
00203 break;
00204
00205 case 'c':
00206 output_clean = true;
00207 break;
00208
00209 case 'd':
00210 connstr = pg_strdup(optarg);
00211 break;
00212
00213 case 'f':
00214 filename = pg_strdup(optarg);
00215 appendPQExpBuffer(pgdumpopts, " -f ");
00216 doShellQuoting(pgdumpopts, filename);
00217 break;
00218
00219 case 'g':
00220 globals_only = true;
00221 break;
00222
00223 case 'h':
00224 pghost = pg_strdup(optarg);
00225 break;
00226
00227 case 'i':
00228
00229 break;
00230
00231 case 'l':
00232 pgdb = pg_strdup(optarg);
00233 break;
00234
00235 case 'o':
00236 appendPQExpBuffer(pgdumpopts, " -o");
00237 break;
00238
00239 case 'O':
00240 appendPQExpBuffer(pgdumpopts, " -O");
00241 break;
00242
00243 case 'p':
00244 pgport = pg_strdup(optarg);
00245 break;
00246
00247 case 'r':
00248 roles_only = true;
00249 break;
00250
00251 case 's':
00252 appendPQExpBuffer(pgdumpopts, " -s");
00253 break;
00254
00255 case 'S':
00256 appendPQExpBuffer(pgdumpopts, " -S ");
00257 doShellQuoting(pgdumpopts, optarg);
00258 break;
00259
00260 case 't':
00261 tablespaces_only = true;
00262 break;
00263
00264 case 'U':
00265 pguser = pg_strdup(optarg);
00266 break;
00267
00268 case 'v':
00269 verbose = true;
00270 appendPQExpBuffer(pgdumpopts, " -v");
00271 break;
00272
00273 case 'w':
00274 prompt_password = TRI_NO;
00275 appendPQExpBuffer(pgdumpopts, " -w");
00276 break;
00277
00278 case 'W':
00279 prompt_password = TRI_YES;
00280 appendPQExpBuffer(pgdumpopts, " -W");
00281 break;
00282
00283 case 'x':
00284 skip_acls = true;
00285 appendPQExpBuffer(pgdumpopts, " -x");
00286 break;
00287
00288 case 0:
00289 break;
00290
00291 case 2:
00292 appendPQExpBuffer(pgdumpopts, " --lock-wait-timeout ");
00293 doShellQuoting(pgdumpopts, optarg);
00294 break;
00295
00296 case 3:
00297 use_role = pg_strdup(optarg);
00298 appendPQExpBuffer(pgdumpopts, " --role ");
00299 doShellQuoting(pgdumpopts, use_role);
00300 break;
00301
00302 default:
00303 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00304 exit_nicely(1);
00305 }
00306 }
00307
00308
00309 if (optind < argc)
00310 {
00311 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
00312 progname, argv[optind]);
00313 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
00314 progname);
00315 exit_nicely(1);
00316 }
00317
00318
00319 if (globals_only && roles_only)
00320 {
00321 fprintf(stderr, _("%s: options -g/--globals-only and -r/--roles-only cannot be used together\n"),
00322 progname);
00323 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
00324 progname);
00325 exit_nicely(1);
00326 }
00327
00328 if (globals_only && tablespaces_only)
00329 {
00330 fprintf(stderr, _("%s: options -g/--globals-only and -t/--tablespaces-only cannot be used together\n"),
00331 progname);
00332 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
00333 progname);
00334 exit_nicely(1);
00335 }
00336
00337 if (roles_only && tablespaces_only)
00338 {
00339 fprintf(stderr, _("%s: options -r/--roles-only and -t/--tablespaces-only cannot be used together\n"),
00340 progname);
00341 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
00342 progname);
00343 exit_nicely(1);
00344 }
00345
00346
00347 if (binary_upgrade)
00348 appendPQExpBuffer(pgdumpopts, " --binary-upgrade");
00349 if (column_inserts)
00350 appendPQExpBuffer(pgdumpopts, " --column-inserts");
00351 if (disable_dollar_quoting)
00352 appendPQExpBuffer(pgdumpopts, " --disable-dollar-quoting");
00353 if (disable_triggers)
00354 appendPQExpBuffer(pgdumpopts, " --disable-triggers");
00355 if (inserts)
00356 appendPQExpBuffer(pgdumpopts, " --inserts");
00357 if (no_tablespaces)
00358 appendPQExpBuffer(pgdumpopts, " --no-tablespaces");
00359 if (quote_all_identifiers)
00360 appendPQExpBuffer(pgdumpopts, " --quote-all-identifiers");
00361 if (use_setsessauth)
00362 appendPQExpBuffer(pgdumpopts, " --use-set-session-authorization");
00363 if (no_security_labels)
00364 appendPQExpBuffer(pgdumpopts, " --no-security-labels");
00365 if (no_unlogged_table_data)
00366 appendPQExpBuffer(pgdumpopts, " --no-unlogged-table-data");
00367
00368
00369
00370
00371
00372
00373
00374 if (pgdb)
00375 {
00376 conn = connectDatabase(pgdb, connstr, pghost, pgport, pguser,
00377 prompt_password, false);
00378
00379 if (!conn)
00380 {
00381 fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
00382 progname, pgdb);
00383 exit_nicely(1);
00384 }
00385 }
00386 else
00387 {
00388 conn = connectDatabase("postgres", connstr, pghost, pgport, pguser,
00389 prompt_password, false);
00390 if (!conn)
00391 conn = connectDatabase("template1", connstr, pghost, pgport, pguser,
00392 prompt_password, true);
00393
00394 if (!conn)
00395 {
00396 fprintf(stderr, _("%s: could not connect to databases \"postgres\" or \"template1\"\n"
00397 "Please specify an alternative database.\n"),
00398 progname);
00399 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
00400 progname);
00401 exit_nicely(1);
00402 }
00403 }
00404
00405
00406
00407
00408 if (filename)
00409 {
00410 OPF = fopen(filename, PG_BINARY_W);
00411 if (!OPF)
00412 {
00413 fprintf(stderr, _("%s: could not open the output file \"%s\": %s\n"),
00414 progname, filename, strerror(errno));
00415 exit_nicely(1);
00416 }
00417 }
00418 else
00419 OPF = stdout;
00420
00421
00422
00423
00424
00425 encoding = PQclientEncoding(conn);
00426 std_strings = PQparameterStatus(conn, "standard_conforming_strings");
00427 if (!std_strings)
00428 std_strings = "off";
00429
00430
00431 if (use_role && server_version >= 80100)
00432 {
00433 PQExpBuffer query = createPQExpBuffer();
00434
00435 appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
00436 executeCommand(conn, query->data);
00437 destroyPQExpBuffer(query);
00438 }
00439
00440
00441 if (quote_all_identifiers && server_version >= 90100)
00442 executeCommand(conn, "SET quote_all_identifiers = true");
00443
00444 fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n");
00445 if (verbose)
00446 dumpTimestamp("Started on");
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 fprintf(OPF, "SET client_encoding = '%s';\n",
00457 pg_encoding_to_char(encoding));
00458 fprintf(OPF, "SET standard_conforming_strings = %s;\n", std_strings);
00459 if (strcmp(std_strings, "off") == 0)
00460 fprintf(OPF, "SET escape_string_warning = off;\n");
00461 fprintf(OPF, "\n");
00462
00463 if (!data_only)
00464 {
00465
00466
00467
00468
00469
00470
00471 if (output_clean)
00472 {
00473 if (!globals_only && !roles_only && !tablespaces_only)
00474 dropDBs(conn);
00475
00476 if (!roles_only && !no_tablespaces)
00477 {
00478 if (server_version >= 80000)
00479 dropTablespaces(conn);
00480 }
00481
00482 if (!tablespaces_only)
00483 dropRoles(conn);
00484 }
00485
00486
00487
00488
00489
00490 if (!tablespaces_only)
00491 {
00492
00493 dumpRoles(conn);
00494
00495
00496 if (server_version >= 80100)
00497 dumpRoleMembership(conn);
00498 else
00499 dumpGroups(conn);
00500 }
00501
00502 if (!roles_only && !no_tablespaces)
00503 {
00504
00505 if (server_version >= 80000)
00506 dumpTablespaces(conn);
00507 }
00508
00509
00510 if (binary_upgrade || (!globals_only && !roles_only && !tablespaces_only))
00511 dumpCreateDB(conn);
00512
00513
00514 if (!tablespaces_only && !roles_only)
00515 {
00516 if (server_version >= 90000)
00517 dumpDbRoleConfig(conn);
00518 }
00519 }
00520
00521 if (!globals_only && !roles_only && !tablespaces_only)
00522 dumpDatabases(conn);
00523
00524 PQfinish(conn);
00525
00526 if (verbose)
00527 dumpTimestamp("Completed on");
00528 fprintf(OPF, "--\n-- PostgreSQL database cluster dump complete\n--\n\n");
00529
00530 if (filename)
00531 fclose(OPF);
00532
00533 exit_nicely(0);
00534 }
00535
00536
00537 static void
00538 help(void)
00539 {
00540 printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname);
00541 printf(_("Usage:\n"));
00542 printf(_(" %s [OPTION]...\n"), progname);
00543
00544 printf(_("\nGeneral options:\n"));
00545 printf(_(" -f, --file=FILENAME output file name\n"));
00546 printf(_(" -V, --version output version information, then exit\n"));
00547 printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
00548 printf(_(" -?, --help show this help, then exit\n"));
00549 printf(_("\nOptions controlling the output content:\n"));
00550 printf(_(" -a, --data-only dump only the data, not the schema\n"));
00551 printf(_(" -c, --clean clean (drop) databases before recreating\n"));
00552 printf(_(" -g, --globals-only dump only global objects, no databases\n"));
00553 printf(_(" -o, --oids include OIDs in dump\n"));
00554 printf(_(" -O, --no-owner skip restoration of object ownership\n"));
00555 printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n"));
00556 printf(_(" -s, --schema-only dump only the schema, no data\n"));
00557 printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n"));
00558 printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n"));
00559 printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
00560 printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
00561 printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
00562 printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
00563 printf(_(" --disable-triggers disable triggers during data-only restore\n"));
00564 printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
00565 printf(_(" --no-security-labels do not dump security label assignments\n"));
00566 printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
00567 printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
00568 printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
00569 printf(_(" --use-set-session-authorization\n"
00570 " use SET SESSION AUTHORIZATION commands instead of\n"
00571 " ALTER OWNER commands to set ownership\n"));
00572
00573 printf(_("\nConnection options:\n"));
00574 printf(_(" -d, --dbname=CONNSTR connect using connection string\n"));
00575 printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
00576 printf(_(" -l, --database=DBNAME alternative default database\n"));
00577 printf(_(" -p, --port=PORT database server port number\n"));
00578 printf(_(" -U, --username=NAME connect as specified database user\n"));
00579 printf(_(" -w, --no-password never prompt for password\n"));
00580 printf(_(" -W, --password force password prompt (should happen automatically)\n"));
00581 printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
00582
00583 printf(_("\nIf -f/--file is not used, then the SQL script will be written to the standard\n"
00584 "output.\n\n"));
00585 printf(_("Report bugs to <[email protected]>.\n"));
00586 }
00587
00588
00589
00590
00591
00592 static void
00593 dropRoles(PGconn *conn)
00594 {
00595 PGresult *res;
00596 int i_rolname;
00597 int i;
00598
00599 if (server_version >= 80100)
00600 res = executeQuery(conn,
00601 "SELECT rolname "
00602 "FROM pg_authid "
00603 "ORDER BY 1");
00604 else
00605 res = executeQuery(conn,
00606 "SELECT usename as rolname "
00607 "FROM pg_shadow "
00608 "UNION "
00609 "SELECT groname as rolname "
00610 "FROM pg_group "
00611 "ORDER BY 1");
00612
00613 i_rolname = PQfnumber(res, "rolname");
00614
00615 if (PQntuples(res) > 0)
00616 fprintf(OPF, "--\n-- Drop roles\n--\n\n");
00617
00618 for (i = 0; i < PQntuples(res); i++)
00619 {
00620 const char *rolename;
00621
00622 rolename = PQgetvalue(res, i, i_rolname);
00623
00624 fprintf(OPF, "DROP ROLE %s;\n", fmtId(rolename));
00625 }
00626
00627 PQclear(res);
00628
00629 fprintf(OPF, "\n\n");
00630 }
00631
00632
00633
00634
00635 static void
00636 dumpRoles(PGconn *conn)
00637 {
00638 PQExpBuffer buf = createPQExpBuffer();
00639 PGresult *res;
00640 int i_oid,
00641 i_rolname,
00642 i_rolsuper,
00643 i_rolinherit,
00644 i_rolcreaterole,
00645 i_rolcreatedb,
00646 i_rolcanlogin,
00647 i_rolconnlimit,
00648 i_rolpassword,
00649 i_rolvaliduntil,
00650 i_rolreplication,
00651 i_rolcomment,
00652 i_is_current_user;
00653 int i;
00654
00655
00656 if (server_version >= 90100)
00657 printfPQExpBuffer(buf,
00658 "SELECT oid, rolname, rolsuper, rolinherit, "
00659 "rolcreaterole, rolcreatedb, "
00660 "rolcanlogin, rolconnlimit, rolpassword, "
00661 "rolvaliduntil, rolreplication, "
00662 "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment, "
00663 "rolname = current_user AS is_current_user "
00664 "FROM pg_authid "
00665 "ORDER BY 2");
00666 else if (server_version >= 80200)
00667 printfPQExpBuffer(buf,
00668 "SELECT oid, rolname, rolsuper, rolinherit, "
00669 "rolcreaterole, rolcreatedb, "
00670 "rolcanlogin, rolconnlimit, rolpassword, "
00671 "rolvaliduntil, false as rolreplication, "
00672 "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment, "
00673 "rolname = current_user AS is_current_user "
00674 "FROM pg_authid "
00675 "ORDER BY 2");
00676 else if (server_version >= 80100)
00677 printfPQExpBuffer(buf,
00678 "SELECT oid, rolname, rolsuper, rolinherit, "
00679 "rolcreaterole, rolcreatedb, "
00680 "rolcanlogin, rolconnlimit, rolpassword, "
00681 "rolvaliduntil, false as rolreplication, "
00682 "null as rolcomment, "
00683 "rolname = current_user AS is_current_user "
00684 "FROM pg_authid "
00685 "ORDER BY 2");
00686 else
00687 printfPQExpBuffer(buf,
00688 "SELECT 0, usename as rolname, "
00689 "usesuper as rolsuper, "
00690 "true as rolinherit, "
00691 "usesuper as rolcreaterole, "
00692 "usecreatedb as rolcreatedb, "
00693 "true as rolcanlogin, "
00694 "-1 as rolconnlimit, "
00695 "passwd as rolpassword, "
00696 "valuntil as rolvaliduntil, "
00697 "false as rolreplication, "
00698 "null as rolcomment, "
00699 "rolname = current_user AS is_current_user "
00700 "FROM pg_shadow "
00701 "UNION ALL "
00702 "SELECT 0, groname as rolname, "
00703 "false as rolsuper, "
00704 "true as rolinherit, "
00705 "false as rolcreaterole, "
00706 "false as rolcreatedb, "
00707 "false as rolcanlogin, "
00708 "-1 as rolconnlimit, "
00709 "null::text as rolpassword, "
00710 "null::abstime as rolvaliduntil, "
00711 "false as rolreplication, "
00712 "null as rolcomment, false "
00713 "FROM pg_group "
00714 "WHERE NOT EXISTS (SELECT 1 FROM pg_shadow "
00715 " WHERE usename = groname) "
00716 "ORDER BY 2");
00717
00718 res = executeQuery(conn, buf->data);
00719
00720 i_oid = PQfnumber(res, "oid");
00721 i_rolname = PQfnumber(res, "rolname");
00722 i_rolsuper = PQfnumber(res, "rolsuper");
00723 i_rolinherit = PQfnumber(res, "rolinherit");
00724 i_rolcreaterole = PQfnumber(res, "rolcreaterole");
00725 i_rolcreatedb = PQfnumber(res, "rolcreatedb");
00726 i_rolcanlogin = PQfnumber(res, "rolcanlogin");
00727 i_rolconnlimit = PQfnumber(res, "rolconnlimit");
00728 i_rolpassword = PQfnumber(res, "rolpassword");
00729 i_rolvaliduntil = PQfnumber(res, "rolvaliduntil");
00730 i_rolreplication = PQfnumber(res, "rolreplication");
00731 i_rolcomment = PQfnumber(res, "rolcomment");
00732 i_is_current_user = PQfnumber(res, "is_current_user");
00733
00734 if (PQntuples(res) > 0)
00735 fprintf(OPF, "--\n-- Roles\n--\n\n");
00736
00737 for (i = 0; i < PQntuples(res); i++)
00738 {
00739 const char *rolename;
00740 Oid auth_oid;
00741
00742 auth_oid = atooid(PQgetvalue(res, i, i_oid));
00743 rolename = PQgetvalue(res, i, i_rolname);
00744
00745 resetPQExpBuffer(buf);
00746
00747 if (binary_upgrade)
00748 {
00749 appendPQExpBuffer(buf, "\n-- For binary upgrade, must preserve pg_authid.oid\n");
00750 appendPQExpBuffer(buf,
00751 "SELECT binary_upgrade.set_next_pg_authid_oid('%u'::pg_catalog.oid);\n\n",
00752 auth_oid);
00753 }
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 if (!binary_upgrade ||
00764 strcmp(PQgetvalue(res, i, i_is_current_user), "f") == 0)
00765 appendPQExpBuffer(buf, "CREATE ROLE %s;\n", fmtId(rolename));
00766 appendPQExpBuffer(buf, "ALTER ROLE %s WITH", fmtId(rolename));
00767
00768 if (strcmp(PQgetvalue(res, i, i_rolsuper), "t") == 0)
00769 appendPQExpBuffer(buf, " SUPERUSER");
00770 else
00771 appendPQExpBuffer(buf, " NOSUPERUSER");
00772
00773 if (strcmp(PQgetvalue(res, i, i_rolinherit), "t") == 0)
00774 appendPQExpBuffer(buf, " INHERIT");
00775 else
00776 appendPQExpBuffer(buf, " NOINHERIT");
00777
00778 if (strcmp(PQgetvalue(res, i, i_rolcreaterole), "t") == 0)
00779 appendPQExpBuffer(buf, " CREATEROLE");
00780 else
00781 appendPQExpBuffer(buf, " NOCREATEROLE");
00782
00783 if (strcmp(PQgetvalue(res, i, i_rolcreatedb), "t") == 0)
00784 appendPQExpBuffer(buf, " CREATEDB");
00785 else
00786 appendPQExpBuffer(buf, " NOCREATEDB");
00787
00788 if (strcmp(PQgetvalue(res, i, i_rolcanlogin), "t") == 0)
00789 appendPQExpBuffer(buf, " LOGIN");
00790 else
00791 appendPQExpBuffer(buf, " NOLOGIN");
00792
00793 if (strcmp(PQgetvalue(res, i, i_rolreplication), "t") == 0)
00794 appendPQExpBuffer(buf, " REPLICATION");
00795 else
00796 appendPQExpBuffer(buf, " NOREPLICATION");
00797
00798 if (strcmp(PQgetvalue(res, i, i_rolconnlimit), "-1") != 0)
00799 appendPQExpBuffer(buf, " CONNECTION LIMIT %s",
00800 PQgetvalue(res, i, i_rolconnlimit));
00801
00802 if (!PQgetisnull(res, i, i_rolpassword))
00803 {
00804 appendPQExpBuffer(buf, " PASSWORD ");
00805 appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolpassword), conn);
00806 }
00807
00808 if (!PQgetisnull(res, i, i_rolvaliduntil))
00809 appendPQExpBuffer(buf, " VALID UNTIL '%s'",
00810 PQgetvalue(res, i, i_rolvaliduntil));
00811
00812 appendPQExpBuffer(buf, ";\n");
00813
00814 if (!PQgetisnull(res, i, i_rolcomment))
00815 {
00816 appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
00817 appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolcomment), conn);
00818 appendPQExpBuffer(buf, ";\n");
00819 }
00820
00821 if (!no_security_labels && server_version >= 90200)
00822 buildShSecLabels(conn, "pg_authid", auth_oid,
00823 buf, "ROLE", rolename);
00824
00825 fprintf(OPF, "%s", buf->data);
00826 }
00827
00828
00829
00830
00831
00832
00833 if (server_version >= 70300)
00834 for (i = 0; i < PQntuples(res); i++)
00835 dumpUserConfig(conn, PQgetvalue(res, i, i_rolname));
00836
00837 PQclear(res);
00838
00839 fprintf(OPF, "\n\n");
00840
00841 destroyPQExpBuffer(buf);
00842 }
00843
00844
00845
00846
00847
00848
00849
00850
00851 static void
00852 dumpRoleMembership(PGconn *conn)
00853 {
00854 PGresult *res;
00855 int i;
00856
00857 res = executeQuery(conn, "SELECT ur.rolname AS roleid, "
00858 "um.rolname AS member, "
00859 "a.admin_option, "
00860 "ug.rolname AS grantor "
00861 "FROM pg_auth_members a "
00862 "LEFT JOIN pg_authid ur on ur.oid = a.roleid "
00863 "LEFT JOIN pg_authid um on um.oid = a.member "
00864 "LEFT JOIN pg_authid ug on ug.oid = a.grantor "
00865 "ORDER BY 1,2,3");
00866
00867 if (PQntuples(res) > 0)
00868 fprintf(OPF, "--\n-- Role memberships\n--\n\n");
00869
00870 for (i = 0; i < PQntuples(res); i++)
00871 {
00872 char *roleid = PQgetvalue(res, i, 0);
00873 char *member = PQgetvalue(res, i, 1);
00874 char *option = PQgetvalue(res, i, 2);
00875
00876 fprintf(OPF, "GRANT %s", fmtId(roleid));
00877 fprintf(OPF, " TO %s", fmtId(member));
00878 if (*option == 't')
00879 fprintf(OPF, " WITH ADMIN OPTION");
00880
00881
00882
00883
00884
00885 if (!PQgetisnull(res, i, 3))
00886 {
00887 char *grantor = PQgetvalue(res, i, 3);
00888
00889 fprintf(OPF, " GRANTED BY %s", fmtId(grantor));
00890 }
00891 fprintf(OPF, ";\n");
00892 }
00893
00894 PQclear(res);
00895
00896 fprintf(OPF, "\n\n");
00897 }
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 static void
00908 dumpGroups(PGconn *conn)
00909 {
00910 PQExpBuffer buf = createPQExpBuffer();
00911 PGresult *res;
00912 int i;
00913
00914 res = executeQuery(conn,
00915 "SELECT groname, grolist FROM pg_group ORDER BY 1");
00916
00917 if (PQntuples(res) > 0)
00918 fprintf(OPF, "--\n-- Role memberships\n--\n\n");
00919
00920 for (i = 0; i < PQntuples(res); i++)
00921 {
00922 char *groname = PQgetvalue(res, i, 0);
00923 char *grolist = PQgetvalue(res, i, 1);
00924 PGresult *res2;
00925 int j;
00926
00927
00928
00929
00930 if (strlen(grolist) < 3)
00931 continue;
00932
00933 grolist = pg_strdup(grolist);
00934 grolist[0] = '(';
00935 grolist[strlen(grolist) - 1] = ')';
00936 printfPQExpBuffer(buf,
00937 "SELECT usename FROM pg_shadow "
00938 "WHERE usesysid IN %s ORDER BY 1",
00939 grolist);
00940 free(grolist);
00941
00942 res2 = executeQuery(conn, buf->data);
00943
00944 for (j = 0; j < PQntuples(res2); j++)
00945 {
00946 char *usename = PQgetvalue(res2, j, 0);
00947
00948
00949
00950
00951
00952 if (strcmp(groname, usename) == 0)
00953 continue;
00954
00955 fprintf(OPF, "GRANT %s", fmtId(groname));
00956 fprintf(OPF, " TO %s;\n", fmtId(usename));
00957 }
00958
00959 PQclear(res2);
00960 }
00961
00962 PQclear(res);
00963 destroyPQExpBuffer(buf);
00964
00965 fprintf(OPF, "\n\n");
00966 }
00967
00968
00969
00970
00971
00972 static void
00973 dropTablespaces(PGconn *conn)
00974 {
00975 PGresult *res;
00976 int i;
00977
00978
00979
00980
00981
00982 res = executeQuery(conn, "SELECT spcname "
00983 "FROM pg_catalog.pg_tablespace "
00984 "WHERE spcname !~ '^pg_' "
00985 "ORDER BY 1");
00986
00987 if (PQntuples(res) > 0)
00988 fprintf(OPF, "--\n-- Drop tablespaces\n--\n\n");
00989
00990 for (i = 0; i < PQntuples(res); i++)
00991 {
00992 char *spcname = PQgetvalue(res, i, 0);
00993
00994 fprintf(OPF, "DROP TABLESPACE %s;\n", fmtId(spcname));
00995 }
00996
00997 PQclear(res);
00998
00999 fprintf(OPF, "\n\n");
01000 }
01001
01002
01003
01004
01005 static void
01006 dumpTablespaces(PGconn *conn)
01007 {
01008 PGresult *res;
01009 int i;
01010
01011
01012
01013
01014
01015 if (server_version >= 90200)
01016 res = executeQuery(conn, "SELECT oid, spcname, "
01017 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
01018 "pg_catalog.pg_tablespace_location(oid), spcacl, "
01019 "array_to_string(spcoptions, ', '),"
01020 "pg_catalog.shobj_description(oid, 'pg_tablespace') "
01021 "FROM pg_catalog.pg_tablespace "
01022 "WHERE spcname !~ '^pg_' "
01023 "ORDER BY 1");
01024 else if (server_version >= 90000)
01025 res = executeQuery(conn, "SELECT oid, spcname, "
01026 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
01027 "spclocation, spcacl, "
01028 "array_to_string(spcoptions, ', '),"
01029 "pg_catalog.shobj_description(oid, 'pg_tablespace') "
01030 "FROM pg_catalog.pg_tablespace "
01031 "WHERE spcname !~ '^pg_' "
01032 "ORDER BY 1");
01033 else if (server_version >= 80200)
01034 res = executeQuery(conn, "SELECT oid, spcname, "
01035 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
01036 "spclocation, spcacl, null, "
01037 "pg_catalog.shobj_description(oid, 'pg_tablespace') "
01038 "FROM pg_catalog.pg_tablespace "
01039 "WHERE spcname !~ '^pg_' "
01040 "ORDER BY 1");
01041 else
01042 res = executeQuery(conn, "SELECT oid, spcname, "
01043 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
01044 "spclocation, spcacl, "
01045 "null, null "
01046 "FROM pg_catalog.pg_tablespace "
01047 "WHERE spcname !~ '^pg_' "
01048 "ORDER BY 1");
01049
01050 if (PQntuples(res) > 0)
01051 fprintf(OPF, "--\n-- Tablespaces\n--\n\n");
01052
01053 for (i = 0; i < PQntuples(res); i++)
01054 {
01055 PQExpBuffer buf = createPQExpBuffer();
01056 uint32 spcoid = atooid(PQgetvalue(res, i, 0));
01057 char *spcname = PQgetvalue(res, i, 1);
01058 char *spcowner = PQgetvalue(res, i, 2);
01059 char *spclocation = PQgetvalue(res, i, 3);
01060 char *spcacl = PQgetvalue(res, i, 4);
01061 char *spcoptions = PQgetvalue(res, i, 5);
01062 char *spccomment = PQgetvalue(res, i, 6);
01063 char *fspcname;
01064
01065
01066 fspcname = pg_strdup(fmtId(spcname));
01067
01068 appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname);
01069 appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
01070
01071 appendPQExpBuffer(buf, " LOCATION ");
01072 appendStringLiteralConn(buf, spclocation, conn);
01073 appendPQExpBuffer(buf, ";\n");
01074
01075 if (spcoptions && spcoptions[0] != '\0')
01076 appendPQExpBuffer(buf, "ALTER TABLESPACE %s SET (%s);\n",
01077 fspcname, spcoptions);
01078
01079 if (!skip_acls &&
01080 !buildACLCommands(fspcname, NULL, "TABLESPACE", spcacl, spcowner,
01081 "", server_version, buf))
01082 {
01083 fprintf(stderr, _("%s: could not parse ACL list (%s) for tablespace \"%s\"\n"),
01084 progname, spcacl, fspcname);
01085 PQfinish(conn);
01086 exit_nicely(1);
01087 }
01088
01089 if (spccomment && strlen(spccomment))
01090 {
01091 appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
01092 appendStringLiteralConn(buf, spccomment, conn);
01093 appendPQExpBuffer(buf, ";\n");
01094 }
01095
01096 if (!no_security_labels && server_version >= 90200)
01097 buildShSecLabels(conn, "pg_tablespace", spcoid,
01098 buf, "TABLESPACE", fspcname);
01099
01100 fprintf(OPF, "%s", buf->data);
01101
01102 free(fspcname);
01103 destroyPQExpBuffer(buf);
01104 }
01105
01106 PQclear(res);
01107 fprintf(OPF, "\n\n");
01108 }
01109
01110
01111
01112
01113
01114
01115
01116 static void
01117 dropDBs(PGconn *conn)
01118 {
01119 PGresult *res;
01120 int i;
01121
01122 if (server_version >= 70100)
01123 res = executeQuery(conn,
01124 "SELECT datname "
01125 "FROM pg_database d "
01126 "WHERE datallowconn ORDER BY 1");
01127 else
01128 res = executeQuery(conn,
01129 "SELECT datname "
01130 "FROM pg_database d "
01131 "ORDER BY 1");
01132
01133 if (PQntuples(res) > 0)
01134 fprintf(OPF, "--\n-- Drop databases\n--\n\n");
01135
01136 for (i = 0; i < PQntuples(res); i++)
01137 {
01138 char *dbname = PQgetvalue(res, i, 0);
01139
01140
01141
01142
01143
01144
01145 if (strcmp(dbname, "template1") != 0 &&
01146 strcmp(dbname, "postgres") != 0)
01147 {
01148 fprintf(OPF, "DROP DATABASE %s;\n", fmtId(dbname));
01149 }
01150 }
01151
01152 PQclear(res);
01153
01154 fprintf(OPF, "\n\n");
01155 }
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168 static void
01169 dumpCreateDB(PGconn *conn)
01170 {
01171 PQExpBuffer buf = createPQExpBuffer();
01172 char *default_encoding = NULL;
01173 char *default_collate = NULL;
01174 char *default_ctype = NULL;
01175 PGresult *res;
01176 int i;
01177
01178 fprintf(OPF, "--\n-- Database creation\n--\n\n");
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192 if (server_version >= 80400)
01193 res = executeQuery(conn,
01194 "SELECT pg_encoding_to_char(encoding), "
01195 "datcollate, datctype "
01196 "FROM pg_database "
01197 "WHERE datname = 'template0'");
01198 else if (server_version >= 70100)
01199 res = executeQuery(conn,
01200 "SELECT pg_encoding_to_char(encoding), "
01201 "null::text AS datcollate, null::text AS datctype "
01202 "FROM pg_database "
01203 "WHERE datname = 'template0'");
01204 else
01205 res = executeQuery(conn,
01206 "SELECT pg_encoding_to_char(encoding), "
01207 "null::text AS datcollate, null::text AS datctype "
01208 "FROM pg_database "
01209 "WHERE datname = 'template1'");
01210
01211
01212 if (PQntuples(res) > 0)
01213 {
01214 if (!PQgetisnull(res, 0, 0))
01215 default_encoding = pg_strdup(PQgetvalue(res, 0, 0));
01216 if (!PQgetisnull(res, 0, 1))
01217 default_collate = pg_strdup(PQgetvalue(res, 0, 1));
01218 if (!PQgetisnull(res, 0, 2))
01219 default_ctype = pg_strdup(PQgetvalue(res, 0, 2));
01220 }
01221
01222 PQclear(res);
01223
01224
01225 if (server_version >= 80400)
01226 res = executeQuery(conn,
01227 "SELECT datname, "
01228 "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
01229 "pg_encoding_to_char(d.encoding), "
01230 "datcollate, datctype, datfrozenxid, "
01231 "datistemplate, datacl, datconnlimit, "
01232 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
01233 "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
01234 "WHERE datallowconn ORDER BY 1");
01235 else if (server_version >= 80100)
01236 res = executeQuery(conn,
01237 "SELECT datname, "
01238 "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
01239 "pg_encoding_to_char(d.encoding), "
01240 "null::text AS datcollate, null::text AS datctype, datfrozenxid, "
01241 "datistemplate, datacl, datconnlimit, "
01242 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
01243 "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
01244 "WHERE datallowconn ORDER BY 1");
01245 else if (server_version >= 80000)
01246 res = executeQuery(conn,
01247 "SELECT datname, "
01248 "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
01249 "pg_encoding_to_char(d.encoding), "
01250 "null::text AS datcollate, null::text AS datctype, datfrozenxid, "
01251 "datistemplate, datacl, -1 as datconnlimit, "
01252 "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
01253 "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
01254 "WHERE datallowconn ORDER BY 1");
01255 else if (server_version >= 70300)
01256 res = executeQuery(conn,
01257 "SELECT datname, "
01258 "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
01259 "pg_encoding_to_char(d.encoding), "
01260 "null::text AS datcollate, null::text AS datctype, datfrozenxid, "
01261 "datistemplate, datacl, -1 as datconnlimit, "
01262 "'pg_default' AS dattablespace "
01263 "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
01264 "WHERE datallowconn ORDER BY 1");
01265 else if (server_version >= 70100)
01266 res = executeQuery(conn,
01267 "SELECT datname, "
01268 "coalesce("
01269 "(select usename from pg_shadow where usesysid=datdba), "
01270 "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
01271 "pg_encoding_to_char(d.encoding), "
01272 "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, "
01273 "datistemplate, '' as datacl, -1 as datconnlimit, "
01274 "'pg_default' AS dattablespace "
01275 "FROM pg_database d "
01276 "WHERE datallowconn ORDER BY 1");
01277 else
01278 {
01279
01280
01281
01282
01283 res = executeQuery(conn,
01284 "SELECT datname, "
01285 "(select usename from pg_shadow where usesysid=datdba), "
01286 "pg_encoding_to_char(d.encoding), "
01287 "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, "
01288 "'f' as datistemplate, "
01289 "'' as datacl, -1 as datconnlimit, "
01290 "'pg_default' AS dattablespace "
01291 "FROM pg_database d "
01292 "ORDER BY 1");
01293 }
01294
01295 for (i = 0; i < PQntuples(res); i++)
01296 {
01297 char *dbname = PQgetvalue(res, i, 0);
01298 char *dbowner = PQgetvalue(res, i, 1);
01299 char *dbencoding = PQgetvalue(res, i, 2);
01300 char *dbcollate = PQgetvalue(res, i, 3);
01301 char *dbctype = PQgetvalue(res, i, 4);
01302 uint32 dbfrozenxid = atooid(PQgetvalue(res, i, 5));
01303 char *dbistemplate = PQgetvalue(res, i, 6);
01304 char *dbacl = PQgetvalue(res, i, 7);
01305 char *dbconnlimit = PQgetvalue(res, i, 8);
01306 char *dbtablespace = PQgetvalue(res, i, 9);
01307 char *fdbname;
01308
01309 fdbname = pg_strdup(fmtId(dbname));
01310
01311 resetPQExpBuffer(buf);
01312
01313
01314
01315
01316
01317
01318 if (strcmp(dbname, "template1") != 0 &&
01319 strcmp(dbname, "postgres") != 0)
01320 {
01321 appendPQExpBuffer(buf, "CREATE DATABASE %s", fdbname);
01322
01323 appendPQExpBuffer(buf, " WITH TEMPLATE = template0");
01324
01325 if (strlen(dbowner) != 0)
01326 appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner));
01327
01328 if (default_encoding && strcmp(dbencoding, default_encoding) != 0)
01329 {
01330 appendPQExpBuffer(buf, " ENCODING = ");
01331 appendStringLiteralConn(buf, dbencoding, conn);
01332 }
01333
01334 if (default_collate && strcmp(dbcollate, default_collate) != 0)
01335 {
01336 appendPQExpBuffer(buf, " LC_COLLATE = ");
01337 appendStringLiteralConn(buf, dbcollate, conn);
01338 }
01339
01340 if (default_ctype && strcmp(dbctype, default_ctype) != 0)
01341 {
01342 appendPQExpBuffer(buf, " LC_CTYPE = ");
01343 appendStringLiteralConn(buf, dbctype, conn);
01344 }
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354 if (strcmp(dbtablespace, "pg_default") != 0 && !no_tablespaces)
01355 appendPQExpBuffer(buf, " TABLESPACE = %s",
01356 fmtId(dbtablespace));
01357
01358 if (strcmp(dbconnlimit, "-1") != 0)
01359 appendPQExpBuffer(buf, " CONNECTION LIMIT = %s",
01360 dbconnlimit);
01361
01362 appendPQExpBuffer(buf, ";\n");
01363
01364 if (strcmp(dbistemplate, "t") == 0)
01365 {
01366 appendPQExpBuffer(buf, "UPDATE pg_catalog.pg_database SET datistemplate = 't' WHERE datname = ");
01367 appendStringLiteralConn(buf, dbname, conn);
01368 appendPQExpBuffer(buf, ";\n");
01369 }
01370
01371 if (binary_upgrade)
01372 {
01373 appendPQExpBuffer(buf, "-- For binary upgrade, set datfrozenxid.\n");
01374 appendPQExpBuffer(buf, "UPDATE pg_catalog.pg_database "
01375 "SET datfrozenxid = '%u' "
01376 "WHERE datname = ",
01377 dbfrozenxid);
01378 appendStringLiteralConn(buf, dbname, conn);
01379 appendPQExpBuffer(buf, ";\n");
01380 }
01381 }
01382
01383 if (!skip_acls &&
01384 !buildACLCommands(fdbname, NULL, "DATABASE", dbacl, dbowner,
01385 "", server_version, buf))
01386 {
01387 fprintf(stderr, _("%s: could not parse ACL list (%s) for database \"%s\"\n"),
01388 progname, dbacl, fdbname);
01389 PQfinish(conn);
01390 exit_nicely(1);
01391 }
01392
01393 fprintf(OPF, "%s", buf->data);
01394
01395 if (server_version >= 70300)
01396 dumpDatabaseConfig(conn, dbname);
01397
01398 free(fdbname);
01399 }
01400
01401 PQclear(res);
01402 destroyPQExpBuffer(buf);
01403
01404 fprintf(OPF, "\n\n");
01405 }
01406
01407
01408
01409
01410
01411 static void
01412 dumpDatabaseConfig(PGconn *conn, const char *dbname)
01413 {
01414 PQExpBuffer buf = createPQExpBuffer();
01415 int count = 1;
01416
01417 for (;;)
01418 {
01419 PGresult *res;
01420
01421 if (server_version >= 90000)
01422 printfPQExpBuffer(buf, "SELECT setconfig[%d] FROM pg_db_role_setting WHERE "
01423 "setrole = 0 AND setdatabase = (SELECT oid FROM pg_database WHERE datname = ", count);
01424 else
01425 printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count);
01426 appendStringLiteralConn(buf, dbname, conn);
01427
01428 if (server_version >= 90000)
01429 appendPQExpBuffer(buf, ")");
01430
01431 appendPQExpBuffer(buf, ";");
01432
01433 res = executeQuery(conn, buf->data);
01434 if (PQntuples(res) == 1 &&
01435 !PQgetisnull(res, 0, 0))
01436 {
01437 makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
01438 "DATABASE", dbname, NULL, NULL);
01439 PQclear(res);
01440 count++;
01441 }
01442 else
01443 {
01444 PQclear(res);
01445 break;
01446 }
01447 }
01448
01449 destroyPQExpBuffer(buf);
01450 }
01451
01452
01453
01454
01455
01456
01457 static void
01458 dumpUserConfig(PGconn *conn, const char *username)
01459 {
01460 PQExpBuffer buf = createPQExpBuffer();
01461 int count = 1;
01462
01463 for (;;)
01464 {
01465 PGresult *res;
01466
01467 if (server_version >= 90000)
01468 printfPQExpBuffer(buf, "SELECT setconfig[%d] FROM pg_db_role_setting WHERE "
01469 "setdatabase = 0 AND setrole = "
01470 "(SELECT oid FROM pg_authid WHERE rolname = ", count);
01471 else if (server_version >= 80100)
01472 printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM pg_authid WHERE rolname = ", count);
01473 else
01474 printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
01475 appendStringLiteralConn(buf, username, conn);
01476 if (server_version >= 90000)
01477 appendPQExpBuffer(buf, ")");
01478
01479 res = executeQuery(conn, buf->data);
01480 if (PQntuples(res) == 1 &&
01481 !PQgetisnull(res, 0, 0))
01482 {
01483 makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
01484 "ROLE", username, NULL, NULL);
01485 PQclear(res);
01486 count++;
01487 }
01488 else
01489 {
01490 PQclear(res);
01491 break;
01492 }
01493 }
01494
01495 destroyPQExpBuffer(buf);
01496 }
01497
01498
01499
01500
01501
01502 static void
01503 dumpDbRoleConfig(PGconn *conn)
01504 {
01505 PQExpBuffer buf = createPQExpBuffer();
01506 PGresult *res;
01507 int i;
01508
01509 printfPQExpBuffer(buf, "SELECT rolname, datname, unnest(setconfig) "
01510 "FROM pg_db_role_setting, pg_authid, pg_database "
01511 "WHERE setrole = pg_authid.oid AND setdatabase = pg_database.oid");
01512 res = executeQuery(conn, buf->data);
01513
01514 if (PQntuples(res) > 0)
01515 {
01516 fprintf(OPF, "--\n-- Per-Database Role Settings \n--\n\n");
01517
01518 for (i = 0; i < PQntuples(res); i++)
01519 {
01520 makeAlterConfigCommand(conn, PQgetvalue(res, i, 2),
01521 "ROLE", PQgetvalue(res, i, 0),
01522 "DATABASE", PQgetvalue(res, i, 1));
01523 }
01524
01525 fprintf(OPF, "\n\n");
01526 }
01527
01528 PQclear(res);
01529 destroyPQExpBuffer(buf);
01530 }
01531
01532
01533
01534
01535
01536 static void
01537 makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
01538 const char *type, const char *name,
01539 const char *type2, const char *name2)
01540 {
01541 char *pos;
01542 char *mine;
01543 PQExpBuffer buf;
01544
01545 mine = pg_strdup(arrayitem);
01546 pos = strchr(mine, '=');
01547 if (pos == NULL)
01548 {
01549 free(mine);
01550 return;
01551 }
01552
01553 buf = createPQExpBuffer();
01554
01555 *pos = 0;
01556 appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name));
01557 if (type2 != NULL && name2 != NULL)
01558 appendPQExpBuffer(buf, "IN %s %s ", type2, fmtId(name2));
01559 appendPQExpBuffer(buf, "SET %s TO ", fmtId(mine));
01560
01561
01562
01563
01564 if (pg_strcasecmp(mine, "DateStyle") == 0
01565 || pg_strcasecmp(mine, "search_path") == 0)
01566 appendPQExpBuffer(buf, "%s", pos + 1);
01567 else
01568 appendStringLiteralConn(buf, pos + 1, conn);
01569 appendPQExpBuffer(buf, ";\n");
01570
01571 fprintf(OPF, "%s", buf->data);
01572 destroyPQExpBuffer(buf);
01573 free(mine);
01574 }
01575
01576
01577
01578
01579
01580
01581 static void
01582 dumpDatabases(PGconn *conn)
01583 {
01584 PGresult *res;
01585 int i;
01586
01587 if (server_version >= 70100)
01588 res = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1");
01589 else
01590 res = executeQuery(conn, "SELECT datname FROM pg_database ORDER BY 1");
01591
01592 for (i = 0; i < PQntuples(res); i++)
01593 {
01594 int ret;
01595
01596 char *dbname = PQgetvalue(res, i, 0);
01597
01598 if (verbose)
01599 fprintf(stderr, _("%s: dumping database \"%s\"...\n"), progname, dbname);
01600
01601 fprintf(OPF, "\\connect %s\n\n", fmtId(dbname));
01602
01603 if (filename)
01604 fclose(OPF);
01605
01606 ret = runPgDump(dbname);
01607 if (ret != 0)
01608 {
01609 fprintf(stderr, _("%s: pg_dump failed on database \"%s\", exiting\n"), progname, dbname);
01610 exit_nicely(1);
01611 }
01612
01613 if (filename)
01614 {
01615 OPF = fopen(filename, PG_BINARY_A);
01616 if (!OPF)
01617 {
01618 fprintf(stderr, _("%s: could not re-open the output file \"%s\": %s\n"),
01619 progname, filename, strerror(errno));
01620 exit_nicely(1);
01621 }
01622 }
01623
01624 }
01625
01626 PQclear(res);
01627 }
01628
01629
01630
01631
01632
01633
01634 static int
01635 runPgDump(const char *dbname)
01636 {
01637 PQExpBuffer connstrbuf = createPQExpBuffer();
01638 PQExpBuffer cmd = createPQExpBuffer();
01639 int ret;
01640
01641 appendPQExpBuffer(cmd, SYSTEMQUOTE "\"%s\" %s", pg_dump_bin,
01642 pgdumpopts->data);
01643
01644
01645
01646
01647
01648 if (filename)
01649 appendPQExpBuffer(cmd, " -Fa ");
01650 else
01651 appendPQExpBuffer(cmd, " -Fp ");
01652
01653
01654
01655
01656
01657 appendPQExpBuffer(connstrbuf, "%s dbname=", connstr);
01658 doConnStrQuoting(connstrbuf, dbname);
01659
01660 doShellQuoting(cmd, connstrbuf->data);
01661
01662 appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE);
01663
01664 if (verbose)
01665 fprintf(stderr, _("%s: running \"%s\"\n"), progname, cmd->data);
01666
01667 fflush(stdout);
01668 fflush(stderr);
01669
01670 ret = system(cmd->data);
01671
01672 destroyPQExpBuffer(cmd);
01673 destroyPQExpBuffer(connstrbuf);
01674
01675 return ret;
01676 }
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686 static void
01687 buildShSecLabels(PGconn *conn, const char *catalog_name, uint32 objectId,
01688 PQExpBuffer buffer, const char *target, const char *objname)
01689 {
01690 PQExpBuffer sql = createPQExpBuffer();
01691 PGresult *res;
01692
01693 buildShSecLabelQuery(conn, catalog_name, objectId, sql);
01694 res = executeQuery(conn, sql->data);
01695 emitShSecLabels(conn, res, buffer, target, objname);
01696
01697 PQclear(res);
01698 destroyPQExpBuffer(sql);
01699 }
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711 static PGconn *
01712 connectDatabase(const char *dbname, const char *connection_string,
01713 const char *pghost, const char *pgport, const char *pguser,
01714 enum trivalue prompt_password, bool fail_on_error)
01715 {
01716 PGconn *conn;
01717 bool new_pass;
01718 const char *remoteversion_str;
01719 int my_version;
01720 static char *password = NULL;
01721 const char **keywords = NULL;
01722 const char **values = NULL;
01723 PQconninfoOption *conn_opts = NULL;
01724
01725 if (prompt_password == TRI_YES && !password)
01726 password = simple_prompt("Password: ", 100, false);
01727
01728
01729
01730
01731
01732 do
01733 {
01734 int argcount = 6;
01735 PQconninfoOption *conn_opt;
01736 char *err_msg = NULL;
01737 int i = 0;
01738
01739 if (keywords)
01740 free(keywords);
01741 if (values)
01742 free(values);
01743 if (conn_opts)
01744 PQconninfoFree(conn_opts);
01745
01746
01747
01748
01749
01750 if (connection_string)
01751 {
01752 conn_opts = PQconninfoParse(connection_string, &err_msg);
01753 if (conn_opts == NULL)
01754 {
01755 fprintf(stderr, "%s: %s\n", progname, err_msg);
01756 exit_nicely(1);
01757 }
01758
01759 for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
01760 {
01761 if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
01762 argcount++;
01763 }
01764
01765 keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
01766 values = pg_malloc0((argcount + 1) * sizeof(*values));
01767
01768 for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
01769 {
01770 if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
01771 {
01772 keywords[i] = conn_opt->keyword;
01773 values[i] = conn_opt->val;
01774 i++;
01775 }
01776 }
01777 }
01778 else
01779 {
01780 keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
01781 values = pg_malloc0((argcount + 1) * sizeof(*values));
01782 }
01783
01784 if (pghost)
01785 {
01786 keywords[i] = "host";
01787 values[i] = pghost;
01788 i++;
01789 }
01790 if (pgport)
01791 {
01792 keywords[i] = "port";
01793 values[i] = pgport;
01794 i++;
01795 }
01796 if (pguser)
01797 {
01798 keywords[i] = "user";
01799 values[i] = pguser;
01800 i++;
01801 }
01802 if (password)
01803 {
01804 keywords[i] = "password";
01805 values[i] = password;
01806 i++;
01807 }
01808 if (dbname)
01809 {
01810 keywords[i] = "dbname";
01811 values[i] = dbname;
01812 i++;
01813 }
01814 keywords[i] = "fallback_application_name";
01815 values[i] = progname;
01816 i++;
01817
01818 new_pass = false;
01819 conn = PQconnectdbParams(keywords, values, true);
01820
01821 if (!conn)
01822 {
01823 fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
01824 progname, dbname);
01825 exit_nicely(1);
01826 }
01827
01828 if (PQstatus(conn) == CONNECTION_BAD &&
01829 PQconnectionNeedsPassword(conn) &&
01830 password == NULL &&
01831 prompt_password != TRI_NO)
01832 {
01833 PQfinish(conn);
01834 password = simple_prompt("Password: ", 100, false);
01835 new_pass = true;
01836 }
01837 } while (new_pass);
01838
01839
01840 if (PQstatus(conn) == CONNECTION_BAD)
01841 {
01842 if (fail_on_error)
01843 {
01844 fprintf(stderr,
01845 _("%s: could not connect to database \"%s\": %s\n"),
01846 progname, dbname, PQerrorMessage(conn));
01847 exit_nicely(1);
01848 }
01849 else
01850 {
01851 PQfinish(conn);
01852
01853 free(keywords);
01854 free(values);
01855 PQconninfoFree(conn_opts);
01856
01857 return NULL;
01858 }
01859 }
01860
01861
01862
01863
01864
01865 connstr = constructConnStr(keywords, values);
01866
01867 free(keywords);
01868 free(values);
01869 PQconninfoFree(conn_opts);
01870
01871
01872 remoteversion_str = PQparameterStatus(conn, "server_version");
01873 if (!remoteversion_str)
01874 {
01875 fprintf(stderr, _("%s: could not get server version\n"), progname);
01876 exit_nicely(1);
01877 }
01878 server_version = PQserverVersion(conn);
01879 if (server_version == 0)
01880 {
01881 fprintf(stderr, _("%s: could not parse server version \"%s\"\n"),
01882 progname, remoteversion_str);
01883 exit_nicely(1);
01884 }
01885
01886 my_version = PG_VERSION_NUM;
01887
01888
01889
01890
01891
01892 if (my_version != server_version
01893 && (server_version < 70000 ||
01894 (server_version / 100) > (my_version / 100)))
01895 {
01896 fprintf(stderr, _("server version: %s; %s version: %s\n"),
01897 remoteversion_str, progname, PG_VERSION);
01898 fprintf(stderr, _("aborting because of server version mismatch\n"));
01899 exit_nicely(1);
01900 }
01901
01902
01903
01904
01905
01906 if (server_version >= 70300)
01907 executeCommand(conn, "SET search_path = pg_catalog");
01908
01909 return conn;
01910 }
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922 static char *
01923 constructConnStr(const char **keywords, const char **values)
01924 {
01925 PQExpBuffer buf = createPQExpBuffer();
01926 char *connstr;
01927 int i;
01928 bool firstkeyword = true;
01929
01930
01931 for (i = 0; keywords[i] != NULL; i++)
01932 {
01933 if (strcmp(keywords[i], "dbname") == 0 ||
01934 strcmp(keywords[i], "password") == 0 ||
01935 strcmp(keywords[i], "fallback_application_name") == 0)
01936 continue;
01937
01938 if (!firstkeyword)
01939 appendPQExpBufferChar(buf, ' ');
01940 firstkeyword = false;
01941 appendPQExpBuffer(buf, "%s=", keywords[i]);
01942 doConnStrQuoting(buf, values[i]);
01943 }
01944
01945 connstr = pg_strdup(buf->data);
01946 destroyPQExpBuffer(buf);
01947 return connstr;
01948 }
01949
01950
01951
01952
01953 static PGresult *
01954 executeQuery(PGconn *conn, const char *query)
01955 {
01956 PGresult *res;
01957
01958 if (verbose)
01959 fprintf(stderr, _("%s: executing %s\n"), progname, query);
01960
01961 res = PQexec(conn, query);
01962 if (!res ||
01963 PQresultStatus(res) != PGRES_TUPLES_OK)
01964 {
01965 fprintf(stderr, _("%s: query failed: %s"),
01966 progname, PQerrorMessage(conn));
01967 fprintf(stderr, _("%s: query was: %s\n"),
01968 progname, query);
01969 PQfinish(conn);
01970 exit_nicely(1);
01971 }
01972
01973 return res;
01974 }
01975
01976
01977
01978
01979 static void
01980 executeCommand(PGconn *conn, const char *query)
01981 {
01982 PGresult *res;
01983
01984 if (verbose)
01985 fprintf(stderr, _("%s: executing %s\n"), progname, query);
01986
01987 res = PQexec(conn, query);
01988 if (!res ||
01989 PQresultStatus(res) != PGRES_COMMAND_OK)
01990 {
01991 fprintf(stderr, _("%s: query failed: %s"),
01992 progname, PQerrorMessage(conn));
01993 fprintf(stderr, _("%s: query was: %s\n"),
01994 progname, query);
01995 PQfinish(conn);
01996 exit_nicely(1);
01997 }
01998
01999 PQclear(res);
02000 }
02001
02002
02003
02004
02005
02006 static void
02007 dumpTimestamp(char *msg)
02008 {
02009 char buf[256];
02010 time_t now = time(NULL);
02011
02012
02013
02014
02015
02016
02017
02018 if (strftime(buf, sizeof(buf),
02019 #ifndef WIN32
02020 "%Y-%m-%d %H:%M:%S %Z",
02021 #else
02022 "%Y-%m-%d %H:%M:%S",
02023 #endif
02024 localtime(&now)) != 0)
02025 fprintf(OPF, "-- %s %s\n\n", msg, buf);
02026 }
02027
02028
02029
02030
02031
02032
02033
02034 static void
02035 doConnStrQuoting(PQExpBuffer buf, const char *str)
02036 {
02037 const char *s;
02038 bool needquotes;
02039
02040
02041
02042
02043
02044 needquotes = false;
02045 for (s = str; *s; s++)
02046 {
02047 if (!((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') ||
02048 (*s >= '0' && *s <= '9') || *s == '_' || *s == '.'))
02049 {
02050 needquotes = true;
02051 break;
02052 }
02053 }
02054
02055 if (needquotes)
02056 {
02057 appendPQExpBufferChar(buf, '\'');
02058 while (*str)
02059 {
02060
02061 if (*str == '\'' || *str == '\\')
02062 appendPQExpBufferChar(buf, '\\');
02063
02064 appendPQExpBufferChar(buf, *str);
02065 str++;
02066 }
02067 appendPQExpBufferChar(buf, '\'');
02068 }
02069 else
02070 appendPQExpBufferStr(buf, str);
02071 }
02072
02073
02074
02075
02076
02077 static void
02078 doShellQuoting(PQExpBuffer buf, const char *str)
02079 {
02080 const char *p;
02081
02082 #ifndef WIN32
02083 appendPQExpBufferChar(buf, '\'');
02084 for (p = str; *p; p++)
02085 {
02086 if (*p == '\'')
02087 appendPQExpBuffer(buf, "'\"'\"'");
02088 else
02089 appendPQExpBufferChar(buf, *p);
02090 }
02091 appendPQExpBufferChar(buf, '\'');
02092 #else
02093
02094 appendPQExpBufferChar(buf, '"');
02095 for (p = str; *p; p++)
02096 {
02097 if (*p == '"')
02098 appendPQExpBuffer(buf, "\\\"");
02099 else
02100 appendPQExpBufferChar(buf, *p);
02101 }
02102 appendPQExpBufferChar(buf, '"');
02103 #endif
02104 }