~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/bin/pg_dump/pg_dumpall.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

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