]> granicus.if.org Git - postgresql/blob - src/bin/pg_dump/pg_dumpall.c
Use single quotes around pg_dump call from pg_dumpall.
[postgresql] / src / bin / pg_dump / pg_dumpall.c
1 /*-------------------------------------------------------------------------
2  *
3  * pg_dumpall
4  *
5  * Portions Copyright (c) 1996-2003, 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.40 2004/06/09 17:37:28 momjian Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13
14 #include "postgres_fe.h"
15
16 #include <unistd.h>
17 #ifdef ENABLE_NLS
18 #include <locale.h>
19 #endif
20 #ifndef HAVE_STRDUP
21 #include "strdup.h"
22 #endif
23 #include <errno.h>
24 #include <time.h>
25
26 #include "getopt_long.h"
27
28 #ifndef HAVE_OPTRESET
29 int                     optreset;
30 #endif
31
32 #include "dumputils.h"
33 #include "libpq-fe.h"
34 #include "pg_backup.h"
35 #include "pqexpbuffer.h"
36
37 #define _(x) gettext((x))
38
39 /* version string we expect back from postgres */
40 #define PG_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
41
42
43 static const char *progname;
44
45 static void help(void);
46
47 static void dumpUsers(PGconn *conn);
48 static void dumpGroups(PGconn *conn);
49 static void dumpCreateDB(PGconn *conn);
50 static void dumpDatabaseConfig(PGconn *conn, const char *dbname);
51 static void dumpUserConfig(PGconn *conn, const char *username);
52 static void makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name);
53 static void dumpDatabases(PGconn *conn);
54 static void dumpTimestamp(char *msg);
55
56 static int      runPgDump(const char *dbname);
57 static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
58                                 const char *pguser, bool require_password);
59 static PGresult *executeQuery(PGconn *conn, const char *query);
60
61
62 char        pg_dump_bin[MAXPGPATH];
63 PQExpBuffer pgdumpopts;
64 bool            output_clean = false;
65 bool            skip_acls = false;
66 bool            verbose = false;
67 int                     server_version;
68
69
70
71 int
72 main(int argc, char *argv[])
73 {
74         char       *pghost = NULL;
75         char       *pgport = NULL;
76         char       *pguser = NULL;
77         bool            force_password = false;
78         bool            data_only = false;
79         bool            globals_only = false;
80         bool            schema_only = false;
81         PGconn     *conn;
82         int                     c, ret;
83
84         static struct option long_options[] = {
85                 {"data-only", no_argument, NULL, 'a'},
86                 {"clean", no_argument, NULL, 'c'},
87                 {"inserts", no_argument, NULL, 'd'},
88                 {"attribute-inserts", no_argument, NULL, 'D'},
89                 {"column-inserts", no_argument, NULL, 'D'},
90                 {"globals-only", no_argument, NULL, 'g'},
91                 {"host", required_argument, NULL, 'h'},
92                 {"ignore-version", no_argument, NULL, 'i'},
93                 {"oids", no_argument, NULL, 'o'},
94                 {"port", required_argument, NULL, 'p'},
95                 {"password", no_argument, NULL, 'W'},
96                 {"schema-only", no_argument, NULL, 's'},
97                 {"username", required_argument, NULL, 'U'},
98                 {"verbose", no_argument, NULL, 'v'},
99                 {"no-privileges", no_argument, NULL, 'x'},
100                 {"no-acl", no_argument, NULL, 'x'},
101                 {NULL, 0, NULL, 0}
102         };
103
104         int                     optindex;
105
106         set_pglocale_pgservice(argv[0], "pg_dump");
107
108         progname = get_progname(argv[0]);
109
110         if (argc > 1)
111         {
112                 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
113                 {
114                         help();
115                         exit(0);
116                 }
117                 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
118                 {
119                         puts("pg_dumpall (PostgreSQL) " PG_VERSION);
120                         exit(0);
121                 }
122         }
123
124         if ((ret = find_other_exec(argv[0], "pg_dump", PG_VERSIONSTR,
125                                                            pg_dump_bin)) < 0)
126         {
127                 if (ret == -1)
128                         fprintf(stderr,
129                                                 _("The program \"pg_dump\" is needed by %s "
130                                                 "but was not found in the same directory as \"%s\".\n"
131                                                 "Check your installation.\n"),
132                                                 progname, progname);
133                 else
134                         fprintf(stderr,
135                                                 _("The program \"pg_dump\" was found by %s "
136                                                 "but was not the same version as \"%s\".\n"
137                                                 "Check your installation.\n"),
138                                                 progname, progname);
139                 exit(1);
140         }
141
142         pgdumpopts = createPQExpBuffer();
143
144         while ((c = getopt_long(argc, argv, "acdDgh:iop:sU:vWx", long_options, &optindex)) != -1)
145         {
146                 switch (c)
147                 {
148                         case 'a':
149                                 data_only = true;
150                                 appendPQExpBuffer(pgdumpopts, " -a");
151                                 break;
152
153                         case 'c':
154                                 output_clean = true;
155                                 break;
156
157                         case 'd':
158                         case 'D':
159                                 appendPQExpBuffer(pgdumpopts, " -%c", c);
160                                 break;
161
162                         case 'g':
163                                 globals_only = true;
164                                 break;
165
166                         case 'h':
167                                 pghost = optarg;
168                                 appendPQExpBuffer(pgdumpopts, " -h '%s'", pghost);
169                                 break;
170
171                         case 'i':
172                         case 'o':
173                                 appendPQExpBuffer(pgdumpopts, " -%c", c);
174                                 break;
175
176                         case 'p':
177                                 pgport = optarg;
178                                 appendPQExpBuffer(pgdumpopts, " -p '%s'", pgport);
179                                 break;
180
181                         case 's':
182                                 schema_only = true;
183                                 appendPQExpBuffer(pgdumpopts, " -s");
184                                 break;
185
186                         case 'U':
187                                 pguser = optarg;
188                                 appendPQExpBuffer(pgdumpopts, " -U '%s'", pguser);
189                                 break;
190
191                         case 'v':
192                                 verbose = true;
193                                 appendPQExpBuffer(pgdumpopts, " -v");
194                                 break;
195
196                         case 'W':
197                                 force_password = true;
198                                 appendPQExpBuffer(pgdumpopts, " -W");
199                                 break;
200
201                         case 'x':
202                                 skip_acls = true;
203                                 appendPQExpBuffer(pgdumpopts, " -x");
204                                 break;
205
206                         default:
207                                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
208                                 exit(1);
209                 }
210         }
211
212         if (optind < argc)
213         {
214                 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
215                                 progname, argv[optind]);
216                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
217                                 progname);
218                 exit(1);
219         }
220
221
222         conn = connectDatabase("template1", pghost, pgport, pguser, force_password);
223
224         printf("--\n-- PostgreSQL database cluster dump\n--\n\n");
225         if (verbose)
226                         dumpTimestamp("Started on");
227
228         printf("\\connect \"template1\"\n\n");
229
230         if (!data_only)
231         {
232                 dumpUsers(conn);
233                 dumpGroups(conn);
234         }
235
236         if (!globals_only)
237         {
238                 if (!data_only)
239                         dumpCreateDB(conn);
240                 dumpDatabases(conn);
241         }
242
243         PQfinish(conn);
244
245         if (verbose)
246                 dumpTimestamp("Completed on");
247         printf("--\n-- PostgreSQL database cluster dump complete\n--\n\n");
248
249         exit(0);
250 }
251
252
253
254 static void
255 help(void)
256 {
257         printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname);
258         printf(_("Usage:\n"));
259         printf(_("  %s [OPTION]...\n"), progname);
260
261         printf(_("\nOptions:\n"));
262         printf(_("  -a, --data-only          dump only the data, not the schema\n"));
263         printf(_("  -c, --clean              clean (drop) databases prior to create\n"));
264         printf(_("  -d, --inserts            dump data as INSERT, rather than COPY, commands\n"));
265         printf(_("  -D, --column-inserts     dump data as INSERT commands with column names\n"));
266         printf(_("  -g, --globals-only       dump only global objects, no databases\n"));
267         printf(_("  -i, --ignore-version     proceed even when server version mismatches\n"
268                          "                           pg_dumpall version\n"));
269         printf(_("  -s, --schema-only        dump only the schema, no data\n"));
270         printf(_("  -o, --oids               include OIDs in dump\n"));
271         printf(_("  -v, --verbose            verbose mode\n"));
272         printf(_("  -x, --no-privileges      do not dump privileges (grant/revoke)\n"));
273         printf(_("  --help                   show this help, then exit\n"));
274         printf(_("  --version                output version information, then exit\n"));
275
276         printf(_("\nConnection options:\n"));
277         printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
278         printf(_("  -p, --port=PORT          database server port number\n"));
279         printf(_("  -U, --username=NAME      connect as specified database user\n"));
280         printf(_("  -W, --password           force password prompt (should happen automatically)\n"));
281
282         printf(_("\nThe SQL script will be written to the standard output.\n\n"));
283         printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
284 }
285
286
287
288 /*
289  * Dump users (but not the user created by initdb).
290  */
291 static void
292 dumpUsers(PGconn *conn)
293 {
294         PGresult   *res;
295         int                     i;
296
297         printf("--\n-- Users\n--\n\n");
298         printf("DELETE FROM pg_shadow WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');\n\n");
299
300         if (server_version >= 70100)
301                 res = executeQuery(conn,
302                                                 "SELECT usename, usesysid, passwd, usecreatedb, "
303                                                    "usesuper, valuntil "
304                                                    "FROM pg_shadow "
305                                                    "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0')");
306         else
307                 res = executeQuery(conn,
308                                                 "SELECT usename, usesysid, passwd, usecreatedb, "
309                                                    "usesuper, valuntil "
310                                                    "FROM pg_shadow "
311                                                    "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template1')");
312
313         for (i = 0; i < PQntuples(res); i++)
314         {
315                 PQExpBuffer buf = createPQExpBuffer();
316                 const char *username;
317
318                 username = PQgetvalue(res, i, 0);
319                 appendPQExpBuffer(buf, "CREATE USER %s WITH SYSID %s",
320                                                   fmtId(username),
321                                                   PQgetvalue(res, i, 1));
322
323                 if (!PQgetisnull(res, i, 2))
324                 {
325                         appendPQExpBuffer(buf, " PASSWORD ");
326                         appendStringLiteral(buf, PQgetvalue(res, i, 2), true);
327                 }
328
329                 if (strcmp(PQgetvalue(res, i, 3), "t") == 0)
330                         appendPQExpBuffer(buf, " CREATEDB");
331                 else
332                         appendPQExpBuffer(buf, " NOCREATEDB");
333
334                 if (strcmp(PQgetvalue(res, i, 4), "t") == 0)
335                         appendPQExpBuffer(buf, " CREATEUSER");
336                 else
337                         appendPQExpBuffer(buf, " NOCREATEUSER");
338
339                 if (!PQgetisnull(res, i, 5))
340                         appendPQExpBuffer(buf, " VALID UNTIL '%s'",
341                                                           PQgetvalue(res, i, 5));
342
343                 appendPQExpBuffer(buf, ";\n");
344
345                 printf("%s", buf->data);
346                 destroyPQExpBuffer(buf);
347
348                 if (server_version >= 70300)
349                         dumpUserConfig(conn, username);
350         }
351
352         PQclear(res);
353         printf("\n\n");
354 }
355
356
357
358 /*
359  * Dump groups.
360  */
361 static void
362 dumpGroups(PGconn *conn)
363 {
364         PGresult   *res;
365         int                     i;
366
367         printf("--\n-- Groups\n--\n\n");
368         printf("DELETE FROM pg_group;\n\n");
369
370         res = executeQuery(conn, "SELECT groname, grosysid, grolist FROM pg_group");
371
372         for (i = 0; i < PQntuples(res); i++)
373         {
374                 PQExpBuffer buf = createPQExpBuffer();
375                 char       *val;
376                 char       *tok;
377
378                 appendPQExpBuffer(buf, "CREATE GROUP %s WITH SYSID %s;\n",
379                                                   fmtId(PQgetvalue(res, i, 0)),
380                                                   PQgetvalue(res, i, 1));
381
382                 val = strdup(PQgetvalue(res, i, 2));
383                 tok = strtok(val, ",{}");
384                 while (tok)
385                 {
386                         PGresult   *res2;
387                         PQExpBuffer buf2 = createPQExpBuffer();
388                         int                     j;
389
390                         appendPQExpBuffer(buf2, "SELECT usename FROM pg_shadow WHERE usesysid = %s;", tok);
391                         res2 = executeQuery(conn, buf2->data);
392                         destroyPQExpBuffer(buf2);
393
394                         for (j = 0; j < PQntuples(res2); j++)
395                         {
396                                 appendPQExpBuffer(buf, "ALTER GROUP %s ", fmtId(PQgetvalue(res, i, 0)));
397                                 appendPQExpBuffer(buf, "ADD USER %s;\n", fmtId(PQgetvalue(res2, j, 0)));
398                         }
399
400                         PQclear(res2);
401
402                         tok = strtok(NULL, "{},");
403                 }
404                 free(val);
405
406                 printf("%s", buf->data);
407                 destroyPQExpBuffer(buf);
408         }
409
410         PQclear(res);
411         printf("\n\n");
412 }
413
414
415
416 /*
417  * Dump commands to create each database.
418  *
419  * To minimize the number of reconnections (and possibly ensuing
420  * password prompts) required by the output script, we emit all CREATE
421  * DATABASE commands during the initial phase of the script, and then
422  * run pg_dump for each database to dump the contents of that
423  * database.  We skip databases marked not datallowconn, since we'd be
424  * unable to connect to them anyway (and besides, we don't want to
425  * dump template0).
426  */
427 static void
428 dumpCreateDB(PGconn *conn)
429 {
430         PGresult   *res;
431         int                     i;
432
433         printf("--\n-- Database creation\n--\n\n");
434
435         if (server_version >= 70300)
436                 res = executeQuery(conn,
437                                                    "SELECT datname, "
438                                                    "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
439                                                    "pg_encoding_to_char(d.encoding), "
440                                                    "datistemplate, datpath, datacl "
441                 "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
442                                                    "WHERE datallowconn ORDER BY 1");
443         else if (server_version >= 70100)
444                 res = executeQuery(conn,
445                                                    "SELECT datname, "
446                                                    "coalesce("
447                                 "(select usename from pg_shadow where usesysid=datdba), "
448                                                    "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
449                                                    "pg_encoding_to_char(d.encoding), "
450                                                    "datistemplate, datpath, '' as datacl "
451                                                    "FROM pg_database d "
452                                                    "WHERE datallowconn ORDER BY 1");
453         else
454         {
455                 /*
456                  * In 7.0, datpath is either the same as datname, or the user-given
457                  * location with "/" and the datname appended.  We must strip this
458                  * junk off to produce a correct LOCATION value.
459                  *
460                  * Note: 7.0 fails to cope with sub-select in COALESCE, so just
461                  * deal with getting a NULL by not printing any OWNER clause.
462                  */
463                 res = executeQuery(conn,
464                                                    "SELECT datname, "
465                                 "(select usename from pg_shadow where usesysid=datdba), "
466                                                    "pg_encoding_to_char(d.encoding), "
467                                                    "'f' as datistemplate, "
468                                                    "CASE WHEN length(datpath) > length(datname) THEN "
469                                                    "substr(datpath,1,length(datpath)-length(datname)-1) "
470                                                    "ELSE '' END as datpath, "
471                                                    "'' as datacl "
472                                                    "FROM pg_database d "
473                                                    "ORDER BY 1");
474         }
475
476         for (i = 0; i < PQntuples(res); i++)
477         {
478                 PQExpBuffer buf;
479                 char       *dbname = PQgetvalue(res, i, 0);
480                 char       *dbowner = PQgetvalue(res, i, 1);
481                 char       *dbencoding = PQgetvalue(res, i, 2);
482                 char       *dbistemplate = PQgetvalue(res, i, 3);
483                 char       *dbpath = PQgetvalue(res, i, 4);
484                 char       *dbacl = PQgetvalue(res, i, 5);
485                 char       *fdbname;
486
487                 if (strcmp(dbname, "template1") == 0)
488                         continue;
489
490                 buf = createPQExpBuffer();
491
492                 /* needed for buildACLCommands() */
493                 fdbname = strdup(fmtId(dbname));
494
495                 if (output_clean)
496                         appendPQExpBuffer(buf, "DROP DATABASE %s;\n", fdbname);
497
498                 appendPQExpBuffer(buf, "CREATE DATABASE %s", fdbname);
499                 if (strlen(dbowner) != 0)
500                         appendPQExpBuffer(buf, " WITH OWNER = %s",
501                                                           fmtId(dbowner));
502                 appendPQExpBuffer(buf, " TEMPLATE = template0");
503
504                 if (strlen(dbpath) != 0)
505                 {
506                         appendPQExpBuffer(buf, " LOCATION = ");
507                         appendStringLiteral(buf, dbpath, true);
508                 }
509
510                 appendPQExpBuffer(buf, " ENCODING = ");
511                 appendStringLiteral(buf, dbencoding, true);
512
513                 appendPQExpBuffer(buf, ";\n");
514
515                 if (strcmp(dbistemplate, "t") == 0)
516                 {
517                         appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = ");
518                         appendStringLiteral(buf, dbname, true);
519                         appendPQExpBuffer(buf, ";\n");
520                 }
521
522                 if (!skip_acls &&
523                         !buildACLCommands(fdbname, "DATABASE", dbacl, dbowner,
524                                                           server_version, buf))
525                 {
526                         fprintf(stderr, _("%s: could not parse ACL list (%s) for database \"%s\"\n"),
527                                         progname, dbacl, fdbname);
528                         PQfinish(conn);
529                         exit(1);
530                 }
531
532                 printf("%s", buf->data);
533                 destroyPQExpBuffer(buf);
534                 free(fdbname);
535
536                 if (server_version >= 70300)
537                         dumpDatabaseConfig(conn, dbname);
538         }
539
540         PQclear(res);
541         printf("\n\n");
542 }
543
544
545
546 /*
547  * Dump database-specific configuration
548  */
549 static void
550 dumpDatabaseConfig(PGconn *conn, const char *dbname)
551 {
552         PQExpBuffer buf = createPQExpBuffer();
553         int                     count = 1;
554
555         for (;;)
556         {
557                 PGresult   *res;
558
559                 printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count);
560                 appendStringLiteral(buf, dbname, true);
561                 appendPQExpBuffer(buf, ";");
562
563                 res = executeQuery(conn, buf->data);
564                 if (!PQgetisnull(res, 0, 0))
565                 {
566                         makeAlterConfigCommand(PQgetvalue(res, 0, 0), "DATABASE", dbname);
567                         PQclear(res);
568                         count++;
569                 }
570                 else
571                 {
572                         PQclear(res);
573                         break;
574                 }
575         }
576
577         destroyPQExpBuffer(buf);
578 }
579
580
581
582 /*
583  * Dump user-specific configuration
584  */
585 static void
586 dumpUserConfig(PGconn *conn, const char *username)
587 {
588         PQExpBuffer buf = createPQExpBuffer();
589         int                     count = 1;
590
591         for (;;)
592         {
593                 PGresult   *res;
594
595                 printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
596                 appendStringLiteral(buf, username, true);
597                 appendPQExpBuffer(buf, ";");
598
599                 res = executeQuery(conn, buf->data);
600                 if (!PQgetisnull(res, 0, 0))
601                 {
602                         makeAlterConfigCommand(PQgetvalue(res, 0, 0), "USER", username);
603                         PQclear(res);
604                         count++;
605                 }
606                 else
607                 {
608                         PQclear(res);
609                         break;
610                 }
611         }
612
613         destroyPQExpBuffer(buf);
614 }
615
616
617
618 /*
619  * Helper function for dumpXXXConfig().
620  */
621 static void
622 makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name)
623 {
624         char       *pos;
625         char       *mine;
626         PQExpBuffer buf = createPQExpBuffer();
627
628         mine = strdup(arrayitem);
629         pos = strchr(mine, '=');
630         if (pos == NULL)
631                 return;
632
633         *pos = 0;
634         appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name));
635         appendPQExpBuffer(buf, "SET %s TO ", fmtId(mine));
636         appendStringLiteral(buf, pos + 1, false);
637         appendPQExpBuffer(buf, ";\n");
638
639         printf("%s", buf->data);
640         destroyPQExpBuffer(buf);
641         free(mine);
642 }
643
644
645
646 /*
647  * Dump contents of databases.
648  */
649 static void
650 dumpDatabases(PGconn *conn)
651 {
652         PGresult   *res;
653         int                     i;
654
655         if (server_version >= 70100)
656                 res = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1");
657         else
658                 res = executeQuery(conn, "SELECT datname FROM pg_database ORDER BY 1");
659
660         for (i = 0; i < PQntuples(res); i++)
661         {
662                 int                     ret;
663
664                 char       *dbname = PQgetvalue(res, i, 0);
665
666                 if (verbose)
667                         fprintf(stderr, _("%s: dumping database \"%s\"...\n"), progname, dbname);
668
669                 printf("\\connect %s\n\n", fmtId(dbname));
670                 ret = runPgDump(dbname);
671                 if (ret != 0)
672                 {
673                         fprintf(stderr, _("%s: pg_dump failed on database \"%s\", exiting\n"), progname, dbname);
674                         exit(1);
675                 }
676         }
677
678         PQclear(res);
679 }
680
681
682
683 /*
684  * Run pg_dump on dbname.
685  */
686 static int
687 runPgDump(const char *dbname)
688 {
689         PQExpBuffer cmd = createPQExpBuffer();
690         const char *p;
691         int                     ret;
692
693         appendPQExpBuffer(cmd, "'%s' %s -Fp '", pg_dump_bin, pgdumpopts->data);
694
695         /* Shell quoting is not quite like SQL quoting, so can't use fmtId */
696         for (p = dbname; *p; p++)
697         {
698                 if (*p == '\'')
699                         appendPQExpBuffer(cmd, "'\"'\"'");
700                 else
701                         appendPQExpBufferChar(cmd, *p);
702         }
703
704         appendPQExpBufferChar(cmd, '\'');
705
706         if (verbose)
707                 fprintf(stderr, _("%s: running \"%s\"\n"), progname, cmd->data);
708
709         fflush(stdout);
710         fflush(stderr);
711
712         ret = system(cmd->data);
713
714         destroyPQExpBuffer(cmd);
715
716         return ret;
717 }
718
719
720
721 /*
722  * Make a database connection with the given parameters.  An
723  * interactive password prompt is automatically issued if required.
724  */
725 static PGconn *
726 connectDatabase(const char *dbname, const char *pghost, const char *pgport,
727                                 const char *pguser, bool require_password)
728 {
729         PGconn     *conn;
730         char       *password = NULL;
731         bool            need_pass = false;
732         const char *remoteversion_str;
733
734         if (require_password)
735                 password = simple_prompt("Password: ", 100, false);
736
737         /*
738          * Start the connection.  Loop until we have a password if requested
739          * by backend.
740          */
741         do
742         {
743                 need_pass = false;
744                 conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password);
745
746                 if (!conn)
747                 {
748                         fprintf(stderr, _("%s: could not connect to database \"%s\"\n"),
749                                         progname, dbname);
750                         exit(1);
751                 }
752
753                 if (PQstatus(conn) == CONNECTION_BAD &&
754                         strcmp(PQerrorMessage(conn), "fe_sendauth: no password supplied\n") == 0 &&
755                         !feof(stdin))
756                 {
757                         PQfinish(conn);
758                         need_pass = true;
759                         free(password);
760                         password = NULL;
761                         password = simple_prompt("Password: ", 100, false);
762                 }
763         } while (need_pass);
764
765         if (password)
766                 free(password);
767
768         /* check to see that the backend connection was successfully made */
769         if (PQstatus(conn) == CONNECTION_BAD)
770         {
771                 fprintf(stderr, _("%s: could not connect to database \"%s\": %s\n"),
772                                 progname, dbname, PQerrorMessage(conn));
773                 exit(1);
774         }
775
776         remoteversion_str = PQparameterStatus(conn, "server_version");
777         if (!remoteversion_str)
778         {
779                 fprintf(stderr, _("%s: could not get server version\n"), progname);
780                 exit(1);
781         }
782         server_version = parse_version(remoteversion_str);
783         if (server_version < 0)
784         {
785                 fprintf(stderr, _("%s: could not parse server version \"%s\"\n"),
786                                 progname, remoteversion_str);
787                 exit(1);
788         }
789
790         return conn;
791 }
792
793
794
795 /*
796  * Run a query, return the results, exit program on failure.
797  */
798 static PGresult *
799 executeQuery(PGconn *conn, const char *query)
800 {
801         PGresult   *res;
802
803         if (verbose)
804                 fprintf(stderr, _("%s: executing %s\n"), progname, query);
805
806         res = PQexec(conn, query);
807         if (!res ||
808                 PQresultStatus(res) != PGRES_TUPLES_OK)
809         {
810                 fprintf(stderr, _("%s: query failed: %s"), progname, PQerrorMessage(conn));
811                 fprintf(stderr, _("%s: query was: %s\n"), progname, query);
812                 PQfinish(conn);
813                 exit(1);
814         }
815
816         return res;
817 }
818
819
820 /*
821  * dumpTimestamp
822  */
823 static void
824 dumpTimestamp(char *msg)
825 {
826         char buf[256];
827         time_t now = time(NULL);
828
829         if (strftime(buf, 256, "%Y-%m-%d %H:%M:%S %Z", localtime(&now)) != 0)
830                 printf("-- %s %s\n\n", msg, buf);
831 }