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