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