]> granicus.if.org Git - postgresql/blob - src/bin/pg_dump/pg_dumpall.c
Fix up the PQconnectionUsedPassword mess: create a separate
[postgresql] / src / bin / pg_dump / pg_dumpall.c
1 /*-------------------------------------------------------------------------
2  *
3  * pg_dumpall.c
4  *
5  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
6  * Portions Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.99 2007/12/09 19:01:40 tgl Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13
14 #include "postgres_fe.h"
15
16 #include <time.h>
17 #include <unistd.h>
18
19 #ifdef ENABLE_NLS
20 #include <locale.h>
21 #endif
22
23 #include "getopt_long.h"
24
25 #ifndef HAVE_INT_OPTRESET
26 int                     optreset;
27 #endif
28
29 #include "dumputils.h"
30
31
32 /* version string we expect back from pg_dump */
33 #define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
34
35
36 static const char *progname;
37
38 static void help(void);
39
40 static void dumpRoles(PGconn *conn);
41 static void dumpRoleMembership(PGconn *conn);
42 static void dumpGroups(PGconn *conn);
43 static void dumpTablespaces(PGconn *conn);
44 static void dumpCreateDB(PGconn *conn);
45 static void dumpDatabaseConfig(PGconn *conn, const char *dbname);
46 static void dumpUserConfig(PGconn *conn, const char *username);
47 static void makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
48                                            const char *type, const char *name);
49 static void dumpDatabases(PGconn *conn);
50 static void dumpTimestamp(char *msg);
51
52 static int      runPgDump(const char *dbname);
53 static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
54                           const char *pguser, bool require_password, bool fail_on_error);
55 static PGresult *executeQuery(PGconn *conn, const char *query);
56 static void executeCommand(PGconn *conn, const char *query);
57
58 static char pg_dump_bin[MAXPGPATH];
59 static PQExpBuffer pgdumpopts;
60 static bool output_clean = false;
61 static bool skip_acls = false;
62 static bool verbose = false;
63 static bool ignoreVersion = false;
64
65 static int      disable_dollar_quoting = 0;
66 static int      disable_triggers = 0;
67 static int      use_setsessauth = 0;
68 static int      server_version;
69
70 static FILE *OPF;
71 static char *filename = NULL;
72
73 int
74 main(int argc, char *argv[])
75 {
76         char       *pghost = NULL;
77         char       *pgport = NULL;
78         char       *pguser = NULL;
79         char       *pgdb = NULL;
80         bool            force_password = false;
81         bool            data_only = false;
82         bool            globals_only = false;
83         bool            roles_only = false;
84         bool            tablespaces_only = false;
85         bool            schema_only = false;
86         PGconn     *conn;
87         int                     encoding;
88         const char *std_strings;
89         int                     c,
90                                 ret;
91
92         static struct option long_options[] = {
93                 {"data-only", no_argument, NULL, 'a'},
94                 {"clean", no_argument, NULL, 'c'},
95                 {"inserts", no_argument, NULL, 'd'},
96                 {"attribute-inserts", no_argument, NULL, 'D'},
97                 {"column-inserts", no_argument, NULL, 'D'},
98                 {"file", required_argument, NULL, 'f'},
99                 {"globals-only", no_argument, NULL, 'g'},
100                 {"host", required_argument, NULL, 'h'},
101                 {"ignore-version", no_argument, NULL, 'i'},
102                 {"database", required_argument, NULL, 'l'},
103                 {"oids", no_argument, NULL, 'o'},
104                 {"no-owner", no_argument, NULL, 'O'},
105                 {"port", required_argument, NULL, 'p'},
106                 {"roles-only", no_argument, NULL, 'r'},
107                 {"schema-only", no_argument, NULL, 's'},
108                 {"superuser", required_argument, NULL, 'S'},
109                 {"tablespaces-only", no_argument, NULL, 't'},
110                 {"username", required_argument, NULL, 'U'},
111                 {"verbose", no_argument, NULL, 'v'},
112                 {"password", no_argument, NULL, 'W'},
113                 {"no-privileges", no_argument, NULL, 'x'},
114                 {"no-acl", no_argument, NULL, 'x'},
115
116                 /*
117                  * the following options don't have an equivalent short option letter
118                  */
119                 {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
120                 {"disable-triggers", no_argument, &disable_triggers, 1},
121                 {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
122
123                 {NULL, 0, NULL, 0}
124         };
125
126         int                     optindex;
127
128         set_pglocale_pgservice(argv[0], "pg_dump");
129
130         progname = get_progname(argv[0]);
131
132         if (argc > 1)
133         {
134                 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
135                 {
136                         help();
137                         exit(0);
138                 }
139                 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
140                 {
141                         puts("pg_dumpall (PostgreSQL) " PG_VERSION);
142                         exit(0);
143                 }
144         }
145
146         if ((ret = find_other_exec(argv[0], "pg_dump", PGDUMP_VERSIONSTR,
147                                                            pg_dump_bin)) < 0)
148         {
149                 char            full_path[MAXPGPATH];
150
151                 if (find_my_exec(argv[0], full_path) < 0)
152                         strlcpy(full_path, progname, sizeof(full_path));
153
154                 if (ret == -1)
155                         fprintf(stderr,
156                                         _("The program \"pg_dump\" is needed by %s "
157                                           "but was not found in the\n"
158                                           "same directory as \"%s\".\n"
159                                           "Check your installation.\n"),
160                                         progname, full_path);
161                 else
162                         fprintf(stderr,
163                                         _("The program \"pg_dump\" was found by \"%s\"\n"
164                                           "but was not the same version as %s.\n"
165                                           "Check your installation.\n"),
166                                         full_path, progname);
167                 exit(1);
168         }
169
170         pgdumpopts = createPQExpBuffer();
171
172         while ((c = getopt_long(argc, argv, "acdDf:gh:il:oOp:rsS:tU:vWxX:", long_options, &optindex)) != -1)
173         {
174                 switch (c)
175                 {
176                         case 'a':
177                                 data_only = true;
178                                 appendPQExpBuffer(pgdumpopts, " -a");
179                                 break;
180
181                         case 'c':
182                                 output_clean = true;
183                                 break;
184
185                         case 'd':
186                         case 'D':
187                                 appendPQExpBuffer(pgdumpopts, " -%c", c);
188                                 break;
189
190                         case 'f':
191                                 filename = optarg;
192 #ifndef WIN32
193                                 appendPQExpBuffer(pgdumpopts, " -f '%s'", filename);
194 #else
195                                 appendPQExpBuffer(pgdumpopts, " -f \"%s\"", filename);
196 #endif
197
198                                 break;
199
200                         case 'g':
201                                 globals_only = true;
202                                 break;
203
204                         case 'h':
205                                 pghost = optarg;
206 #ifndef WIN32
207                                 appendPQExpBuffer(pgdumpopts, " -h '%s'", pghost);
208 #else
209                                 appendPQExpBuffer(pgdumpopts, " -h \"%s\"", pghost);
210 #endif
211
212                                 break;
213
214                         case 'i':
215                                 ignoreVersion = true;
216                                 appendPQExpBuffer(pgdumpopts, " -i");
217                                 break;
218
219                         case 'l':
220                                 pgdb = optarg;
221                                 break;
222
223                         case 'o':
224                                 appendPQExpBuffer(pgdumpopts, " -o");
225                                 break;
226
227                         case 'O':
228                                 appendPQExpBuffer(pgdumpopts, " -O");
229                                 break;
230
231                         case 'p':
232                                 pgport = optarg;
233 #ifndef WIN32
234                                 appendPQExpBuffer(pgdumpopts, " -p '%s'", pgport);
235 #else
236                                 appendPQExpBuffer(pgdumpopts, " -p \"%s\"", pgport);
237 #endif
238                                 break;
239
240                         case 'r':
241                                 roles_only = true;
242                                 break;
243
244                         case 's':
245                                 schema_only = true;
246                                 appendPQExpBuffer(pgdumpopts, " -s");
247                                 break;
248
249                         case 'S':
250 #ifndef WIN32
251                                 appendPQExpBuffer(pgdumpopts, " -S '%s'", optarg);
252 #else
253                                 appendPQExpBuffer(pgdumpopts, " -S \"%s\"", optarg);
254 #endif
255                                 break;
256
257                         case 't':
258                                 tablespaces_only = true;
259                                 break;
260
261                         case 'U':
262                                 pguser = optarg;
263 #ifndef WIN32
264                                 appendPQExpBuffer(pgdumpopts, " -U '%s'", pguser);
265 #else
266                                 appendPQExpBuffer(pgdumpopts, " -U \"%s\"", pguser);
267 #endif
268                                 break;
269
270                         case 'v':
271                                 verbose = true;
272                                 appendPQExpBuffer(pgdumpopts, " -v");
273                                 break;
274
275                         case 'W':
276                                 force_password = true;
277                                 appendPQExpBuffer(pgdumpopts, " -W");
278                                 break;
279
280                         case 'x':
281                                 skip_acls = true;
282                                 appendPQExpBuffer(pgdumpopts, " -x");
283                                 break;
284
285                         case 'X':
286                                 /* -X is a deprecated alternative to long options */
287                                 if (strcmp(optarg, "disable-dollar-quoting") == 0)
288                                         appendPQExpBuffer(pgdumpopts, " --disable-dollar-quoting");
289                                 else if (strcmp(optarg, "disable-triggers") == 0)
290                                         appendPQExpBuffer(pgdumpopts, " --disable-triggers");
291                                 else if (strcmp(optarg, "use-set-session-authorization") == 0)
292                                          /* no-op, still allowed for compatibility */ ;
293                                 else
294                                 {
295                                         fprintf(stderr,
296                                                         _("%s: invalid -X option -- %s\n"),
297                                                         progname, optarg);
298                                         fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
299                                         exit(1);
300                                 }
301                                 break;
302
303                         case 0:
304                                 break;
305
306                         default:
307                                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
308                                 exit(1);
309                 }
310         }
311
312         /* Add long options to the pg_dump argument list */
313         if (disable_dollar_quoting)
314                 appendPQExpBuffer(pgdumpopts, " --disable-dollar-quoting");
315         if (disable_triggers)
316                 appendPQExpBuffer(pgdumpopts, " --disable-triggers");
317         if (use_setsessauth)
318                 appendPQExpBuffer(pgdumpopts, " --use-set-session-authorization");
319
320         if (optind < argc)
321         {
322                 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
323                                 progname, argv[optind]);
324                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
325                                 progname);
326                 exit(1);
327         }
328
329         /* Make sure the user hasn't specified a mix of globals-only options */
330         if (globals_only && roles_only)
331         {
332                 fprintf(stderr, _("%s: options -g/--globals-only and -r/--roles-only cannot be used together\n"),
333                                 progname);
334                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
335                                 progname);
336                 exit(1);
337         }
338
339         if (globals_only && tablespaces_only)
340         {
341                 fprintf(stderr, _("%s: options -g/--globals-only and -t/--tablespaces-only cannot be used together\n"),
342                                 progname);
343                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
344                                 progname);
345                 exit(1);
346         }
347
348         if (roles_only && tablespaces_only)
349         {
350                 fprintf(stderr, _("%s: options -r/--roles-only and -t/--tablespaces-only cannot be used together\n"),
351                                 progname);
352                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
353                                 progname);
354                 exit(1);
355         }
356
357         /*
358          * If there was a database specified on the command line, use that,
359          * otherwise try to connect to database "postgres", and failing that
360          * "template1".  "postgres" is the preferred choice for 8.1 and later
361          * servers, but it usually will not exist on older ones.
362          */
363         if (pgdb)
364         {
365                 conn = connectDatabase(pgdb, pghost, pgport, pguser,
366                                                            force_password, false);
367
368                 if (!conn)
369                 {
370                         fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
371                                         progname, pgdb);
372                         exit(1);
373                 }
374         }
375         else
376         {
377                 conn = connectDatabase("postgres", pghost, pgport, pguser,
378                                                            force_password, false);
379                 if (!conn)
380                         conn = connectDatabase("template1", pghost, pgport, pguser,
381                                                                    force_password, true);
382
383                 if (!conn)
384                 {
385                         fprintf(stderr, _("%s: could not connect to databases \"postgres\" or \"template1\"\n"
386                                                           "Please specify an alternative database.\n"),
387                                         progname);
388                         fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
389                                         progname);
390                         exit(1);
391                 }
392         }
393
394         /*
395          * Open the output file if required, otherwise use stdout
396          */
397         if (filename)
398         {
399                 OPF = fopen(filename, PG_BINARY_W);
400                 if (!OPF)
401                 {
402                         fprintf(stderr, _("%s: could not open the output file \"%s\": %s\n"),
403                                         progname, filename, strerror(errno));
404                         exit(1);
405                 }
406         }
407         else
408                 OPF = stdout;
409
410         /*
411          * Get the active encoding and the standard_conforming_strings setting, so
412          * we know how to escape strings.
413          */
414         encoding = PQclientEncoding(conn);
415         std_strings = PQparameterStatus(conn, "standard_conforming_strings");
416         if (!std_strings)
417                 std_strings = "off";
418
419         fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n");
420         if (verbose)
421                 dumpTimestamp("Started on");
422
423         fprintf(OPF, "\\connect postgres\n\n");
424
425         if (!data_only)
426         {
427                 /* Replicate encoding and std_strings in output */
428                 fprintf(OPF, "SET client_encoding = '%s';\n",
429                                 pg_encoding_to_char(encoding));
430                 fprintf(OPF, "SET standard_conforming_strings = %s;\n", std_strings);
431                 if (strcmp(std_strings, "off") == 0)
432                         fprintf(OPF, "SET escape_string_warning = 'off';\n");
433                 fprintf(OPF, "\n");
434
435                 if (!tablespaces_only)
436                 {
437                         /* Dump roles (users) */
438                         dumpRoles(conn);
439
440                         /* Dump role memberships --- need different method for pre-8.1 */
441                         if (server_version >= 80100)
442                                 dumpRoleMembership(conn);
443                         else
444                                 dumpGroups(conn);
445                 }
446
447                 if (!roles_only)
448                 {
449                         /* Dump tablespaces */
450                         if (server_version >= 80000)
451                                 dumpTablespaces(conn);
452                 }
453
454                 /* Dump CREATE DATABASE commands */
455                 if (!globals_only && !roles_only && !tablespaces_only)
456                         dumpCreateDB(conn);
457         }
458
459         if (!globals_only && !roles_only && !tablespaces_only)
460                 dumpDatabases(conn);
461
462         PQfinish(conn);
463
464         if (verbose)
465                 dumpTimestamp("Completed on");
466         fprintf(OPF, "--\n-- PostgreSQL database cluster dump complete\n--\n\n");
467
468         if (filename)
469                 fclose(OPF);
470
471         exit(0);
472 }
473
474
475
476 static void
477 help(void)
478 {
479         printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname);
480         printf(_("Usage:\n"));
481         printf(_("  %s [OPTION]...\n"), progname);
482
483         printf(_("\nGeneral options:\n"));
484         printf(_("  -f, --file=FILENAME      output file name\n"));
485         printf(_("  -i, --ignore-version     proceed even when server version mismatches\n"
486                          "                           pg_dumpall version\n"));
487         printf(_("  --help                   show this help, then exit\n"));
488         printf(_("  --version                output version information, then exit\n"));
489         printf(_("\nOptions controlling the output content:\n"));
490         printf(_("  -a, --data-only          dump only the data, not the schema\n"));
491         printf(_("  -c, --clean              clean (drop) databases prior to create\n"));
492         printf(_("  -d, --inserts            dump data as INSERT, rather than COPY, commands\n"));
493         printf(_("  -D, --column-inserts     dump data as INSERT commands with column names\n"));
494         printf(_("  -g, --globals-only       dump only global objects, no databases\n"));
495         printf(_("  -o, --oids               include OIDs in dump\n"));
496         printf(_("  -O, --no-owner           skip restoration of object ownership\n"));
497         printf(_("  -r, --roles-only         dump only roles, no databases or tablespaces\n"));
498         printf(_("  -s, --schema-only        dump only the schema, no data\n"));
499         printf(_("  -S, --superuser=NAME     specify the superuser user name to use in the dump\n"));
500         printf(_("  -t, --tablespaces-only   dump only tablespaces, no databases or roles\n"));
501         printf(_("  -x, --no-privileges      do not dump privileges (grant/revoke)\n"));
502         printf(_("  --disable-dollar-quoting\n"
503                          "                           disable dollar quoting, use SQL standard quoting\n"));
504         printf(_("  --disable-triggers       disable triggers during data-only restore\n"));
505         printf(_("  --use-set-session-authorization\n"
506                          "                           use SESSION AUTHORIZATION commands instead of\n"
507                          "                           OWNER TO commands\n"));
508
509         printf(_("\nConnection options:\n"));
510         printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
511         printf(_("  -l, --database=DBNAME    specify an alternative default database\n"));
512         printf(_("  -p, --port=PORT          database server port number\n"));
513         printf(_("  -U, --username=NAME      connect as specified database user\n"));
514         printf(_("  -W, --password           force password prompt (should happen automatically)\n"));
515
516         printf(_("\nThe SQL script will be written to the standard output.\n\n"));
517         printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
518 }
519
520
521
522 /*
523  * Dump roles
524  */
525 static void
526 dumpRoles(PGconn *conn)
527 {
528         PQExpBuffer buf = createPQExpBuffer();
529         PGresult   *res;
530         int                     i_rolname,
531                                 i_rolsuper,
532                                 i_rolinherit,
533                                 i_rolcreaterole,
534                                 i_rolcreatedb,
535                                 i_rolcatupdate,
536                                 i_rolcanlogin,
537                                 i_rolconnlimit,
538                                 i_rolpassword,
539                                 i_rolvaliduntil,
540                                 i_rolcomment;
541         int                     i;
542
543         /* note: rolconfig is dumped later */
544         if (server_version >= 80200)
545                 printfPQExpBuffer(buf,
546                                                   "SELECT rolname, rolsuper, rolinherit, "
547                                                   "rolcreaterole, rolcreatedb, rolcatupdate, "
548                                                   "rolcanlogin, rolconnlimit, rolpassword, "
549                                                   "rolvaliduntil, "
550                           "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment "
551                                                   "FROM pg_authid "
552                                                   "ORDER BY 1");
553         else if (server_version >= 80100)
554                 printfPQExpBuffer(buf,
555                                                   "SELECT rolname, rolsuper, rolinherit, "
556                                                   "rolcreaterole, rolcreatedb, rolcatupdate, "
557                                                   "rolcanlogin, rolconnlimit, rolpassword, "
558                                                   "rolvaliduntil, null as rolcomment "
559                                                   "FROM pg_authid "
560                                                   "ORDER BY 1");
561         else
562                 printfPQExpBuffer(buf,
563                                                   "SELECT usename as rolname, "
564                                                   "usesuper as rolsuper, "
565                                                   "true as rolinherit, "
566                                                   "usesuper as rolcreaterole, "
567                                                   "usecreatedb as rolcreatedb, "
568                                                   "usecatupd as rolcatupdate, "
569                                                   "true as rolcanlogin, "
570                                                   "-1 as rolconnlimit, "
571                                                   "passwd as rolpassword, "
572                                                   "valuntil as rolvaliduntil, "
573                                                   "null as rolcomment "
574                                                   "FROM pg_shadow "
575                                                   "UNION ALL "
576                                                   "SELECT groname as rolname, "
577                                                   "false as rolsuper, "
578                                                   "true as rolinherit, "
579                                                   "false as rolcreaterole, "
580                                                   "false as rolcreatedb, "
581                                                   "false as rolcatupdate, "
582                                                   "false as rolcanlogin, "
583                                                   "-1 as rolconnlimit, "
584                                                   "null::text as rolpassword, "
585                                                   "null::abstime as rolvaliduntil, "
586                                                   "null as rolcomment "
587                                                   "FROM pg_group "
588                                                   "WHERE NOT EXISTS (SELECT 1 FROM pg_shadow "
589                                                   " WHERE usename = groname) "
590                                                   "ORDER BY 1");
591
592         res = executeQuery(conn, buf->data);
593
594         i_rolname = PQfnumber(res, "rolname");
595         i_rolsuper = PQfnumber(res, "rolsuper");
596         i_rolinherit = PQfnumber(res, "rolinherit");
597         i_rolcreaterole = PQfnumber(res, "rolcreaterole");
598         i_rolcreatedb = PQfnumber(res, "rolcreatedb");
599         i_rolcatupdate = PQfnumber(res, "rolcatupdate");
600         i_rolcanlogin = PQfnumber(res, "rolcanlogin");
601         i_rolconnlimit = PQfnumber(res, "rolconnlimit");
602         i_rolpassword = PQfnumber(res, "rolpassword");
603         i_rolvaliduntil = PQfnumber(res, "rolvaliduntil");
604         i_rolcomment = PQfnumber(res, "rolcomment");
605
606         if (PQntuples(res) > 0)
607                 fprintf(OPF, "--\n-- Roles\n--\n\n");
608
609         for (i = 0; i < PQntuples(res); i++)
610         {
611                 const char *rolename;
612
613                 rolename = PQgetvalue(res, i, i_rolname);
614
615                 resetPQExpBuffer(buf);
616
617                 if (output_clean)
618                         appendPQExpBuffer(buf, "DROP ROLE %s;\n", fmtId(rolename));
619
620                 /*
621                  * We dump CREATE ROLE followed by ALTER ROLE to ensure that the role
622                  * will acquire the right properties even if it already exists. (The
623                  * above DROP may therefore seem redundant, but it isn't really,
624                  * because this technique doesn't get rid of role memberships.)
625                  */
626                 appendPQExpBuffer(buf, "CREATE ROLE %s;\n", fmtId(rolename));
627                 appendPQExpBuffer(buf, "ALTER ROLE %s WITH", fmtId(rolename));
628
629                 if (strcmp(PQgetvalue(res, i, i_rolsuper), "t") == 0)
630                         appendPQExpBuffer(buf, " SUPERUSER");
631                 else
632                         appendPQExpBuffer(buf, " NOSUPERUSER");
633
634                 if (strcmp(PQgetvalue(res, i, i_rolinherit), "t") == 0)
635                         appendPQExpBuffer(buf, " INHERIT");
636                 else
637                         appendPQExpBuffer(buf, " NOINHERIT");
638
639                 if (strcmp(PQgetvalue(res, i, i_rolcreaterole), "t") == 0)
640                         appendPQExpBuffer(buf, " CREATEROLE");
641                 else
642                         appendPQExpBuffer(buf, " NOCREATEROLE");
643
644                 if (strcmp(PQgetvalue(res, i, i_rolcreatedb), "t") == 0)
645                         appendPQExpBuffer(buf, " CREATEDB");
646                 else
647                         appendPQExpBuffer(buf, " NOCREATEDB");
648
649                 if (strcmp(PQgetvalue(res, i, i_rolcanlogin), "t") == 0)
650                         appendPQExpBuffer(buf, " LOGIN");
651                 else
652                         appendPQExpBuffer(buf, " NOLOGIN");
653
654                 if (strcmp(PQgetvalue(res, i, i_rolconnlimit), "-1") != 0)
655                         appendPQExpBuffer(buf, " CONNECTION LIMIT %s",
656                                                           PQgetvalue(res, i, i_rolconnlimit));
657
658                 if (!PQgetisnull(res, i, i_rolpassword))
659                 {
660                         appendPQExpBuffer(buf, " PASSWORD ");
661                         appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolpassword), conn);
662                 }
663
664                 if (!PQgetisnull(res, i, i_rolvaliduntil))
665                         appendPQExpBuffer(buf, " VALID UNTIL '%s'",
666                                                           PQgetvalue(res, i, i_rolvaliduntil));
667
668                 appendPQExpBuffer(buf, ";\n");
669
670                 if (!PQgetisnull(res, i, i_rolcomment))
671                 {
672                         appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
673                         appendStringLiteralConn(buf, PQgetvalue(res, i, i_rolcomment), conn);
674                         appendPQExpBuffer(buf, ";\n");
675                 }
676
677                 fprintf(OPF, "%s", buf->data);
678
679                 if (server_version >= 70300)
680                         dumpUserConfig(conn, rolename);
681         }
682
683         PQclear(res);
684
685         fprintf(OPF, "\n\n");
686
687         destroyPQExpBuffer(buf);
688 }
689
690
691 /*
692  * Dump role memberships.  This code is used for 8.1 and later servers.
693  *
694  * Note: we expect dumpRoles already created all the roles, but there is
695  * no membership yet.
696  */
697 static void
698 dumpRoleMembership(PGconn *conn)
699 {
700         PGresult   *res;
701         int                     i;
702
703         res = executeQuery(conn, "SELECT ur.rolname AS roleid, "
704                                            "um.rolname AS member, "
705                                            "a.admin_option, "
706                                            "ug.rolname AS grantor "
707                                            "FROM pg_auth_members a "
708                                            "LEFT JOIN pg_authid ur on ur.oid = a.roleid "
709                                            "LEFT JOIN pg_authid um on um.oid = a.member "
710                                            "LEFT JOIN pg_authid ug on ug.oid = a.grantor "
711                                            "ORDER BY 1,2,3");
712
713         if (PQntuples(res) > 0)
714                 fprintf(OPF, "--\n-- Role memberships\n--\n\n");
715
716         for (i = 0; i < PQntuples(res); i++)
717         {
718                 char       *roleid = PQgetvalue(res, i, 0);
719                 char       *member = PQgetvalue(res, i, 1);
720                 char       *option = PQgetvalue(res, i, 2);
721
722                 fprintf(OPF, "GRANT %s", fmtId(roleid));
723                 fprintf(OPF, " TO %s", fmtId(member));
724                 if (*option == 't')
725                         fprintf(OPF, " WITH ADMIN OPTION");
726
727                 /*
728                  * We don't track the grantor very carefully in the backend, so cope
729                  * with the possibility that it has been dropped.
730                  */
731                 if (!PQgetisnull(res, i, 3))
732                 {
733                         char       *grantor = PQgetvalue(res, i, 3);
734
735                         fprintf(OPF, " GRANTED BY %s", fmtId(grantor));
736                 }
737                 fprintf(OPF, ";\n");
738         }
739
740         PQclear(res);
741
742         fprintf(OPF, "\n\n");
743 }
744
745 /*
746  * Dump group memberships from a pre-8.1 server.  It's annoying that we
747  * can't share any useful amount of code with the post-8.1 case, but
748  * the catalog representations are too different.
749  *
750  * Note: we expect dumpRoles already created all the roles, but there is
751  * no membership yet.
752  */
753 static void
754 dumpGroups(PGconn *conn)
755 {
756         PQExpBuffer buf = createPQExpBuffer();
757         PGresult   *res;
758         int                     i;
759
760         res = executeQuery(conn,
761                                            "SELECT groname, grolist FROM pg_group ORDER BY 1");
762
763         if (PQntuples(res) > 0)
764                 fprintf(OPF, "--\n-- Role memberships\n--\n\n");
765
766         for (i = 0; i < PQntuples(res); i++)
767         {
768                 char       *groname = PQgetvalue(res, i, 0);
769                 char       *grolist = PQgetvalue(res, i, 1);
770                 PGresult   *res2;
771                 int                     j;
772
773                 /*
774                  * Array representation is {1,2,3} ... convert to (1,2,3)
775                  */
776                 if (strlen(grolist) < 3)
777                         continue;
778
779                 grolist = strdup(grolist);
780                 grolist[0] = '(';
781                 grolist[strlen(grolist) - 1] = ')';
782                 printfPQExpBuffer(buf,
783                                                   "SELECT usename FROM pg_shadow "
784                                                   "WHERE usesysid IN %s ORDER BY 1",
785                                                   grolist);
786                 free(grolist);
787
788                 res2 = executeQuery(conn, buf->data);
789
790                 for (j = 0; j < PQntuples(res2); j++)
791                 {
792                         char       *usename = PQgetvalue(res2, j, 0);
793
794                         /*
795                          * Don't try to grant a role to itself; can happen if old
796                          * installation has identically named user and group.
797                          */
798                         if (strcmp(groname, usename) == 0)
799                                 continue;
800
801                         fprintf(OPF, "GRANT %s", fmtId(groname));
802                         fprintf(OPF, " TO %s;\n", fmtId(usename));
803                 }
804
805                 PQclear(res2);
806         }
807
808         PQclear(res);
809         destroyPQExpBuffer(buf);
810
811         fprintf(OPF, "\n\n");
812 }
813
814 /*
815  * Dump tablespaces.
816  */
817 static void
818 dumpTablespaces(PGconn *conn)
819 {
820         PGresult   *res;
821         int                     i;
822
823         /*
824          * Get all tablespaces except built-in ones (which we assume are named
825          * pg_xxx)
826          */
827         if (server_version >= 80200)
828                 res = executeQuery(conn, "SELECT spcname, "
829                                                  "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
830                                                    "spclocation, spcacl, "
831                                                 "pg_catalog.shobj_description(oid, 'pg_tablespace') "
832                                                    "FROM pg_catalog.pg_tablespace "
833                                                    "WHERE spcname !~ '^pg_' "
834                                                    "ORDER BY 1");
835         else
836                 res = executeQuery(conn, "SELECT spcname, "
837                                                  "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
838                                                    "spclocation, spcacl, "
839                                                    "null "
840                                                    "FROM pg_catalog.pg_tablespace "
841                                                    "WHERE spcname !~ '^pg_' "
842                                                    "ORDER BY 1");
843
844         if (PQntuples(res) > 0)
845                 fprintf(OPF, "--\n-- Tablespaces\n--\n\n");
846
847         for (i = 0; i < PQntuples(res); i++)
848         {
849                 PQExpBuffer buf = createPQExpBuffer();
850                 char       *spcname = PQgetvalue(res, i, 0);
851                 char       *spcowner = PQgetvalue(res, i, 1);
852                 char       *spclocation = PQgetvalue(res, i, 2);
853                 char       *spcacl = PQgetvalue(res, i, 3);
854                 char       *spccomment = PQgetvalue(res, i, 4);
855                 char       *fspcname;
856
857                 /* needed for buildACLCommands() */
858                 fspcname = strdup(fmtId(spcname));
859
860                 if (output_clean)
861                         appendPQExpBuffer(buf, "DROP TABLESPACE %s;\n", fspcname);
862
863                 appendPQExpBuffer(buf, "CREATE TABLESPACE %s", fspcname);
864                 appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
865
866                 appendPQExpBuffer(buf, " LOCATION ");
867                 appendStringLiteralConn(buf, spclocation, conn);
868                 appendPQExpBuffer(buf, ";\n");
869
870                 if (!skip_acls &&
871                         !buildACLCommands(fspcname, "TABLESPACE", spcacl, spcowner,
872                                                           server_version, buf))
873                 {
874                         fprintf(stderr, _("%s: could not parse ACL list (%s) for tablespace \"%s\"\n"),
875                                         progname, spcacl, fspcname);
876                         PQfinish(conn);
877                         exit(1);
878                 }
879
880                 if (spccomment && strlen(spccomment))
881                 {
882                         appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
883                         appendStringLiteralConn(buf, spccomment, conn);
884                         appendPQExpBuffer(buf, ";\n");
885                 }
886
887                 fprintf(OPF, "%s", buf->data);
888
889                 free(fspcname);
890                 destroyPQExpBuffer(buf);
891         }
892
893         PQclear(res);
894         fprintf(OPF, "\n\n");
895 }
896
897 /*
898  * Dump commands to create each database.
899  *
900  * To minimize the number of reconnections (and possibly ensuing
901  * password prompts) required by the output script, we emit all CREATE
902  * DATABASE commands during the initial phase of the script, and then
903  * run pg_dump for each database to dump the contents of that
904  * database.  We skip databases marked not datallowconn, since we'd be
905  * unable to connect to them anyway (and besides, we don't want to
906  * dump template0).
907  */
908 static void
909 dumpCreateDB(PGconn *conn)
910 {
911         PQExpBuffer buf = createPQExpBuffer();
912         PGresult   *res;
913         int                     i;
914
915         fprintf(OPF, "--\n-- Database creation\n--\n\n");
916
917         if (server_version >= 80100)
918                 res = executeQuery(conn,
919                                                    "SELECT datname, "
920                                                    "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), "
921                                                    "pg_encoding_to_char(d.encoding), "
922                                                    "datistemplate, datacl, datconnlimit, "
923                                                    "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
924                           "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) "
925                                                    "WHERE datallowconn ORDER BY 1");
926         else if (server_version >= 80000)
927                 res = executeQuery(conn,
928                                                    "SELECT datname, "
929                                                    "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
930                                                    "pg_encoding_to_char(d.encoding), "
931                                                    "datistemplate, datacl, -1 as datconnlimit, "
932                                                    "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
933                    "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
934                                                    "WHERE datallowconn ORDER BY 1");
935         else if (server_version >= 70300)
936                 res = executeQuery(conn,
937                                                    "SELECT datname, "
938                                                    "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
939                                                    "pg_encoding_to_char(d.encoding), "
940                                                    "datistemplate, datacl, -1 as datconnlimit, "
941                                                    "'pg_default' AS dattablespace "
942                    "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
943                                                    "WHERE datallowconn ORDER BY 1");
944         else if (server_version >= 70100)
945                 res = executeQuery(conn,
946                                                    "SELECT datname, "
947                                                    "coalesce("
948                                         "(select usename from pg_shadow where usesysid=datdba), "
949                                                    "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
950                                                    "pg_encoding_to_char(d.encoding), "
951                                                    "datistemplate, '' as datacl, -1 as datconnlimit, "
952                                                    "'pg_default' AS dattablespace "
953                                                    "FROM pg_database d "
954                                                    "WHERE datallowconn ORDER BY 1");
955         else
956         {
957                 /*
958                  * Note: 7.0 fails to cope with sub-select in COALESCE, so just deal
959                  * with getting a NULL by not printing any OWNER clause.
960                  */
961                 res = executeQuery(conn,
962                                                    "SELECT datname, "
963                                         "(select usename from pg_shadow where usesysid=datdba), "
964                                                    "pg_encoding_to_char(d.encoding), "
965                                                    "'f' as datistemplate, "
966                                                    "'' as datacl, -1 as datconnlimit, "
967                                                    "'pg_default' AS dattablespace "
968                                                    "FROM pg_database d "
969                                                    "ORDER BY 1");
970         }
971
972         for (i = 0; i < PQntuples(res); i++)
973         {
974                 char       *dbname = PQgetvalue(res, i, 0);
975                 char       *dbowner = PQgetvalue(res, i, 1);
976                 char       *dbencoding = PQgetvalue(res, i, 2);
977                 char       *dbistemplate = PQgetvalue(res, i, 3);
978                 char       *dbacl = PQgetvalue(res, i, 4);
979                 char       *dbconnlimit = PQgetvalue(res, i, 5);
980                 char       *dbtablespace = PQgetvalue(res, i, 6);
981                 char       *fdbname;
982
983                 fdbname = strdup(fmtId(dbname));
984
985                 resetPQExpBuffer(buf);
986
987                 /*
988                  * Skip the CREATE DATABASE commands for "template1" and "postgres",
989                  * since they are presumably already there in the destination cluster.
990                  * We do want to emit their ACLs and config options if any, however.
991                  */
992                 if (strcmp(dbname, "template1") != 0 &&
993                         strcmp(dbname, "postgres") != 0)
994                 {
995                         if (output_clean)
996                                 appendPQExpBuffer(buf, "DROP DATABASE %s;\n", fdbname);
997
998                         appendPQExpBuffer(buf, "CREATE DATABASE %s", fdbname);
999
1000                         appendPQExpBuffer(buf, " WITH TEMPLATE = template0");
1001
1002                         if (strlen(dbowner) != 0)
1003                                 appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner));
1004
1005                         appendPQExpBuffer(buf, " ENCODING = ");
1006                         appendStringLiteralConn(buf, dbencoding, conn);
1007
1008                         /*
1009                          * Output tablespace if it isn't the default.  For default, it
1010                          * uses the default from the template database.  If tablespace is
1011                          * specified and tablespace creation failed earlier, (e.g. no such
1012                          * directory), the database creation will fail too.  One solution
1013                          * would be to use 'SET default_tablespace' like we do in pg_dump
1014                          * for setting non-default database locations.
1015                          */
1016                         if (strcmp(dbtablespace, "pg_default") != 0)
1017                                 appendPQExpBuffer(buf, " TABLESPACE = %s",
1018                                                                   fmtId(dbtablespace));
1019
1020                         if (strcmp(dbconnlimit, "-1") != 0)
1021                                 appendPQExpBuffer(buf, " CONNECTION LIMIT = %s",
1022                                                                   dbconnlimit);
1023
1024                         appendPQExpBuffer(buf, ";\n");
1025
1026                         if (strcmp(dbistemplate, "t") == 0)
1027                         {
1028                                 appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = ");
1029                                 appendStringLiteralConn(buf, dbname, conn);
1030                                 appendPQExpBuffer(buf, ";\n");
1031                         }
1032                 }
1033
1034                 if (!skip_acls &&
1035                         !buildACLCommands(fdbname, "DATABASE", dbacl, dbowner,
1036                                                           server_version, buf))
1037                 {
1038                         fprintf(stderr, _("%s: could not parse ACL list (%s) for database \"%s\"\n"),
1039                                         progname, dbacl, fdbname);
1040                         PQfinish(conn);
1041                         exit(1);
1042                 }
1043
1044                 fprintf(OPF, "%s", buf->data);
1045
1046                 if (server_version >= 70300)
1047                         dumpDatabaseConfig(conn, dbname);
1048
1049                 free(fdbname);
1050         }
1051
1052         PQclear(res);
1053         destroyPQExpBuffer(buf);
1054
1055         fprintf(OPF, "\n\n");
1056 }
1057
1058
1059
1060 /*
1061  * Dump database-specific configuration
1062  */
1063 static void
1064 dumpDatabaseConfig(PGconn *conn, const char *dbname)
1065 {
1066         PQExpBuffer buf = createPQExpBuffer();
1067         int                     count = 1;
1068
1069         for (;;)
1070         {
1071                 PGresult   *res;
1072
1073                 printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count);
1074                 appendStringLiteralConn(buf, dbname, conn);
1075                 appendPQExpBuffer(buf, ";");
1076
1077                 res = executeQuery(conn, buf->data);
1078                 if (!PQgetisnull(res, 0, 0))
1079                 {
1080                         makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
1081                                                                    "DATABASE", dbname);
1082                         PQclear(res);
1083                         count++;
1084                 }
1085                 else
1086                 {
1087                         PQclear(res);
1088                         break;
1089                 }
1090         }
1091
1092         destroyPQExpBuffer(buf);
1093 }
1094
1095
1096
1097 /*
1098  * Dump user-specific configuration
1099  */
1100 static void
1101 dumpUserConfig(PGconn *conn, const char *username)
1102 {
1103         PQExpBuffer buf = createPQExpBuffer();
1104         int                     count = 1;
1105
1106         for (;;)
1107         {
1108                 PGresult   *res;
1109
1110                 if (server_version >= 80100)
1111                         printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM pg_authid WHERE rolname = ", count);
1112                 else
1113                         printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
1114                 appendStringLiteralConn(buf, username, conn);
1115
1116                 res = executeQuery(conn, buf->data);
1117                 if (PQntuples(res) == 1 &&
1118                         !PQgetisnull(res, 0, 0))
1119                 {
1120                         makeAlterConfigCommand(conn, PQgetvalue(res, 0, 0),
1121                                                                    "ROLE", username);
1122                         PQclear(res);
1123                         count++;
1124                 }
1125                 else
1126                 {
1127                         PQclear(res);
1128                         break;
1129                 }
1130         }
1131
1132         destroyPQExpBuffer(buf);
1133 }
1134
1135
1136
1137 /*
1138  * Helper function for dumpXXXConfig().
1139  */
1140 static void
1141 makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
1142                                            const char *type, const char *name)
1143 {
1144         char       *pos;
1145         char       *mine;
1146         PQExpBuffer buf = createPQExpBuffer();
1147
1148         mine = strdup(arrayitem);
1149         pos = strchr(mine, '=');
1150         if (pos == NULL)
1151                 return;
1152
1153         *pos = 0;
1154         appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name));
1155         appendPQExpBuffer(buf, "SET %s TO ", fmtId(mine));
1156
1157         /*
1158          * Some GUC variable names are 'LIST' type and hence must not be quoted.
1159          */
1160         if (pg_strcasecmp(mine, "DateStyle") == 0
1161                 || pg_strcasecmp(mine, "search_path") == 0)
1162                 appendPQExpBuffer(buf, "%s", pos + 1);
1163         else
1164                 appendStringLiteralConn(buf, pos + 1, conn);
1165         appendPQExpBuffer(buf, ";\n");
1166
1167         fprintf(OPF, "%s", buf->data);
1168         destroyPQExpBuffer(buf);
1169         free(mine);
1170 }
1171
1172
1173
1174 /*
1175  * Dump contents of databases.
1176  */
1177 static void
1178 dumpDatabases(PGconn *conn)
1179 {
1180         PGresult   *res;
1181         int                     i;
1182
1183         if (server_version >= 70100)
1184                 res = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1");
1185         else
1186                 res = executeQuery(conn, "SELECT datname FROM pg_database ORDER BY 1");
1187
1188         for (i = 0; i < PQntuples(res); i++)
1189         {
1190                 int                     ret;
1191
1192                 char       *dbname = PQgetvalue(res, i, 0);
1193
1194                 if (verbose)
1195                         fprintf(stderr, _("%s: dumping database \"%s\"...\n"), progname, dbname);
1196
1197                 fprintf(OPF, "\\connect %s\n\n", fmtId(dbname));
1198
1199                 if (filename)
1200                         fclose(OPF);
1201
1202                 ret = runPgDump(dbname);
1203                 if (ret != 0)
1204                 {
1205                         fprintf(stderr, _("%s: pg_dump failed on database \"%s\", exiting\n"), progname, dbname);
1206                         exit(1);
1207                 }
1208
1209                 if (filename)
1210                 {
1211                         OPF = fopen(filename, PG_BINARY_A);
1212                         if (!OPF)
1213                         {
1214                                 fprintf(stderr, _("%s: could not re-open the output file \"%s\": %s\n"),
1215                                                 progname, filename, strerror(errno));
1216                                 exit(1);
1217                         }
1218                 }
1219
1220         }
1221
1222         PQclear(res);
1223 }
1224
1225
1226
1227 /*
1228  * Run pg_dump on dbname.
1229  */
1230 static int
1231 runPgDump(const char *dbname)
1232 {
1233         PQExpBuffer cmd = createPQExpBuffer();
1234         const char *p;
1235         int                     ret;
1236
1237         /*
1238          * Win32 has to use double-quotes for args, rather than single quotes.
1239          * Strangely enough, this is the only place we pass a database name on the
1240          * command line, except "postgres" which doesn't need quoting.
1241          *
1242          * If we have a filename, use the undocumented plain-append pg_dump
1243          * format.
1244          */
1245         if (filename)
1246         {
1247 #ifndef WIN32
1248                 appendPQExpBuffer(cmd, "%s\"%s\" %s -Fa '", SYSTEMQUOTE, pg_dump_bin,
1249 #else
1250                 appendPQExpBuffer(cmd, "%s\"%s\" %s -Fa \"", SYSTEMQUOTE, pg_dump_bin,
1251 #endif
1252                                                   pgdumpopts->data);
1253         }
1254         else
1255         {
1256 #ifndef WIN32
1257                 appendPQExpBuffer(cmd, "%s\"%s\" %s -Fp '", SYSTEMQUOTE, pg_dump_bin,
1258 #else
1259                 appendPQExpBuffer(cmd, "%s\"%s\" %s -Fp \"", SYSTEMQUOTE, pg_dump_bin,
1260 #endif
1261                                                   pgdumpopts->data);
1262         }
1263
1264
1265         /* Shell quoting is not quite like SQL quoting, so can't use fmtId */
1266         for (p = dbname; *p; p++)
1267         {
1268 #ifndef WIN32
1269                 if (*p == '\'')
1270                         appendPQExpBuffer(cmd, "'\"'\"'");
1271 #else
1272                 if (*p == '"')
1273                         appendPQExpBuffer(cmd, "\\\"");
1274 #endif
1275                 else
1276                         appendPQExpBufferChar(cmd, *p);
1277         }
1278
1279 #ifndef WIN32
1280         appendPQExpBufferChar(cmd, '\'');
1281 #else
1282         appendPQExpBufferChar(cmd, '"');
1283 #endif
1284
1285         appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE);
1286
1287         if (verbose)
1288                 fprintf(stderr, _("%s: running \"%s\"\n"), progname, cmd->data);
1289
1290         fflush(stdout);
1291         fflush(stderr);
1292
1293         ret = system(cmd->data);
1294
1295         destroyPQExpBuffer(cmd);
1296
1297         return ret;
1298 }
1299
1300
1301
1302 /*
1303  * Make a database connection with the given parameters.  An
1304  * interactive password prompt is automatically issued if required.
1305  *
1306  * If fail_on_error is false, we return NULL without printing any message
1307  * on failure, but preserve any prompted password for the next try.
1308  */
1309 static PGconn *
1310 connectDatabase(const char *dbname, const char *pghost, const char *pgport,
1311                                 const char *pguser, bool require_password, bool fail_on_error)
1312 {
1313         PGconn     *conn;
1314         bool            new_pass;
1315         const char *remoteversion_str;
1316         int                     my_version;
1317         static char *password = NULL;
1318
1319         if (require_password && !password)
1320                 password = simple_prompt("Password: ", 100, false);
1321
1322         /*
1323          * Start the connection.  Loop until we have a password if requested by
1324          * backend.
1325          */
1326         do
1327         {
1328                 new_pass = false;
1329                 conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password);
1330
1331                 if (!conn)
1332                 {
1333                         fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
1334                                         progname, dbname);
1335                         exit(1);
1336                 }
1337
1338                 if (PQstatus(conn) == CONNECTION_BAD &&
1339                         PQconnectionNeedsPassword(conn) &&
1340                         password == NULL &&
1341                         !feof(stdin))
1342                 {
1343                         PQfinish(conn);
1344                         password = simple_prompt("Password: ", 100, false);
1345                         new_pass = true;
1346                 }
1347         } while (new_pass);
1348
1349         /* check to see that the backend connection was successfully made */
1350         if (PQstatus(conn) == CONNECTION_BAD)
1351         {
1352                 if (fail_on_error)
1353                 {
1354                         fprintf(stderr,
1355                                         _("%s: could not connect to database \"%s\": %s\n"),
1356                                         progname, dbname, PQerrorMessage(conn));
1357                         exit(1);
1358                 }
1359                 else
1360                 {
1361                         PQfinish(conn);
1362                         return NULL;
1363                 }
1364         }
1365
1366         remoteversion_str = PQparameterStatus(conn, "server_version");
1367         if (!remoteversion_str)
1368         {
1369                 fprintf(stderr, _("%s: could not get server version\n"), progname);
1370                 exit(1);
1371         }
1372         server_version = parse_version(remoteversion_str);
1373         if (server_version < 0)
1374         {
1375                 fprintf(stderr, _("%s: could not parse server version \"%s\"\n"),
1376                                 progname, remoteversion_str);
1377                 exit(1);
1378         }
1379
1380         my_version = parse_version(PG_VERSION);
1381         if (my_version < 0)
1382         {
1383                 fprintf(stderr, _("%s: could not parse version \"%s\"\n"),
1384                                 progname, PG_VERSION);
1385                 exit(1);
1386         }
1387
1388         if (my_version != server_version
1389                 && (server_version < 70000              /* we can handle back to 7.0 */
1390                         || server_version > my_version))
1391         {
1392                 fprintf(stderr, _("server version: %s; %s version: %s\n"),
1393                                 remoteversion_str, progname, PG_VERSION);
1394                 if (ignoreVersion)
1395                         fprintf(stderr, _("proceeding despite version mismatch\n"));
1396                 else
1397                 {
1398                         fprintf(stderr, _("aborting because of version mismatch  (Use the -i option to proceed anyway.)\n"));
1399                         exit(1);
1400                 }
1401         }
1402
1403         /*
1404          * On 7.3 and later, make sure we are not fooled by non-system schemas in
1405          * the search path.
1406          */
1407         if (server_version >= 70300)
1408                 executeCommand(conn, "SET search_path = pg_catalog");
1409
1410         return conn;
1411 }
1412
1413
1414 /*
1415  * Run a query, return the results, exit program on failure.
1416  */
1417 static PGresult *
1418 executeQuery(PGconn *conn, const char *query)
1419 {
1420         PGresult   *res;
1421
1422         if (verbose)
1423                 fprintf(stderr, _("%s: executing %s\n"), progname, query);
1424
1425         res = PQexec(conn, query);
1426         if (!res ||
1427                 PQresultStatus(res) != PGRES_TUPLES_OK)
1428         {
1429                 fprintf(stderr, _("%s: query failed: %s"),
1430                                 progname, PQerrorMessage(conn));
1431                 fprintf(stderr, _("%s: query was: %s\n"),
1432                                 progname, query);
1433                 PQfinish(conn);
1434                 exit(1);
1435         }
1436
1437         return res;
1438 }
1439
1440 /*
1441  * As above for a SQL command (which returns nothing).
1442  */
1443 static void
1444 executeCommand(PGconn *conn, const char *query)
1445 {
1446         PGresult   *res;
1447
1448         if (verbose)
1449                 fprintf(stderr, _("%s: executing %s\n"), progname, query);
1450
1451         res = PQexec(conn, query);
1452         if (!res ||
1453                 PQresultStatus(res) != PGRES_COMMAND_OK)
1454         {
1455                 fprintf(stderr, _("%s: query failed: %s"),
1456                                 progname, PQerrorMessage(conn));
1457                 fprintf(stderr, _("%s: query was: %s\n"),
1458                                 progname, query);
1459                 PQfinish(conn);
1460                 exit(1);
1461         }
1462
1463         PQclear(res);
1464 }
1465
1466
1467 /*
1468  * dumpTimestamp
1469  */
1470 static void
1471 dumpTimestamp(char *msg)
1472 {
1473         char            buf[256];
1474         time_t          now = time(NULL);
1475
1476         /*
1477          * We don't print the timezone on Win32, because the names are long and
1478          * localized, which means they may contain characters in various random
1479          * encodings; this has been seen to cause encoding errors when reading the
1480          * dump script.
1481          */
1482         if (strftime(buf, sizeof(buf),
1483 #ifndef WIN32
1484                                  "%Y-%m-%d %H:%M:%S %Z",
1485 #else
1486                                  "%Y-%m-%d %H:%M:%S",
1487 #endif
1488                                  localtime(&now)) != 0)
1489                 fprintf(OPF, "-- %s %s\n\n", msg, buf);
1490 }