PageRenderTime 60ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/src/bin/pg_dump/pg_dumpall.c

https://github.com/matheusoliveira/postgres
C | 2137 lines | 1544 code | 303 blank | 290 comment | 296 complexity | 791ce756aff3963e159c5fade6a45ab9 MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*-------------------------------------------------------------------------
  2. *
  3. * pg_dumpall.c
  4. *
  5. * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
  6. * Portions Copyright (c) 1994, Regents of the University of California
  7. *
  8. * pg_dumpall forces all pg_dump output to be text, since it also outputs
  9. * text into the same output stream.
  10. *
  11. * src/bin/pg_dump/pg_dumpall.c
  12. *
  13. *-------------------------------------------------------------------------
  14. */
  15. #include "postgres_fe.h"
  16. #include <time.h>
  17. #include <unistd.h>
  18. #ifdef ENABLE_NLS
  19. #include <locale.h>
  20. #endif
  21. #include "getopt_long.h"
  22. #include "dumputils.h"
  23. #include "pg_backup.h"
  24. /* version string we expect back from pg_dump */
  25. #define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
  26. static void help(void);
  27. static void dropRoles(PGconn *conn);
  28. static void dumpRoles(PGconn *conn);
  29. static void dumpRoleMembership(PGconn *conn);
  30. static void dumpGroups(PGconn *conn);
  31. static void dropTablespaces(PGconn *conn);
  32. static void dumpTablespaces(PGconn *conn);
  33. static void dropDBs(PGconn *conn);
  34. static void dumpCreateDB(PGconn *conn);
  35. static void dumpDatabaseConfig(PGconn *conn, const char *dbname);
  36. static void dumpUserConfig(PGconn *conn, const char *username);
  37. static void dumpDbRoleConfig(PGconn *conn);
  38. static void makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
  39. const char *type, const char *name, const char *type2,
  40. const char *name2);
  41. static void dumpDatabases(PGconn *conn);
  42. static void dumpTimestamp(char *msg);
  43. static void doShellQuoting(PQExpBuffer buf, const char *str);
  44. static void doConnStrQuoting(PQExpBuffer buf, const char *str);
  45. static int runPgDump(const char *dbname);
  46. static void buildShSecLabels(PGconn *conn, const char *catalog_name,
  47. uint32 objectId, PQExpBuffer buffer,
  48. const char *target, const char *objname);
  49. static PGconn *connectDatabase(const char *dbname, const char *connstr, const char *pghost, const char *pgport,
  50. const char *pguser, enum trivalue prompt_password, bool fail_on_error);
  51. static char *constructConnStr(const char **keywords, const char **values);
  52. static PGresult *executeQuery(PGconn *conn, const char *query);
  53. static void executeCommand(PGconn *conn, const char *query);
  54. static char pg_dump_bin[MAXPGPATH];
  55. static const char *progname;
  56. static PQExpBuffer pgdumpopts;
  57. static char *connstr = "";
  58. static bool skip_acls = false;
  59. static bool verbose = false;
  60. static int binary_upgrade = 0;
  61. static int column_inserts = 0;
  62. static int disable_dollar_quoting = 0;
  63. static int disable_triggers = 0;
  64. static int if_exists = 0;
  65. static int inserts = 0;
  66. static int no_tablespaces = 0;
  67. static int use_setsessauth = 0;
  68. static int no_security_labels = 0;
  69. static int no_unlogged_table_data = 0;
  70. static int server_version;
  71. static FILE *OPF;
  72. static char *filename = NULL;
  73. #define exit_nicely(code) exit(code)
  74. int
  75. main(int argc, char *argv[])
  76. {
  77. static struct option long_options[] = {
  78. {"data-only", no_argument, NULL, 'a'},
  79. {"clean", no_argument, NULL, 'c'},
  80. {"file", required_argument, NULL, 'f'},
  81. {"globals-only", no_argument, NULL, 'g'},
  82. {"host", required_argument, NULL, 'h'},
  83. {"ignore-version", no_argument, NULL, 'i'},
  84. {"dbname", required_argument, NULL, 'd'},
  85. {"database", required_argument, NULL, 'l'},
  86. {"oids", no_argument, NULL, 'o'},
  87. {"no-owner", no_argument, NULL, 'O'},
  88. {"port", required_argument, NULL, 'p'},
  89. {"roles-only", no_argument, NULL, 'r'},
  90. {"schema-only", no_argument, NULL, 's'},
  91. {"superuser", required_argument, NULL, 'S'},
  92. {"tablespaces-only", no_argument, NULL, 't'},
  93. {"username", required_argument, NULL, 'U'},
  94. {"verbose", no_argument, NULL, 'v'},
  95. {"no-password", no_argument, NULL, 'w'},
  96. {"password", no_argument, NULL, 'W'},
  97. {"no-privileges", no_argument, NULL, 'x'},
  98. {"no-acl", no_argument, NULL, 'x'},
  99. /*
  100. * the following options don't have an equivalent short option letter
  101. */
  102. {"attribute-inserts", no_argument, &column_inserts, 1},
  103. {"binary-upgrade", no_argument, &binary_upgrade, 1},
  104. {"column-inserts", no_argument, &column_inserts, 1},
  105. {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
  106. {"disable-triggers", no_argument, &disable_triggers, 1},
  107. {"if-exists", no_argument, &if_exists, 1},
  108. {"inserts", no_argument, &inserts, 1},
  109. {"lock-wait-timeout", required_argument, NULL, 2},
  110. {"no-tablespaces", no_argument, &no_tablespaces, 1},
  111. {"quote-all-identifiers", no_argument, &quote_all_identifiers, 1},
  112. {"role", required_argument, NULL, 3},
  113. {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
  114. {"no-security-labels", no_argument, &no_security_labels, 1},
  115. {"no-unlogged-table-data", no_argument, &no_unlogged_table_data, 1},
  116. {NULL, 0, NULL, 0}
  117. };
  118. char *pghost = NULL;
  119. char *pgport = NULL;
  120. char *pguser = NULL;
  121. char *pgdb = NULL;
  122. char *use_role = NULL;
  123. enum trivalue prompt_password = TRI_DEFAULT;
  124. bool data_only = false;
  125. bool globals_only = false;
  126. bool output_clean = false;
  127. bool roles_only = false;
  128. bool tablespaces_only = false;
  129. PGconn *conn;
  130. int encoding;
  131. const char *std_strings;
  132. int c,
  133. ret;
  134. int optindex;
  135. set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
  136. progname = get_progname(argv[0]);
  137. if (argc > 1)
  138. {
  139. if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
  140. {
  141. help();
  142. exit_nicely(0);
  143. }
  144. if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
  145. {
  146. puts("pg_dumpall (PostgreSQL) " PG_VERSION);
  147. exit_nicely(0);
  148. }
  149. }
  150. if ((ret = find_other_exec(argv[0], "pg_dump", PGDUMP_VERSIONSTR,
  151. pg_dump_bin)) < 0)
  152. {
  153. char full_path[MAXPGPATH];
  154. if (find_my_exec(argv[0], full_path) < 0)
  155. strlcpy(full_path, progname, sizeof(full_path));
  156. if (ret == -1)
  157. fprintf(stderr,
  158. _("The program \"pg_dump\" is needed by %s "
  159. "but was not found in the\n"
  160. "same directory as \"%s\".\n"
  161. "Check your installation.\n"),
  162. progname, full_path);
  163. else
  164. fprintf(stderr,
  165. _("The program \"pg_dump\" was found by \"%s\"\n"
  166. "but was not the same version as %s.\n"
  167. "Check your installation.\n"),
  168. full_path, progname);
  169. exit_nicely(1);
  170. }
  171. pgdumpopts = createPQExpBuffer();
  172. while ((c = getopt_long(argc, argv, "acd:f:gh:il:oOp:rsS:tU:vwWx", long_options, &optindex)) != -1)
  173. {
  174. switch (c)
  175. {
  176. case 'a':
  177. data_only = true;
  178. appendPQExpBufferStr(pgdumpopts, " -a");
  179. break;
  180. case 'c':
  181. output_clean = true;
  182. break;
  183. case 'd':
  184. connstr = pg_strdup(optarg);
  185. break;
  186. case 'f':
  187. filename = pg_strdup(optarg);
  188. appendPQExpBufferStr(pgdumpopts, " -f ");
  189. doShellQuoting(pgdumpopts, filename);
  190. break;
  191. case 'g':
  192. globals_only = true;
  193. break;
  194. case 'h':
  195. pghost = pg_strdup(optarg);
  196. break;
  197. case 'i':
  198. /* ignored, deprecated option */
  199. break;
  200. case 'l':
  201. pgdb = pg_strdup(optarg);
  202. break;
  203. case 'o':
  204. appendPQExpBufferStr(pgdumpopts, " -o");
  205. break;
  206. case 'O':
  207. appendPQExpBufferStr(pgdumpopts, " -O");
  208. break;
  209. case 'p':
  210. pgport = pg_strdup(optarg);
  211. break;
  212. case 'r':
  213. roles_only = true;
  214. break;
  215. case 's':
  216. appendPQExpBufferStr(pgdumpopts, " -s");
  217. break;
  218. case 'S':
  219. appendPQExpBufferStr(pgdumpopts, " -S ");
  220. doShellQuoting(pgdumpopts, optarg);
  221. break;
  222. case 't':
  223. tablespaces_only = true;
  224. break;
  225. case 'U':
  226. pguser = pg_strdup(optarg);
  227. break;
  228. case 'v':
  229. verbose = true;
  230. appendPQExpBufferStr(pgdumpopts, " -v");
  231. break;
  232. case 'w':
  233. prompt_password = TRI_NO;
  234. appendPQExpBufferStr(pgdumpopts, " -w");
  235. break;
  236. case 'W':
  237. prompt_password = TRI_YES;
  238. appendPQExpBufferStr(pgdumpopts, " -W");
  239. break;
  240. case 'x':
  241. skip_acls = true;
  242. appendPQExpBufferStr(pgdumpopts, " -x");
  243. break;
  244. case 0:
  245. break;
  246. case 2:
  247. appendPQExpBufferStr(pgdumpopts, " --lock-wait-timeout ");
  248. doShellQuoting(pgdumpopts, optarg);
  249. break;
  250. case 3:
  251. use_role = pg_strdup(optarg);
  252. appendPQExpBufferStr(pgdumpopts, " --role ");
  253. doShellQuoting(pgdumpopts, use_role);
  254. break;
  255. default:
  256. fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
  257. exit_nicely(1);
  258. }
  259. }
  260. /* Complain if any arguments remain */
  261. if (optind < argc)
  262. {
  263. fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
  264. progname, argv[optind]);
  265. fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
  266. progname);
  267. exit_nicely(1);
  268. }
  269. /* Make sure the user hasn't specified a mix of globals-only options */
  270. if (globals_only && roles_only)
  271. {
  272. fprintf(stderr, _("%s: options -g/--globals-only and -r/--roles-only cannot be used together\n"),
  273. progname);
  274. fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
  275. progname);
  276. exit_nicely(1);
  277. }
  278. if (globals_only && tablespaces_only)
  279. {
  280. fprintf(stderr, _("%s: options -g/--globals-only and -t/--tablespaces-only cannot be used together\n"),
  281. progname);
  282. fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
  283. progname);
  284. exit_nicely(1);
  285. }
  286. if (if_exists && !output_clean)
  287. {
  288. fprintf(stderr, _("%s: option --if-exists requires option -c/--clean\n"),
  289. progname);
  290. exit_nicely(1);
  291. }
  292. if (roles_only && tablespaces_only)
  293. {
  294. fprintf(stderr, _("%s: options -r/--roles-only and -t/--tablespaces-only cannot be used together\n"),
  295. progname);
  296. fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
  297. progname);
  298. exit_nicely(1);
  299. }
  300. /* Add long options to the pg_dump argument list */
  301. if (binary_upgrade)
  302. appendPQExpBufferStr(pgdumpopts, " --binary-upgrade");
  303. if (column_inserts)
  304. appendPQExpBufferStr(pgdumpopts, " --column-inserts");
  305. if (disable_dollar_quoting)
  306. appendPQExpBufferStr(pgdumpopts, " --disable-dollar-quoting");
  307. if (disable_triggers)
  308. appendPQExpBufferStr(pgdumpopts, " --disable-triggers");
  309. if (inserts)
  310. appendPQExpBufferStr(pgdumpopts, " --inserts");
  311. if (no_tablespaces)
  312. appendPQExpBufferStr(pgdumpopts, " --no-tablespaces");
  313. if (quote_all_identifiers)
  314. appendPQExpBufferStr(pgdumpopts, " --quote-all-identifiers");
  315. if (use_setsessauth)
  316. appendPQExpBufferStr(pgdumpopts, " --use-set-session-authorization");
  317. if (no_security_labels)
  318. appendPQExpBufferStr(pgdumpopts, " --no-security-labels");
  319. if (no_unlogged_table_data)
  320. appendPQExpBufferStr(pgdumpopts, " --no-unlogged-table-data");
  321. /*
  322. * If there was a database specified on the command line, use that,
  323. * otherwise try to connect to database "postgres", and failing that
  324. * "template1". "postgres" is the preferred choice for 8.1 and later
  325. * servers, but it usually will not exist on older ones.
  326. */
  327. if (pgdb)
  328. {
  329. conn = connectDatabase(pgdb, connstr, pghost, pgport, pguser,
  330. prompt_password, false);
  331. if (!conn)
  332. {
  333. fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
  334. progname, pgdb);
  335. exit_nicely(1);
  336. }
  337. }
  338. else
  339. {
  340. conn = connectDatabase("postgres", connstr, pghost, pgport, pguser,
  341. prompt_password, false);
  342. if (!conn)
  343. conn = connectDatabase("template1", connstr, pghost, pgport, pguser,
  344. prompt_password, true);
  345. if (!conn)
  346. {
  347. fprintf(stderr, _("%s: could not connect to databases \"postgres\" or \"template1\"\n"
  348. "Please specify an alternative database.\n"),
  349. progname);
  350. fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
  351. progname);
  352. exit_nicely(1);
  353. }
  354. }
  355. /*
  356. * Open the output file if required, otherwise use stdout
  357. */
  358. if (filename)
  359. {
  360. OPF = fopen(filename, PG_BINARY_W);
  361. if (!OPF)
  362. {
  363. fprintf(stderr, _("%s: could not open the output file \"%s\": %s\n"),
  364. progname, filename, strerror(errno));
  365. exit_nicely(1);
  366. }
  367. }
  368. else
  369. OPF = stdout;
  370. /*
  371. * Get the active encoding and the standard_conforming_strings setting, so
  372. * we know how to escape strings.
  373. */
  374. encoding = PQclientEncoding(conn);
  375. std_strings = PQparameterStatus(conn, "standard_conforming_strings");
  376. if (!std_strings)
  377. std_strings = "off";
  378. /* Set the role if requested */
  379. if (use_role && server_version >= 80100)
  380. {
  381. PQExpBuffer query = createPQExpBuffer();
  382. appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
  383. executeCommand(conn, query->data);
  384. destroyPQExpBuffer(query);
  385. }
  386. /* Force quoting of all identifiers if requested. */
  387. if (quote_all_identifiers && server_version >= 90100)
  388. executeCommand(conn, "SET quote_all_identifiers = true");
  389. fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n");
  390. if (verbose)
  391. dumpTimestamp("Started on");
  392. /*
  393. * We used to emit \connect postgres here, but that served no purpose
  394. * other than to break things for installations without a postgres
  395. * database. Everything we're restoring here is a global, so whichever
  396. * database we're connected to at the moment is fine.
  397. */
  398. /* Restore will need to write to the target cluster */
  399. fprintf(OPF, "SET default_transaction_read_only = off;\n\n");
  400. /* Replicate encoding and std_strings in output */
  401. fprintf(OPF, "SET client_encoding = '%s';\n",
  402. pg_encoding_to_char(encoding));
  403. fprintf(OPF, "SET standard_conforming_strings = %s;\n", std_strings);
  404. if (strcmp(std_strings, "off") == 0)
  405. fprintf(OPF, "SET escape_string_warning = off;\n");
  406. fprintf(OPF, "\n");
  407. if (!data_only)
  408. {
  409. /*
  410. * If asked to --clean, do that first. We can avoid detailed
  411. * dependency analysis because databases never depend on each other,
  412. * and tablespaces never depend on each other. Roles could have
  413. * grants to each other, but DROP ROLE will clean those up silently.
  414. */
  415. if (output_clean)
  416. {
  417. if (!globals_only && !roles_only && !tablespaces_only)
  418. dropDBs(conn);
  419. if (!roles_only && !no_tablespaces)
  420. {
  421. if (server_version >= 80000)
  422. dropTablespaces(conn);
  423. }
  424. if (!tablespaces_only)
  425. dropRoles(conn);
  426. }
  427. /*
  428. * Now create objects as requested. Be careful that option logic here
  429. * is the same as for drops above.
  430. */
  431. if (!tablespaces_only)
  432. {
  433. /* Dump roles (users) */
  434. dumpRoles(conn);
  435. /* Dump role memberships --- need different method for pre-8.1 */
  436. if (server_version >= 80100)
  437. dumpRoleMembership(conn);
  438. else
  439. dumpGroups(conn);
  440. }
  441. if (!roles_only && !no_tablespaces)
  442. {
  443. /* Dump tablespaces */
  444. if (server_version >= 80000)
  445. dumpTablespaces(conn);
  446. }
  447. /* Dump CREATE DATABASE commands */
  448. if (binary_upgrade || (!globals_only && !roles_only && !tablespaces_only))
  449. dumpCreateDB(conn);
  450. /* Dump role/database settings */
  451. if (!tablespaces_only && !roles_only)
  452. {
  453. if (server_version >= 90000)
  454. dumpDbRoleConfig(conn);
  455. }
  456. }
  457. if (!globals_only && !roles_only && !tablespaces_only)
  458. dumpDatabases(conn);
  459. PQfinish(conn);
  460. if (verbose)
  461. dumpTimestamp("Completed on");
  462. fprintf(OPF, "--\n-- PostgreSQL database cluster dump complete\n--\n\n");
  463. if (filename)
  464. fclose(OPF);
  465. exit_nicely(0);
  466. }
  467. static void
  468. help(void)
  469. {
  470. printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname);
  471. printf(_("Usage:\n"));
  472. printf(_(" %s [OPTION]...\n"), progname);
  473. printf(_("\nGeneral options:\n"));
  474. printf(_(" -f, --file=FILENAME output file name\n"));
  475. printf(_(" -V, --version output version information, then exit\n"));
  476. printf(_(" --lock-wait-timeout=TIMEOUT fail after waiting TIMEOUT for a table lock\n"));
  477. printf(_(" -?, --help show this help, then exit\n"));
  478. printf(_("\nOptions controlling the output content:\n"));
  479. printf(_(" -a, --data-only dump only the data, not the schema\n"));
  480. printf(_(" -c, --clean clean (drop) databases before recreating\n"));
  481. printf(_(" -g, --globals-only dump only global objects, no databases\n"));
  482. printf(_(" -o, --oids include OIDs in dump\n"));
  483. printf(_(" -O, --no-owner skip restoration of object ownership\n"));
  484. printf(_(" -r, --roles-only dump only roles, no databases or tablespaces\n"));
  485. printf(_(" -s, --schema-only dump only the schema, no data\n"));
  486. printf(_(" -S, --superuser=NAME superuser user name to use in the dump\n"));
  487. printf(_(" -t, --tablespaces-only dump only tablespaces, no databases or roles\n"));
  488. printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
  489. printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
  490. printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
  491. printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
  492. printf(_(" --disable-triggers disable triggers during data-only restore\n"));
  493. printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
  494. printf(_(" --inserts dump data as INSERT commands, rather than COPY\n"));
  495. printf(_(" --no-security-labels do not dump security label assignments\n"));
  496. printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
  497. printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
  498. printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
  499. printf(_(" --use-set-session-authorization\n"
  500. " use SET SESSION AUTHORIZATION commands instead of\n"
  501. " ALTER OWNER commands to set ownership\n"));
  502. printf(_("\nConnection options:\n"));
  503. printf(_(" -d, --dbname=CONNSTR connect using connection string\n"));
  504. printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
  505. printf(_(" -l, --database=DBNAME alternative default database\n"));
  506. printf(_(" -p, --port=PORT database server port number\n"));
  507. printf(_(" -U, --username=NAME connect as specified database user\n"));
  508. printf(_(" -w, --no-password never prompt for password\n"));
  509. printf(_(" -W, --password force password prompt (should happen automatically)\n"));
  510. printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
  511. printf(_("\nIf -f/--file is not used, then the SQL script will be written to the standard\n"
  512. "output.\n\n"));
  513. printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
  514. }
  515. /*
  516. * Drop roles
  517. */
  518. static void
  519. dropRoles(PGconn *conn)
  520. {
  521. PGresult *res;
  522. int i_rolname;
  523. int i;
  524. if (server_version >= 80100)
  525. res = executeQuery(conn,
  526. "SELECT rolname "
  527. "FROM pg_authid "
  528. "ORDER BY 1");
  529. else
  530. res = executeQuery(conn,
  531. "SELECT usename as rolname "
  532. "FROM pg_shadow "
  533. "UNION "
  534. "SELECT groname as rolname "
  535. "FROM pg_group "
  536. "ORDER BY 1");
  537. i_rolname = PQfnumber(res, "rolname");
  538. if (PQntuples(res) > 0)
  539. fprintf(OPF, "--\n-- Drop roles\n--\n\n");
  540. for (i = 0; i < PQntuples(res); i++)
  541. {
  542. const char *rolename;
  543. rolename = PQgetvalue(res, i, i_rolname);
  544. fprintf(OPF, "DROP ROLE %s%s;\n",
  545. if_exists ? "IF EXISTS " : "",
  546. fmtId(rolename));
  547. }
  548. PQclear(res);
  549. fprintf(OPF, "\n\n");
  550. }
  551. /*
  552. * Dump roles
  553. */
  554. static void
  555. dumpRoles(PGconn *conn)
  556. {
  557. PQExpBuffer buf = createPQExpBuffer();
  558. PGresult *res;
  559. int i_oid,
  560. i_rolname,
  561. i_rolsuper,
  562. i_rolinherit,
  563. i_rolcreaterole,
  564. i_rolcreatedb,
  565. i_rolcanlogin,
  566. i_rolconnlimit,
  567. i_rolpassword,
  568. i_rolvaliduntil,
  569. i_rolreplication,
  570. i_rolcomment,
  571. i_is_current_user;
  572. int i;
  573. /* note: rolconfig is dumped later */
  574. if (server_version >= 90100)
  575. printfPQExpBuffer(buf,
  576. "SELECT oid, rolname, rolsuper, rolinherit, "
  577. "rolcreaterole, rolcreatedb, "
  578. "rolcanlogin, rolconnlimit, rolpassword, "
  579. "rolvaliduntil, rolreplication, "
  580. "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment, "
  581. "rolname = current_user AS is_current_user "
  582. "FROM pg_authid "
  583. "ORDER BY 2");
  584. else if (server_version >= 80200)
  585. printfPQExpBuffer(buf,
  586. "SELECT oid, rolname, rolsuper, rolinherit, "
  587. "rolcreaterole, rolcreatedb, "
  588. "rolcanlogin, rolconnlimit, rolpassword, "
  589. "rolvaliduntil, false as rolreplication, "
  590. "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment, "
  591. "rolname = current_user AS is_current_user "
  592. "FROM pg_authid "
  593. "ORDER BY 2");
  594. else if (server_version >= 80100)
  595. printfPQExpBuffer(buf,
  596. "SELECT oid, rolname, rolsuper, rolinherit, "
  597. "rolcreaterole, rolcreatedb, "
  598. "rolcanlogin, rolconnlimit, rolpassword, "
  599. "rolvaliduntil, false as rolreplication, "
  600. "null as rolcomment, "
  601. "rolname = current_user AS is_current_user "
  602. "FROM pg_authid "
  603. "ORDER BY 2");
  604. else
  605. printfPQExpBuffer(buf,
  606. "SELECT 0, usename as rolname, "
  607. "usesuper as rolsuper, "
  608. "true as rolinherit, "
  609. "usesuper as rolcreaterole, "
  610. "usecreatedb as rolcreatedb, "
  611. "true as rolcanlogin, "
  612. "-1 as rolconnlimit, "
  613. "passwd as rolpassword, "
  614. "valuntil as rolvaliduntil, "
  615. "false as rolreplication, "
  616. "null as rolcomment, "
  617. "usename = current_user AS is_current_user "
  618. "FROM pg_shadow "
  619. "UNION ALL "
  620. "SELECT 0, groname as rolname, "
  621. "false as rolsuper, "
  622. "true as rolinherit, "
  623. "false as rolcreaterole, "
  624. "false as rolcreatedb, "
  625. "false as rolcanlogin, "
  626. "-1 as rolconnlimit, "
  627. "null::text as rolpassword, "
  628. "null::abstime as rolvaliduntil, "
  629. "false as rolreplication, "
  630. "null as rolcomment, false "
  631. "FROM pg_group "
  632. "WHERE NOT EXISTS (SELECT 1 FROM pg_shadow "
  633. " WHERE usename = groname) "
  634. "ORDER BY 2");
  635. res = executeQuery(conn, buf->data);
  636. i_oid = PQfnumber(res, "oid");
  637. i_rolname = PQfnumber(res, "rolname");
  638. i_rolsuper = PQfnumber(res, "rolsuper");
  639. i_rolinherit = PQfnumber(res, "rolinherit");
  640. i_rolcreaterole = PQfnumber(res, "rolcreaterole");
  641. i_rolcreatedb = PQfnumber(res, "rolcreatedb");
  642. i_rolcanlogin = PQfnumber(res, "rolcanlogin");
  643. i_rolconnlimit = PQfnumber(res, "rolconnlimit");
  644. i_rolpassword = PQfnumber(res, "rolpassword");
  645. i_rolvaliduntil = PQfnumber(res, "rolvaliduntil");
  646. i_rolreplication = PQfnumber(res, "rolreplication");
  647. i_rolcomment = PQfnumber(res, "rolcomment");
  648. i_is_current_user = PQfnumber(res, "is_current_user");
  649. if (PQntuples(res) > 0)
  650. fprintf(OPF, "--\n-- Roles\n--\n\n");
  651. for (i = 0; i < PQntuples(res); i++)
  652. {
  653. const char *rolename;
  654. Oid auth_oid;
  655. auth_oid = atooid(PQgetvalue(res, i, i_oid));
  656. rolename = PQgetvalue(res, i, i_rolname);
  657. resetPQExpBuffer(buf);
  658. if (binary_upgrade)
  659. {
  660. appendPQExpBufferStr(buf, "\n-- For binary upgrade, must preserve pg_authid.oid\n");
  661. appendPQExpBuffer(buf,
  662. "SELECT binary_upgrade.set_next_pg_authid_oid('%u'::pg_catalog.oid);\n\n",
  663. auth_oid);
  664. }
  665. /*
  666. * We dump CREATE ROLE followed by ALTER ROLE to ensure that the role
  667. * will acquire the right properties even if it already exists (ie, it
  668. * won't hurt for the CREATE to fail). This is particularly important
  669. * for the role we are connected as, since even with --clean we will
  670. * have failed to drop it. binary_upgrade cannot generate any errors,
  671. * so we assume the current role is already created.
  672. */
  673. if (!binary_upgrade ||
  674. strcmp(PQgetvalue(res, i, i_is_current_user), "f") == 0)
  675. appendPQExpBuffer(buf, "CREATE ROLE %s;\n", fmtId(rolename));
  676. appendPQExpBuffer(buf, "ALTER ROLE %s WITH", fmtId(rolename));
  677. if (strcmp(PQgetvalue(res, i, i_rolsuper), "t") == 0)
  678. appendPQExpBufferStr(buf, " SUPERUSER");
  679. else
  680. appendPQExpBufferStr(buf, " NOSUPERUSER");
  681. if (strcmp(PQgetvalue(res, i, i_rolinherit), "t") == 0)
  682. appendPQExpBufferStr(buf, " INHERIT");
  683. else
  684. appendPQExpBufferStr(buf, " NOINHERIT");
  685. if (strcmp(PQgetvalue(res, i, i_rolcreaterole), "t") == 0)
  686. appendPQExpBufferStr(buf, " CREATEROLE");
  687. else
  688. appendPQExpBufferStr(buf, " NOCREATEROLE");
  689. if (strcmp(PQgetvalue(res, i, i_rolcreatedb), "t") == 0)
  690. appendPQExpBufferStr(buf, " CREATEDB");
  691. else
  692. appendPQExpBufferStr(buf, " NOCREATEDB");
  693. if (strcmp(PQgetvalue(res, i, i_rolcanlogin), "t") == 0)
  694. appendPQExpBufferStr(buf, " LOGIN");
  695. else
  696. appendPQExpBufferStr(buf, " NOLOGIN");
  697. if (strcmp(PQgetvalue(res, i, i_rolreplication), "t") == 0)
  698. appendPQExpBufferStr(buf, " REPLICATION");
  699. else
  700. appendPQExpBufferStr(buf, " NOREPLICATION");
  701. if (strcmp(PQgetvalue(res, i, i_rolconnlimit), "-1") != 0)
  702. appendPQExpBuffer(buf, " CONNECTION LIMIT %s",
  703. PQgetvalue(res, i, i_rolconnlimit));
  704. if (!PQgetisnull(res, i, i_rolpassword))
  705. {
  706. appendPQExpBufferStr(buf, " PASSWORD ");
  707. appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolpassword), conn);
  708. }
  709. if (!PQgetisnull(res, i, i_rolvaliduntil))
  710. appendPQExpBuffer(buf, " VALID UNTIL '%s'",
  711. PQgetvalue(res, i, i_rolvaliduntil));
  712. appendPQExpBufferStr(buf, ";\n");
  713. if (!PQgetisnull(res, i, i_rolcomment))
  714. {
  715. appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
  716. appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolcomment), conn);
  717. appendPQExpBufferStr(buf, ";\n");
  718. }
  719. if (!no_security_labels && server_version >= 90200)
  720. buildShSecLabels(conn, "pg_authid", auth_oid,
  721. buf, "ROLE", rolename);
  722. fprintf(OPF, "%s", buf->data);
  723. }
  724. /*
  725. * Dump configuration settings for roles after all roles have been dumped.
  726. * We do it this way because config settings for roles could mention the
  727. * names of other roles.
  728. */
  729. if (server_version >= 70300)
  730. for (i = 0; i < PQntuples(res); i++)
  731. dumpUserConfig(conn, PQgetvalue(res, i, i_rolname));
  732. PQclear(res);
  733. fprintf(OPF, "\n\n");
  734. destroyPQExpBuffer(buf);
  735. }
  736. /*
  737. * Dump role memberships. This code is used for 8.1 and later servers.
  738. *
  739. * Note: we expect dumpRoles already created all the roles, but there is
  740. * no membership yet.
  741. */
  742. static void
  743. dumpRoleMembership(PGconn *conn)
  744. {
  745. PGresult *res;
  746. int i;
  747. res = executeQuery(conn, "SELECT ur.rolname AS roleid, "
  748. "um.rolname AS member, "
  749. "a.admin_option, "
  750. "ug.rolname AS grantor "
  751. "FROM pg_auth_members a "
  752. "LEFT JOIN pg_authid ur on ur.oid = a.roleid "
  753. "LEFT JOIN pg_authid um on um.oid = a.member "
  754. "LEFT JOIN pg_authid ug on ug.oid = a.grantor "
  755. "ORDER BY 1,2,3");
  756. if (PQntuples(res) > 0)
  757. fprintf(OPF, "--\n-- Role memberships\n--\n\n");
  758. for (i = 0; i < PQntuples(res); i++)
  759. {
  760. char *roleid = PQgetvalue(res, i, 0);
  761. char *member = PQgetvalue(res, i, 1);
  762. char *option = PQgetvalue(res, i, 2);
  763. fprintf(OPF, "GRANT %s", fmtId(roleid));
  764. fprintf(OPF, " TO %s", fmtId(member));
  765. if (*option == 't')
  766. fprintf(OPF, " WITH ADMIN OPTION");
  767. /*
  768. * We don't track the grantor very carefully in the backend, so cope
  769. * with the possibility that it has been dropped.
  770. */
  771. if (!PQgetisnull(res, i, 3))
  772. {
  773. char *grantor = PQgetvalue(res, i, 3);
  774. fprintf(OPF, " GRANTED BY %s", fmtId(grantor));
  775. }
  776. fprintf(OPF, ";\n");
  777. }
  778. PQclear(res);
  779. fprintf(OPF, "\n\n");
  780. }
  781. /*
  782. * Dump group memberships from a pre-8.1 server. It's annoying that we
  783. * can't share any useful amount of code with the post-8.1 case, but
  784. * the catalog representations are too different.
  785. *
  786. * Note: we expect dumpRoles already created all the roles, but there is
  787. * no membership yet.
  788. */
  789. static void
  790. dumpGroups(PGconn *conn)
  791. {
  792. PQExpBuffer buf = createPQExpBuffer();
  793. PGresult *res;
  794. int i;
  795. res = executeQuery(conn,
  796. "SELECT groname, grolist FROM pg_group ORDER BY 1");
  797. if (PQntuples(res) > 0)
  798. fprintf(OPF, "--\n-- Role memberships\n--\n\n");
  799. for (i = 0; i < PQntuples(res); i++)
  800. {
  801. char *groname = PQgetvalue(res, i, 0);
  802. char *grolist = PQgetvalue(res, i, 1);
  803. PGresult *res2;
  804. int j;
  805. /*
  806. * Array representation is {1,2,3} ... convert to (1,2,3)
  807. */
  808. if (strlen(grolist) < 3)
  809. continue;
  810. grolist = pg_strdup(grolist);
  811. grolist[0] = '(';
  812. grolist[strlen(grolist) - 1] = ')';
  813. printfPQExpBuffer(buf,
  814. "SELECT usename FROM pg_shadow "
  815. "WHERE usesysid IN %s ORDER BY 1",
  816. grolist);
  817. free(grolist);
  818. res2 = executeQuery(conn, buf->data);
  819. for (j = 0; j < PQntuples(res2); j++)
  820. {
  821. char *usename = PQgetvalue(res2, j, 0);
  822. /*
  823. * Don't try to grant a role to itself; can happen if old
  824. * installation has identically named user and group.
  825. */
  826. if (strcmp(groname, usename) == 0)
  827. continue;
  828. fprintf(OPF, "GRANT %s", fmtId(groname));
  829. fprintf(OPF, " TO %s;\n", fmtId(usename));
  830. }
  831. PQclear(res2);
  832. }
  833. PQclear(res);
  834. destroyPQExpBuffer(buf);
  835. fprintf(OPF, "\n\n");
  836. }
  837. /*
  838. * Drop tablespaces.
  839. */
  840. static void
  841. dropTablespaces(PGconn *conn)
  842. {
  843. PGresult *res;
  844. int i;
  845. /*
  846. * Get all tablespaces except built-in ones (which we assume are named
  847. * pg_xxx)
  848. */
  849. res = executeQuery(conn, "SELECT spcname "
  850. "FROM pg_catalog.pg_tablespace "
  851. "WHERE spcname !~ '^pg_' "
  852. "ORDER BY 1");
  853. if (PQntuples(res) > 0)
  854. fprintf(OPF, "--\n-- Drop tablespaces\n--\n\n");
  855. for (i = 0; i < PQntuples(res); i++)
  856. {
  857. char *spcname = PQgetvalue(res, i, 0);
  858. fprintf(OPF, "DROP TABLESPACE %s%s;\n",
  859. if_exists ? "IF EXISTS " : "",
  860. fmtId(spcname));
  861. }
  862. PQclear(res);
  863. fprintf(OPF, "\n\n");
  864. }
  865. /*
  866. * Dump tablespaces.
  867. */
  868. static void
  869. dumpTablespaces(PGconn *conn)
  870. {
  871. PGresult *res;
  872. int i;
  873. /*
  874. * Get all tablespaces except built-in ones (which we assume are named
  875. * pg_xxx)
  876. */
  877. if (server_version >= 90200)
  878. res = executeQuery(conn, "SELECT oid, spcname, "
  879. "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
  880. "pg_catalog.pg_tablespace_location(oid), spcacl, "
  881. "array_to_string(spcoptions, ', '),"
  882. "pg_catalog.shobj_description(oid, 'pg_tablespace') "
  883. "FROM pg_catalog.pg_tablespace "
  884. "WHERE spcname !~ '^pg_' "
  885. "ORDER BY 1");
  886. else if (server_version >= 90000)
  887. res = executeQuery(conn, "SELECT oid, spcname, "
  888. "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
  889. "spclocation, spcacl, "
  890. "array_to_string(spcoptions, ', '),"
  891. "pg_catalog.shobj_description(oid, 'pg_tablespace') "
  892. "FROM pg_catalog.pg_tablespace "
  893. "WHERE spcname !~ '^pg_' "
  894. "ORDER BY 1");
  895. else if (server_version >= 80200)
  896. res = executeQuery(conn, "SELECT oid, spcname, "
  897. "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
  898. "spclocation, spcacl, null, "
  899. "pg_catalog.shobj_description(oid, 'pg_tablespace') "
  900. "FROM pg_catalog.pg_tablespace "
  901. "WHERE spcname !~ '^pg_' "
  902. "ORDER BY 1");
  903. else
  904. res = executeQuery(conn, "SELECT oid, spcname, "
  905. "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
  906. "spclocation, spcacl, "
  907. "null, null "
  908. "FROM pg_catalog.pg_tablespace "
  909. "WHERE spcname !~ '^pg_' "
  910. "ORDER BY 1");
  911. if (PQntuples(res) > 0)
  912. fprintf(OPF, "--\n-- Tablespaces\n--\n\n");
  913. for (i = 0; i < PQntuples(res); i++)
  914. {
  915. PQExpBuffer buf = createPQExpBuffer();
  916. uint32 spcoid = atooid(PQgetvalue(res, i, 0));
  917. char *spcname = PQgetvalue(res, i, 1);
  918. char *spcowner = PQgetvalue(res, i, 2);
  919. char *spclocation = PQgetvalue(res, i, 3);
  920. char *spcacl = PQgetvalue(res, i, 4);
  921. char *spcoptions = PQgetvalue(res, i, 5);
  922. char *spccomment = PQgetvalue(res, i, 6);
  923. char *fspcname;
  924. /* needed for buildACLCommands() */
  925. fspcname = pg_strdup(fmtId(spcname));
  926. appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname);
  927. appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
  928. appendPQExpBufferStr(buf, " LOCATION ");
  929. appendStringLiteralConn(buf, spclocation, conn);
  930. appendPQExpBufferStr(buf, ";\n");
  931. if (spcoptions && spcoptions[0] != '\0')
  932. appendPQExpBuffer(buf, "ALTER TABLESPACE %s SET (%s);\n",
  933. fspcname, spcoptions);
  934. if (!skip_acls &&
  935. !buildACLCommands(fspcname, NULL, "TABLESPACE", spcacl, spcowner,
  936. "", server_version, buf))
  937. {
  938. fprintf(stderr, _("%s: could not parse ACL list (%s) for tablespace \"%s\"\n"),
  939. progname, spcacl, fspcname);
  940. PQfinish(conn);
  941. exit_nicely(1);
  942. }
  943. if (spccomment && strlen(spccomment))
  944. {
  945. appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
  946. appendStringLiteralConn(buf, spccomment, conn);
  947. appendPQExpBufferStr(buf, ";\n");
  948. }
  949. if (!no_security_labels && server_version >= 90200)
  950. buildShSecLabels(conn, "pg_tablespace", spcoid,
  951. buf, "TABLESPACE", fspcname);
  952. fprintf(OPF, "%s", buf->data);
  953. free(fspcname);
  954. destroyPQExpBuffer(buf);
  955. }
  956. PQclear(res);
  957. fprintf(OPF, "\n\n");
  958. }
  959. /*
  960. * Dump commands to drop each database.
  961. *
  962. * This should match the set of databases targeted by dumpCreateDB().
  963. */
  964. static void
  965. dropDBs(PGconn *conn)
  966. {
  967. PGresult *res;
  968. int i;
  969. if (server_version >= 70100)
  970. res = executeQuery(conn,
  971. "SELECT datname "
  972. "FROM pg_database d "
  973. "WHERE datallowconn ORDER BY 1");
  974. else
  975. res = executeQuery(conn,
  976. "SELECT datname "
  977. "FROM pg_database d "
  978. "ORDER BY 1");
  979. if (PQntuples(res) > 0)
  980. fprintf(OPF, "--\n-- Drop databases\n--\n\n");
  981. for (i = 0; i < PQntuples(res); i++)
  982. {
  983. char *dbname = PQgetvalue(res, i, 0);
  984. /*
  985. * Skip "template1" and "postgres"; the restore script is almost
  986. * certainly going to be run in one or the other, and we don't know
  987. * which. This must agree with dumpCreateDB's choices!
  988. */
  989. if (strcmp(dbname, "template1") != 0 &&
  990. strcmp(dbname, "postgres") != 0)
  991. {
  992. fprintf(OPF, "DROP DATABASE %s%s;\n",
  993. if_exists ? "IF EXISTS " : "",
  994. fmtId(dbname));
  995. }
  996. }
  997. PQclear(res);
  998. fprintf(OPF, "\n\n");
  999. }
  1000. /*
  1001. * Dump commands to create each database.
  1002. *
  1003. * To minimize the number of reconnections (and possibly ensuing
  1004. * password prompts) required by the output script, we emit all CREATE
  1005. * DATABASE commands during the initial phase of the script, and then
  1006. * run pg_dump for each database to dump the contents of that
  1007. * database. We skip databases marked not datallowconn, since we'd be
  1008. * unable to connect to them anyway (and besides, we don't want to
  1009. * dump template0).
  1010. */
  1011. static void
  1012. dumpCreateDB(PGconn *conn)
  1013. {
  1014. PQExpBuffer buf = createPQExpBuffer();
  1015. char *default_encoding = NULL;
  1016. char *default_collate = NULL;
  1017. char *default_ctype = NULL;
  1018. PGresult *res;
  1019. int i;
  1020. fprintf(OPF, "--\n-- Database creation\n--\n\n");
  1021. /*
  1022. * First, get the installation's default encoding and locale information.
  1023. * We will dump encoding and locale specifications in the CREATE DATABASE
  1024. * commands for just those databases with values different from defaults.
  1025. *
  1026. * We consider template0's encoding and locale (or, pre-7.1, template1's)
  1027. * to define the installation default. Pre-8.4 installations do not have
  1028. * per-database locale settings; for them, every database must necessarily
  1029. * be using the installation default, so there's no need to do anything
  1030. * (which is good, since in very old versions there is no good way to find
  1031. * out what the installation locale is anyway...)
  1032. */
  1033. if (server_version >= 80400)
  1034. res = executeQuery(conn,
  1035. "SELECT pg_encoding_to_char(encoding), "
  1036. "datcollate, datctype "
  1037. "FROM pg_database "
  1038. "WHERE datname = 'template0'");
  1039. else if (server_version >= 70100)
  1040. res = executeQuery(conn,
  1041. "SELECT pg_encoding_to_char(encoding), "
  1042. "null::text AS datcollate, null::text AS datctype "
  1043. "FROM pg_database "
  1044. "WHERE datname = 'template0'");
  1045. else
  1046. res = executeQuery(conn,
  1047. "SELECT pg_encoding_to_char(encoding), "
  1048. "null::text AS datcollate, null::text AS datctype "
  1049. "FROM pg_database "
  1050. "WHERE datname = 'template1'");
  1051. /* If for some reason the template DB isn't there, treat as unknown */
  1052. if (PQntuples(res) > 0)
  1053. {
  1054. if (!PQgetisnull(res, 0, 0))
  1055. default_encoding = pg_strdup(PQgetvalue(res, 0, 0));
  1056. if (!PQgetisnull(res, 0, 1))
  1057. default_collate = pg_strdup(PQgetvalue(res, 0, 1));
  1058. if (!PQgetisnull(res, 0, 2))
  1059. default_ctype = pg_strdup(PQgetvalue(res, 0, 2));
  1060. }
  1061. PQclear(res);
  1062. /* Now collect all the information about databases to dump */
  1063. if (server_version >= 90300)
  1064. res = executeQuery(conn,
  1065. "SELECT datname, "
  1066. "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
  1067. "pg_encoding_to_char(d.encoding), "
  1068. "datcollate, datctype, datfrozenxid, datminmxid, "
  1069. "datistemplate, datacl, datconnlimit, "
  1070. "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
  1071. "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
  1072. "WHERE datallowconn ORDER BY 1");
  1073. else if (server_version >= 80400)
  1074. res = executeQuery(conn,
  1075. "SELECT datname, "
  1076. "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
  1077. "pg_encoding_to_char(d.encoding), "
  1078. "datcollate, datctype, datfrozenxid, 0 AS datminmxid, "
  1079. "datistemplate, datacl, datconnlimit, "
  1080. "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
  1081. "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
  1082. "WHERE datallowconn ORDER BY 1");
  1083. else if (server_version >= 80100)
  1084. res = executeQuery(conn,
  1085. "SELECT datname, "
  1086. "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
  1087. "pg_encoding_to_char(d.encoding), "
  1088. "null::text AS datcollate, null::text AS datctype, datfrozenxid, 0 AS datminmxid, "
  1089. "datistemplate, datacl, datconnlimit, "
  1090. "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
  1091. "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
  1092. "WHERE datallowconn ORDER BY 1");
  1093. else if (server_version >= 80000)
  1094. res = executeQuery(conn,
  1095. "SELECT datname, "
  1096. "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
  1097. "pg_encoding_to_char(d.encoding), "
  1098. "null::text AS datcollate, null::text AS datctype, datfrozenxid, 0 AS datminmxid, "
  1099. "datistemplate, datacl, -1 as datconnlimit, "
  1100. "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
  1101. "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
  1102. "WHERE datallowconn ORDER BY 1");
  1103. else if (server_version >= 70300)
  1104. res = executeQuery(conn,
  1105. "SELECT datname, "
  1106. "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
  1107. "pg_encoding_to_char(d.encoding), "
  1108. "null::text AS datcollate, null::text AS datctype, datfrozenxid, 0 AS datminmxid, "
  1109. "datistemplate, datacl, -1 as datconnlimit, "
  1110. "'pg_default' AS dattablespace "
  1111. "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
  1112. "WHERE datallowconn ORDER BY 1");
  1113. else if (server_version >= 70100)
  1114. res = executeQuery(conn,
  1115. "SELECT datname, "
  1116. "coalesce("
  1117. "(select usename from pg_shadow where usesysid=datdba), "
  1118. "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
  1119. "pg_encoding_to_char(d.encoding), "
  1120. "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, 0 AS datminmxid, "
  1121. "datistemplate, '' as datacl, -1 as datconnlimit, "
  1122. "'pg_default' AS dattablespace "
  1123. "FROM pg_database d "
  1124. "WHERE datallowconn ORDER BY 1");
  1125. else
  1126. {
  1127. /*
  1128. * Note: 7.0 fails to cope with sub-select in COALESCE, so just deal
  1129. * with getting a NULL by not printing any OWNER clause.
  1130. */
  1131. res = executeQuery(conn,
  1132. "SELECT datname, "
  1133. "(select usename from pg_shadow where usesysid=datdba), "
  1134. "pg_encoding_to_char(d.encoding), "
  1135. "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, 0 AS datminmxid, "
  1136. "'f' as datistemplate, "
  1137. "'' as datacl, -1 as datconnlimit, "
  1138. "'pg_default' AS dattablespace "
  1139. "FROM pg_database d "
  1140. "ORDER BY 1");
  1141. }
  1142. for (i = 0; i < PQntuples(res); i++)
  1143. {
  1144. char *dbname = PQgetvalue(res, i, 0);
  1145. char *dbowner = PQgetvalue(res, i, 1);
  1146. char *dbencoding = PQgetvalue(res, i, 2);
  1147. char *dbcollate = PQgetvalue(res, i, 3);
  1148. char *dbctype = PQgetvalue(res, i, 4);
  1149. uint32 dbfrozenxid = atooid(PQgetvalue(res, i, 5));
  1150. uint32 dbminmxid = atooid(PQgetvalue(res, i, 6));
  1151. char *dbistemplate = PQgetvalue(res, i, 7);
  1152. char *dbacl = PQgetvalue(res, i, 8);
  1153. char *dbconnlimit = PQgetvalue(res, i, 9);
  1154. char *dbtablespace = PQgetvalue(res, i, 10);
  1155. char *fdbname;
  1156. fdbname = pg_strdup(fmtId(dbname));
  1157. resetPQExpBuffer(buf);
  1158. /*
  1159. * Skip the CREATE DATABASE commands for "template1" and "postgres",
  1160. * since they are presumably already there in the destination cluster.
  1161. * We do want to emit their ACLs and config options if any, however.
  1162. */
  1163. if (strcmp(dbname, "template1") != 0 &&
  1164. strcmp(dbname, "postgres") != 0)
  1165. {
  1166. appendPQExpBuffer(buf, "CREATE DATABASE %s", fdbname);
  1167. appendPQExpBufferStr(buf, " WITH TEMPLATE = template0");
  1168. if (strlen(dbowner) != 0)
  1169. appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner));
  1170. if (default_encoding && strcmp(dbencoding, default_encoding) != 0)
  1171. {
  1172. appendPQExpBufferStr(buf, " ENCODING = ");
  1173. appendStringLiteralConn(buf, dbencoding, conn);
  1174. }
  1175. if (default_collate && strcmp(dbcollate, default_collate) != 0)
  1176. {
  1177. appendPQExpBufferStr(buf, " LC_COLLATE = ");
  1178. appendStringLiteralConn(buf, dbcollate, conn);
  1179. }
  1180. if (default_ctype && strcmp(dbctype, default_ctype) != 0)
  1181. {
  1182. appendPQExpBufferStr(buf, " LC_CTYPE = ");
  1183. appendStringLiteralConn(buf, dbctype, conn);
  1184. }
  1185. /*
  1186. * Output tablespace if it isn't the default. For default, it
  1187. * uses the default from the template database. If tablespace is
  1188. * specified and tablespace creation failed earlier, (e.g. no such
  1189. * directory), the database creation will fail too. One solution
  1190. * would be to use 'SET default_tablespace' like we do in pg_dump
  1191. * for setting non-default database locations.
  1192. */
  1193. if (strcmp(dbtablespace, "pg_default") != 0 && !no_tablespaces)
  1194. appendPQExpBuffer(buf, " TABLESPACE = %s",
  1195. fmtId(dbtablespace));
  1196. if (strcmp(dbistemplate, "t") == 0)
  1197. appendPQExpBuffer(buf, " IS_TEMPLATE = true");
  1198. if (strcmp(dbconnlimit, "-1") != 0)
  1199. appendPQExpBuffer(buf, " CONNECTION LIMIT = %s",
  1200. dbconnlimit);
  1201. appendPQExpBufferStr(buf, ";\n");
  1202. if (binary_upgrade)
  1203. {
  1204. appendPQExpBufferStr(buf, "-- For binary upgrade, set datfrozenxid and datminmxid.\n");
  1205. appendPQExpBuffer(buf, "UPDATE pg_catalog.pg_database "
  1206. "SET datfrozenxid = '%u', datminmxid = '%u' "
  1207. "WHERE datname = ",
  1208. dbfrozenxid, dbminmxid);
  1209. appendStringLiteralConn(buf, dbname, conn);
  1210. appendPQExpBufferStr(buf, ";\n");
  1211. }
  1212. }
  1213. if (!skip_acls &&
  1214. !buildACLCommands(fdbname, NULL, "DATABASE", dbacl, dbowner,
  1215. "", server_version, buf))
  1216. {
  1217. fprintf(stderr, _("%s: could not parse ACL list (%s) for database \"%s\"\n"),
  1218. progname, dbacl, fdbname);
  1219. PQfinish(conn);
  1220. exit_nicely(1);
  1221. }
  1222. fprintf(OPF, "%s", buf->data);
  1223. if (server_version >= 70300)
  1224. dumpDatabaseConfig(conn, dbname);
  1225. free(fdbname);
  1226. }
  1227. PQclear(res);
  1228. destroyPQExpBuffer(buf);
  1229. fprintf(OPF, "\n\n");
  1230. }
  1231. /*
  1232. * Dump database-specific configuration
  1233. */
  1234. static void
  1235. dumpDatabaseConfig(PGconn *conn, const char *dbname)
  1236. {
  1237. PQExpBuffer buf = createPQExpBuffer();
  1238. int count = 1;
  1239. for (;;)
  1240. {
  1241. PGresult *res;
  1242. if (server_version >= 90000)
  1243. printfPQExpBuffer(buf, "SELECT setconfig[%d] FROM pg_db_role_setting WHERE "
  1244. "setrole = 0 AND setdatabase = (SELECT oid FROM pg_database WHERE datname = ", count);
  1245. else
  1246. printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count);
  1247. appendStringLiteralConn(buf, dbname, conn);
  1248. if (server_version >= 90000)
  1249. appendPQExpBuffer(buf, ")");
  1250. res = executeQuery(conn, buf->data);
  1251. if (PQntuples(res) == 1 &&
  1252. !PQgetisnull(res, 0, 0))
  1253. {
  1254. makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
  1255. "DATABASE", dbname, NULL, NULL);
  1256. PQclear(res);
  1257. count++;
  1258. }
  1259. else
  1260. {
  1261. PQclear(res);
  1262. break;
  1263. }
  1264. }
  1265. destroyPQExpBuffer(buf);
  1266. }
  1267. /*
  1268. * Dump user-specific configuration
  1269. */
  1270. static void
  1271. dumpUserConfig(PGconn *conn, const char *username)
  1272. {
  1273. PQExpBuffer buf = createPQExpBuffer();
  1274. int count = 1;
  1275. for (;;)
  1276. {
  1277. PGresult *res;
  1278. if (server_version >= 90000)
  1279. printfPQExpBuffer(buf, "SELECT setconfig[%d] FROM pg_db_role_setting WHERE "
  1280. "setdatabase = 0 AND setrole = "
  1281. "(SELECT oid FROM pg_authid WHERE rolname = ", count);
  1282. else if (server_version >= 80100)
  1283. printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM pg_authid WHERE rolname = ", count);
  1284. else
  1285. printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
  1286. appendStringLiteralConn(buf, username, conn);
  1287. if (server_version >= 90000)
  1288. appendPQExpBufferChar(buf, ')');
  1289. res = executeQuery(conn, buf->data);
  1290. if (PQntuples(res) == 1 &&
  1291. !PQgetisnull(res, 0, 0))
  1292. {
  1293. makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
  1294. "ROLE", username, NULL, NULL);
  1295. PQclear(res);
  1296. count++;
  1297. }
  1298. else
  1299. {
  1300. PQclear(res);
  1301. break;
  1302. }
  1303. }
  1304. destroyPQExpBuffer(buf);
  1305. }
  1306. /*
  1307. * Dump user-and-database-specific configuration
  1308. */
  1309. static void
  1310. dumpDbRoleConfig(PGconn *conn)
  1311. {
  1312. PQExpBuffer buf = createPQExpBuffer();
  1313. PGresult *res;
  1314. int i;
  1315. printfPQExpBuffer(buf, "SELECT rolname, datname, unnest(setconfig) "
  1316. "FROM pg_db_role_setting, pg_authid, pg_database "
  1317. "WHERE setrole = pg_authid.oid AND setdatabase = pg_database.oid");
  1318. res = executeQuery(conn, buf->data);
  1319. if (PQntuples(res) > 0)
  1320. {
  1321. fprintf(OPF, "--\n-- Per-Database Role Settings \n--\n\n");
  1322. for (i = 0; i < PQntuples(res); i++)
  1323. {
  1324. makeAlterConfigCommand(conn, PQgetvalue(res, i, 2),
  1325. "ROLE", PQgetvalue(res, i, 0),
  1326. "DATABASE", PQgetvalue(res, i, 1));
  1327. }
  1328. fprintf(OPF, "\n\n");
  1329. }
  1330. PQclear(res);
  1331. destroyPQExpBuffer(buf);
  1332. }
  1333. /*
  1334. * Helper function for dumpXXXConfig().
  1335. */
  1336. static void
  1337. makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
  1338. const char *type, const char *name,
  1339. const char *type2, const char *name2)
  1340. {
  1341. char *pos;
  1342. char *mine;
  1343. PQExpBuffer buf;
  1344. mine = pg_strdup(arrayitem);
  1345. pos = strchr(mine, '=');
  1346. if (pos == NULL)
  1347. {
  1348. free(mine);
  1349. return;
  1350. }
  1351. buf = createPQExpBuffer();
  1352. *pos = 0;
  1353. appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name));
  1354. if (type2 != NULL && name2 != NULL)
  1355. appendPQExpBuffer(buf, "IN %s %s ", type2, fmtId(name2));
  1356. appendPQExpBuffer(buf, "SET %s TO ", fmtId(mine));
  1357. /*
  1358. * Some GUC variable names are 'LIST' type and hence must not be quoted.
  1359. */
  1360. if (pg_strcasecmp(mine, "DateStyle") == 0
  1361. || pg_strcasecmp(mine, "search_path") == 0)
  1362. appendPQExpBufferStr(buf, pos + 1);
  1363. else
  1364. appendStringLiteralConn(buf, pos + 1, conn);
  1365. appendPQExpBufferStr(buf, ";\n");
  1366. fprintf(OPF, "%s", buf->data);
  1367. destroyPQExpBuffer(buf);
  1368. free(mine);
  1369. }
  1370. /*
  1371. * Dump contents of databases.
  1372. */
  1373. static void
  1374. dumpDatabases(PGconn *conn)
  1375. {
  1376. PGresult *res;
  1377. int i;
  1378. if (server_version >= 70100)
  1379. res = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1");
  1380. else
  1381. res = executeQuery(conn, "SELECT datname FROM pg_database ORDER BY 1");
  1382. for (i = 0; i < PQntuples(res); i++)
  1383. {
  1384. int ret;
  1385. char *dbname = PQgetvalue(res, i, 0);
  1386. if (verbose)
  1387. fprintf(stderr, _("%s: dumping database \"%s\"...\n"), progname, dbname);
  1388. fprintf(OPF, "\\connect %s\n\n", fmtId(dbname));
  1389. /*
  1390. * Restore will need to write to the target cluster. This connection
  1391. * setting is emitted for pg_dumpall rather than in the code also used
  1392. * by pg_dump, so that a cluster with databases or users which have
  1393. * this flag turned on can still be replicated through pg_dumpall
  1394. * without editing the file or stream. With pg_dump there are many
  1395. * other ways to allow the file to be used, and leaving it out allows
  1396. * users to protect databases from being accidental restore targets.
  1397. */
  1398. fprintf(OPF, "SET default_transaction_read_only = off;\n\n");
  1399. if (filename)
  1400. fclose(OPF);
  1401. ret = runPgDump(dbname);
  1402. if (ret != 0)
  1403. {
  1404. fprintf(stderr, _("%s: pg_dump failed on database \"%s\", exiting\n"), progname, dbname);
  1405. exit_nicely(1);
  1406. }
  1407. if (filename)
  1408. {
  1409. OPF = fopen(filename, PG_BINARY_A);
  1410. if (!OPF)
  1411. {
  1412. fprintf(stderr, _("%s: could not re-open the output file \"%s\": %s\n"),
  1413. progname, filename, strerror(errno));
  1414. exit_nicely(1);
  1415. }
  1416. }
  1417. }
  1418. PQclear(res);
  1419. }
  1420. /*
  1421. * Run pg_dump on dbname.
  1422. */
  1423. static int
  1424. runPgDump(const char *dbname)
  1425. {
  1426. PQExpBuffer connstrbuf = createPQExpBuffer();
  1427. PQExpBuffer cmd = createPQExpBuffer();
  1428. int ret;
  1429. appendPQExpBuffer(cmd, "\"%s\" %s", pg_dump_bin,
  1430. pgdumpopts->data);
  1431. /*
  1432. * If we have a filename, use the undocumented plain-append pg_dump
  1433. * format.
  1434. */
  1435. if (filename)
  1436. appendPQExpBufferStr(cmd, " -Fa ");
  1437. else
  1438. appendPQExpBufferStr(cmd, " -Fp ");
  1439. /*
  1440. * Append the database name to the already-constructed stem of connection
  1441. * string.
  1442. */
  1443. appendPQExpBuffer(connstrbuf, "%s dbname=", connstr);
  1444. doConnStrQuoting(connstrbuf, dbname);
  1445. doShellQuoting(cmd, connstrbuf->data);
  1446. if (verbose)
  1447. fprintf(stderr, _("%s: running \"%s\"\n"), progname, cmd->data);
  1448. fflush(stdout);
  1449. fflush(stderr);
  1450. ret = system(cmd->data);
  1451. destroyPQExpBuffer(cmd);
  1452. destroyPQExpBuffer(connstrbuf);
  1453. return ret;
  1454. }
  1455. /*
  1456. * buildShSecLabels
  1457. *
  1458. * Build SECURITY LABEL command(s) for an shared object
  1459. *
  1460. * The caller has to provide object type and identifier to select security
  1461. * labels from pg_seclabels system view.
  1462. */
  1463. static void
  1464. buildShSecLabels(PGconn *conn, const char *catalog_name, uint32 objectId,
  1465. PQExpBuffer buffer, const char *target, const char *objname)
  1466. {
  1467. PQExpBuffer sql = createPQExpBuffer();
  1468. PGresult *res;
  1469. buildShSecLabelQuery(conn, catalog_name, objectId, sql);
  1470. res = executeQuery(conn, sql->data);
  1471. emitShSecLabels(conn, res, buffer, target, objname);
  1472. PQclear(res);
  1473. destroyPQExpBuffer(sql);
  1474. }
  1475. /*
  1476. * Make a database connection with the given parameters. An
  1477. * interactive password prompt is automatically issued if required.
  1478. *
  1479. * If fail_on_error is false, we return NULL without printing any message
  1480. * on failure, but preserve any prompted password for the next try.
  1481. *
  1482. * On success, the global variable 'connstr' is set to a connection string
  1483. * containing the options used.
  1484. */
  1485. static PGconn *
  1486. connectDatabase(const char *dbname, const char *connection_string,
  1487. const char *pghost, const char *pgport, const char *pguser,
  1488. enum trivalue prompt_password, bool fail_on_error)
  1489. {
  1490. PGconn *conn;
  1491. bool new_pass;
  1492. const char *remoteversion_str;
  1493. int my_version;
  1494. static char *password = NULL;
  1495. const char **keywords = NULL;
  1496. const char **values = NULL;
  1497. PQconninfoOption *conn_opts = NULL;
  1498. if (prompt_password == TRI_YES && !password)
  1499. password = simple_prompt("Password: ", 100, false);
  1500. /*
  1501. * Start the connection. Loop until we have a password if requested by
  1502. * backend.
  1503. */
  1504. do
  1505. {
  1506. int argcount = 6;
  1507. PQconninfoOption *conn_opt;
  1508. char *err_msg = NULL;
  1509. int i = 0;
  1510. if (keywords)
  1511. free(keywords);
  1512. if (values)
  1513. free(values);
  1514. if (conn_opts)
  1515. PQconninfoFree(conn_opts);
  1516. /*
  1517. * Merge the connection info inputs given in form of connection string
  1518. * and other options.
  1519. */
  1520. if (connection_string)
  1521. {
  1522. conn_opts = PQconninfoParse(connection_string, &err_msg);
  1523. if (conn_opts == NULL)
  1524. {
  1525. fprintf(stderr, "%s: %s", progname, err_msg);
  1526. exit_nicely(1);
  1527. }
  1528. for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
  1529. {
  1530. if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
  1531. argcount++;
  1532. }
  1533. keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
  1534. values = pg_malloc0((argcount + 1) * sizeof(*values));
  1535. for (conn_opt = conn_opts; conn_opt->keyword != NULL; conn_opt++)
  1536. {
  1537. if (conn_opt->val != NULL && conn_opt->val[0] != '\0')
  1538. {
  1539. keywords[i] = conn_opt->keyword;
  1540. values[i] = conn_opt->val;
  1541. i++;
  1542. }
  1543. }
  1544. }
  1545. else
  1546. {
  1547. keywords = pg_malloc0((argcount + 1) * sizeof(*keywords));
  1548. values = pg_malloc0((argcount + 1) * sizeof(*values));
  1549. }
  1550. if (pghost)
  1551. {
  1552. keywords[i] = "host";
  1553. values[i] = pghost;
  1554. i++;
  1555. }
  1556. if (pgport)
  1557. {
  1558. keywords[i] = "port";
  1559. values[i] = pgport;
  1560. i++;
  1561. }
  1562. if (pguser)
  1563. {
  1564. keywords[i] = "user";
  1565. values[i] = pguser;
  1566. i++;
  1567. }
  1568. if (password)
  1569. {
  1570. keywords[i] = "password";
  1571. values[i] = password;
  1572. i++;
  1573. }
  1574. if (dbname)
  1575. {
  1576. keywords[i] = "dbname";
  1577. values[i] = dbname;
  1578. i++;
  1579. }
  1580. keywords[i] = "fallback_application_name";
  1581. values[i] = progname;
  1582. i++;
  1583. new_pass = false;
  1584. conn = PQconnectdbParams(keywords, values, true);
  1585. if (!conn)
  1586. {
  1587. fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
  1588. progname, dbname);
  1589. exit_nicely(1);
  1590. }
  1591. if (PQstatus(conn) == CONNECTION_BAD &&
  1592. PQconnectionNeedsPassword(conn) &&
  1593. password == NULL &&
  1594. prompt_password != TRI_NO)
  1595. {
  1596. PQfinish(conn);
  1597. password = simple_prompt("Password: ", 100, false);
  1598. new_pass = true;
  1599. }
  1600. } while (new_pass);
  1601. /* check to see that the backend connection was successfully made */
  1602. if (PQstatus(conn) == CONNECTION_BAD)
  1603. {
  1604. if (fail_on_error)
  1605. {
  1606. fprintf(stderr,
  1607. _("%s: could not connect to database \"%s\": %s\n"),
  1608. progname, dbname, PQerrorMessage(conn));
  1609. exit_nicely(1);
  1610. }
  1611. else
  1612. {
  1613. PQfinish(conn);
  1614. free(keywords);
  1615. free(values);
  1616. PQconninfoFree(conn_opts);
  1617. return NULL;
  1618. }
  1619. }
  1620. /*
  1621. * Ok, connected successfully. Remember the options used, in the form of a
  1622. * connection string.
  1623. */
  1624. connstr = constructConnStr(keywords, values);
  1625. free(keywords);
  1626. free(values);
  1627. PQconninfoFree(conn_opts);
  1628. /* Check version */
  1629. remoteversion_str = PQparameterStatus(conn, "server_version");
  1630. if (!remoteversion_str)
  1631. {
  1632. fprintf(stderr, _("%s: could not get server version\n"), progname);
  1633. exit_nicely(1);
  1634. }
  1635. server_version = PQserverVersion(conn);
  1636. if (server_version == 0)
  1637. {
  1638. fprintf(stderr, _("%s: could not parse server version \"%s\"\n"),
  1639. progname, remoteversion_str);
  1640. exit_nicely(1);
  1641. }
  1642. my_version = PG_VERSION_NUM;
  1643. /*
  1644. * We allow the server to be back to 7.0, and up to any minor release of
  1645. * our own major version. (See also version check in pg_dump.c.)
  1646. */
  1647. if (my_version != server_version
  1648. && (server_version < 70000 ||
  1649. (server_version / 100) > (my_version / 100)))
  1650. {
  1651. fprintf(stderr, _("server version: %s; %s version: %s\n"),
  1652. remoteversion_str, progname, PG_VERSION);
  1653. fprintf(stderr, _("aborting because of server version mismatch\n"));
  1654. exit_nicely(1);
  1655. }
  1656. /*
  1657. * On 7.3 and later, make sure we are not fooled by non-system schemas in
  1658. * the search path.
  1659. */
  1660. if (server_version >= 70300)
  1661. executeCommand(conn, "SET search_path = pg_catalog");
  1662. return conn;
  1663. }
  1664. /* ----------
  1665. * Construct a connection string from the given keyword/value pairs. It is
  1666. * used to pass the connection options to the pg_dump subprocess.
  1667. *
  1668. * The following parameters are excluded:
  1669. * dbname - varies in each pg_dump invocation
  1670. * password - it's not secure to pass a password on the command line
  1671. * fallback_application_name - we'll let pg_dump set it
  1672. * ----------
  1673. */
  1674. static char *
  1675. constructConnStr(const char **keywords, const char **values)
  1676. {
  1677. PQExpBuffer buf = createPQExpBuffer();
  1678. char *connstr;
  1679. int i;
  1680. bool firstkeyword = true;
  1681. /* Construct a new connection string in key='value' format. */
  1682. for (i = 0; keywords[i] != NULL; i++)
  1683. {
  1684. if (strcmp(keywords[i], "dbname") == 0 ||
  1685. strcmp(keywords[i], "password") == 0 ||
  1686. strcmp(keywords[i], "fallback_application_name") == 0)
  1687. continue;
  1688. if (!firstkeyword)
  1689. appendPQExpBufferChar(buf, ' ');
  1690. firstkeyword = false;
  1691. appendPQExpBuffer(buf, "%s=", keywords[i]);
  1692. doConnStrQuoting(buf, values[i]);
  1693. }
  1694. connstr = pg_strdup(buf->data);
  1695. destroyPQExpBuffer(buf);
  1696. return connstr;
  1697. }
  1698. /*
  1699. * Run a query, return the results, exit program on failure.
  1700. */
  1701. static PGresult *
  1702. executeQuery(PGconn *conn, const char *query)
  1703. {
  1704. PGresult *res;
  1705. if (verbose)
  1706. fprintf(stderr, _("%s: executing %s\n"), progname, query);
  1707. res = PQexec(conn, query);
  1708. if (!res ||
  1709. PQresultStatus(res) != PGRES_TUPLES_OK)
  1710. {
  1711. fprintf(stderr, _("%s: query failed: %s"),
  1712. progname, PQerrorMessage(conn));
  1713. fprintf(stderr, _("%s: query was: %s\n"),
  1714. progname, query);
  1715. PQfinish(conn);
  1716. exit_nicely(1);
  1717. }
  1718. return res;
  1719. }
  1720. /*
  1721. * As above for a SQL command (which returns nothing).
  1722. */
  1723. static void
  1724. executeCommand(PGconn *conn, const char *query)
  1725. {
  1726. PGresult *res;
  1727. if (verbose)
  1728. fprintf(stderr, _("%s: executing %s\n"), progname, query);
  1729. res = PQexec(conn, query);
  1730. if (!res ||
  1731. PQresultStatus(res) != PGRES_COMMAND_OK)
  1732. {
  1733. fprintf(stderr, _("%s: query failed: %s"),
  1734. progname, PQerrorMessage(conn));
  1735. fprintf(stderr, _("%s: query was: %s\n"),
  1736. progname, query);
  1737. PQfinish(conn);
  1738. exit_nicely(1);
  1739. }
  1740. PQclear(res);
  1741. }
  1742. /*
  1743. * dumpTimestamp
  1744. */
  1745. static void
  1746. dumpTimestamp(char *msg)
  1747. {
  1748. char buf[256];
  1749. time_t now = time(NULL);
  1750. /*
  1751. * We don't print the timezone on Win32, because the names are long and
  1752. * localized, which means they may contain characters in various random
  1753. * encodings; this has been seen to cause encoding errors when reading the
  1754. * dump script.
  1755. */
  1756. if (strftime(buf, sizeof(buf),
  1757. #ifndef WIN32
  1758. "%Y-%m-%d %H:%M:%S %Z",
  1759. #else
  1760. "%Y-%m-%d %H:%M:%S",
  1761. #endif
  1762. localtime(&now)) != 0)
  1763. fprintf(OPF, "-- %s %s\n\n", msg, buf);
  1764. }
  1765. /*
  1766. * Append the given string to the buffer, with suitable quoting for passing
  1767. * the string as a value, in a keyword/pair value in a libpq connection
  1768. * string
  1769. */
  1770. static void
  1771. doConnStrQuoting(PQExpBuffer buf, const char *str)
  1772. {
  1773. const char *s;
  1774. bool needquotes;
  1775. /*
  1776. * If the string consists entirely of plain ASCII characters, no need to
  1777. * quote it. This is quite conservative, but better safe than sorry.
  1778. */
  1779. needquotes = false;
  1780. for (s = str; *s; s++)
  1781. {
  1782. if (!((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') ||
  1783. (*s >= '0' && *s <= '9') || *s == '_' || *s == '.'))
  1784. {
  1785. needquotes = true;
  1786. break;
  1787. }
  1788. }
  1789. if (needquotes)
  1790. {
  1791. appendPQExpBufferChar(buf, '\'');
  1792. while (*str)
  1793. {
  1794. /* ' and \ must be escaped by to \' and \\ */
  1795. if (*str == '\'' || *str == '\\')
  1796. appendPQExpBufferChar(buf, '\\');
  1797. appendPQExpBufferChar(buf, *str);
  1798. str++;
  1799. }
  1800. appendPQExpBufferChar(buf, '\'');
  1801. }
  1802. else
  1803. appendPQExpBufferStr(buf, str);
  1804. }
  1805. /*
  1806. * Append the given string to the shell command being built in the buffer,
  1807. * with suitable shell-style quoting.
  1808. */
  1809. static void
  1810. doShellQuoting(PQExpBuffer buf, const char *str)
  1811. {
  1812. const char *p;
  1813. #ifndef WIN32
  1814. appendPQExpBufferChar(buf, '\'');
  1815. for (p = str; *p; p++)
  1816. {
  1817. if (*p == '\'')
  1818. appendPQExpBufferStr(buf, "'\"'\"'");
  1819. else
  1820. appendPQExpBufferChar(buf, *p);
  1821. }
  1822. appendPQExpBufferChar(buf, '\'');
  1823. #else /* WIN32 */
  1824. appendPQExpBufferChar(buf, '"');
  1825. for (p = str; *p; p++)
  1826. {
  1827. if (*p == '"')
  1828. appendPQExpBufferStr(buf, "\\\"");
  1829. else
  1830. appendPQExpBufferChar(buf, *p);
  1831. }
  1832. appendPQExpBufferChar(buf, '"');
  1833. #endif /* WIN32 */
  1834. }