Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pg_restore.c
4 : * pg_restore is an utility extracting postgres database definitions
5 : * from a backup archive created by pg_dump/pg_dumpall using the archiver
6 : * interface.
7 : *
8 : * pg_restore will read the backup archive and
9 : * dump out a script that reproduces
10 : * the schema of the database in terms of
11 : * user-defined types
12 : * user-defined functions
13 : * tables
14 : * indexes
15 : * aggregates
16 : * operators
17 : * ACL - grant/revoke
18 : *
19 : * the output script is SQL that is understood by PostgreSQL
20 : *
21 : * Basic process in a restore operation is:
22 : *
23 : * Open the Archive and read the TOC.
24 : * Set flags in TOC entries, and *maybe* reorder them.
25 : * Generate script to stdout
26 : * Exit
27 : *
28 : * Copyright (c) 2000, Philip Warner
29 : * Rights are granted to use this software in any way so long
30 : * as this notice is not removed.
31 : *
32 : * The author is not responsible for loss or damages that may
33 : * result from its use.
34 : *
35 : *
36 : * IDENTIFICATION
37 : * src/bin/pg_dump/pg_restore.c
38 : *
39 : *-------------------------------------------------------------------------
40 : */
41 : #include "postgres_fe.h"
42 :
43 : #include <ctype.h>
44 : #include <sys/stat.h>
45 : #ifdef HAVE_TERMIOS_H
46 : #include <termios.h>
47 : #endif
48 :
49 : #include "common/string.h"
50 : #include "connectdb.h"
51 : #include "dumputils.h"
52 : #include "fe_utils/option_utils.h"
53 : #include "fe_utils/string_utils.h"
54 : #include "filter.h"
55 : #include "getopt_long.h"
56 : #include "parallel.h"
57 : #include "pg_backup_utils.h"
58 :
59 : static void usage(const char *progname);
60 : static void read_restore_filters(const char *filename, RestoreOptions *opts);
61 : static bool file_exists_in_directory(const char *dir, const char *filename);
62 : static int restore_one_database(const char *inputFileSpec, RestoreOptions *opts,
63 : int numWorkers, bool append_data);
64 : static int restore_global_objects(const char *inputFileSpec, RestoreOptions *opts);
65 :
66 : static int restore_all_databases(const char *inputFileSpec,
67 : SimpleStringList db_exclude_patterns, RestoreOptions *opts, int numWorkers);
68 : static int get_dbnames_list_to_restore(PGconn *conn,
69 : SimplePtrList *dbname_oid_list,
70 : SimpleStringList db_exclude_patterns);
71 : static int get_dbname_oid_list_from_mfile(const char *dumpdirpath,
72 : SimplePtrList *dbname_oid_list);
73 :
74 : /*
75 : * Stores a database OID and the corresponding name.
76 : */
77 : typedef struct DbOidName
78 : {
79 : Oid oid;
80 : char str[FLEXIBLE_ARRAY_MEMBER]; /* null-terminated string here */
81 : } DbOidName;
82 :
83 :
84 : int
85 134 : main(int argc, char **argv)
86 : {
87 : RestoreOptions *opts;
88 : int c;
89 134 : int numWorkers = 1;
90 : char *inputFileSpec;
91 134 : bool data_only = false;
92 134 : bool schema_only = false;
93 134 : int n_errors = 0;
94 134 : bool globals_only = false;
95 134 : SimpleStringList db_exclude_patterns = {NULL, NULL};
96 : static int disable_triggers = 0;
97 : static int enable_row_security = 0;
98 : static int if_exists = 0;
99 : static int no_data_for_failed_tables = 0;
100 : static int outputNoTableAm = 0;
101 : static int outputNoTablespaces = 0;
102 : static int use_setsessauth = 0;
103 : static int no_comments = 0;
104 : static int no_data = 0;
105 : static int no_policies = 0;
106 : static int no_publications = 0;
107 : static int no_schema = 0;
108 : static int no_security_labels = 0;
109 : static int no_statistics = 0;
110 : static int no_globals = 0;
111 : static int no_subscriptions = 0;
112 : static int strict_names = 0;
113 : static int statistics_only = 0;
114 : static int with_statistics = 0;
115 :
116 134 : struct option cmdopts[] = {
117 : {"clean", 0, NULL, 'c'},
118 : {"create", 0, NULL, 'C'},
119 : {"data-only", 0, NULL, 'a'},
120 : {"globals-only", 0, NULL, 'g'},
121 : {"dbname", 1, NULL, 'd'},
122 : {"exit-on-error", 0, NULL, 'e'},
123 : {"exclude-schema", 1, NULL, 'N'},
124 : {"file", 1, NULL, 'f'},
125 : {"format", 1, NULL, 'F'},
126 : {"function", 1, NULL, 'P'},
127 : {"host", 1, NULL, 'h'},
128 : {"index", 1, NULL, 'I'},
129 : {"jobs", 1, NULL, 'j'},
130 : {"list", 0, NULL, 'l'},
131 : {"no-privileges", 0, NULL, 'x'},
132 : {"no-acl", 0, NULL, 'x'},
133 : {"no-owner", 0, NULL, 'O'},
134 : {"no-reconnect", 0, NULL, 'R'},
135 : {"port", 1, NULL, 'p'},
136 : {"no-password", 0, NULL, 'w'},
137 : {"password", 0, NULL, 'W'},
138 : {"schema", 1, NULL, 'n'},
139 : {"schema-only", 0, NULL, 's'},
140 : {"superuser", 1, NULL, 'S'},
141 : {"table", 1, NULL, 't'},
142 : {"trigger", 1, NULL, 'T'},
143 : {"use-list", 1, NULL, 'L'},
144 : {"username", 1, NULL, 'U'},
145 : {"verbose", 0, NULL, 'v'},
146 : {"single-transaction", 0, NULL, '1'},
147 :
148 : /*
149 : * the following options don't have an equivalent short option letter
150 : */
151 : {"disable-triggers", no_argument, &disable_triggers, 1},
152 : {"enable-row-security", no_argument, &enable_row_security, 1},
153 : {"if-exists", no_argument, &if_exists, 1},
154 : {"no-data-for-failed-tables", no_argument, &no_data_for_failed_tables, 1},
155 : {"no-table-access-method", no_argument, &outputNoTableAm, 1},
156 : {"no-tablespaces", no_argument, &outputNoTablespaces, 1},
157 : {"role", required_argument, NULL, 2},
158 : {"section", required_argument, NULL, 3},
159 : {"strict-names", no_argument, &strict_names, 1},
160 : {"transaction-size", required_argument, NULL, 5},
161 : {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
162 : {"no-comments", no_argument, &no_comments, 1},
163 : {"no-data", no_argument, &no_data, 1},
164 : {"no-policies", no_argument, &no_policies, 1},
165 : {"no-publications", no_argument, &no_publications, 1},
166 : {"no-schema", no_argument, &no_schema, 1},
167 : {"no-security-labels", no_argument, &no_security_labels, 1},
168 : {"no-globals", no_argument, &no_globals, 1},
169 : {"no-subscriptions", no_argument, &no_subscriptions, 1},
170 : {"no-statistics", no_argument, &no_statistics, 1},
171 : {"statistics", no_argument, &with_statistics, 1},
172 : {"statistics-only", no_argument, &statistics_only, 1},
173 : {"filter", required_argument, NULL, 4},
174 : {"restrict-key", required_argument, NULL, 6},
175 : {"exclude-database", required_argument, NULL, 7},
176 :
177 : {NULL, 0, NULL, 0}
178 : };
179 :
180 134 : pg_logging_init(argv[0]);
181 134 : pg_logging_set_level(PG_LOG_WARNING);
182 134 : set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
183 :
184 134 : init_parallel_dump_utils();
185 :
186 134 : opts = NewRestoreOptions();
187 :
188 134 : progname = get_progname(argv[0]);
189 :
190 134 : if (argc > 1)
191 : {
192 133 : if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
193 : {
194 1 : usage(progname);
195 1 : exit_nicely(0);
196 : }
197 132 : if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
198 : {
199 20 : puts("pg_restore (PostgreSQL) " PG_VERSION);
200 20 : exit_nicely(0);
201 : }
202 : }
203 :
204 647 : while ((c = getopt_long(argc, argv, "acCd:ef:F:gh:I:j:lL:n:N:Op:P:RsS:t:T:U:vwWx1",
205 647 : cmdopts, NULL)) != -1)
206 : {
207 540 : switch (c)
208 : {
209 5 : case 'a': /* Dump data only */
210 5 : data_only = true;
211 5 : break;
212 23 : case 'c': /* clean (i.e., drop) schema prior to create */
213 23 : opts->dropSchema = 1;
214 23 : break;
215 61 : case 'C':
216 61 : opts->createDB = 1;
217 61 : break;
218 45 : case 'd':
219 45 : opts->cparams.dbname = pg_strdup(optarg);
220 45 : break;
221 33 : case 'e':
222 33 : opts->exit_on_error = true;
223 33 : break;
224 61 : case 'f': /* output file name */
225 61 : opts->filename = pg_strdup(optarg);
226 61 : break;
227 42 : case 'F':
228 42 : opts->formatName = pg_strdup(optarg);
229 42 : break;
230 15 : case 'g':
231 : /* restore only global sql commands. */
232 15 : globals_only = true;
233 15 : break;
234 42 : case 'h':
235 42 : opts->cparams.pghost = pg_strdup(optarg);
236 42 : break;
237 7 : case 'j': /* number of restore jobs */
238 7 : if (!option_parse_int(optarg, "-j/--jobs", 1,
239 : PG_MAX_JOBS,
240 : &numWorkers))
241 1 : exit(1);
242 6 : break;
243 :
244 5 : case 'l': /* Dump the TOC summary */
245 5 : opts->tocSummary = 1;
246 5 : break;
247 :
248 1 : case 'L': /* input TOC summary file name */
249 1 : opts->tocFile = pg_strdup(optarg);
250 1 : break;
251 :
252 0 : case 'n': /* Dump data for this schema only */
253 0 : simple_string_list_append(&opts->schemaNames, optarg);
254 0 : break;
255 :
256 0 : case 'N': /* Do not dump data for this schema */
257 0 : simple_string_list_append(&opts->schemaExcludeNames, optarg);
258 0 : break;
259 :
260 0 : case 'O':
261 0 : opts->noOwner = 1;
262 0 : break;
263 :
264 52 : case 'p':
265 52 : opts->cparams.pgport = pg_strdup(optarg);
266 52 : break;
267 0 : case 'R':
268 : /* no-op, still accepted for backwards compatibility */
269 0 : break;
270 0 : case 'P': /* Function */
271 0 : opts->selTypes = 1;
272 0 : opts->selFunction = 1;
273 0 : simple_string_list_append(&opts->functionNames, optarg);
274 0 : break;
275 0 : case 'I': /* Index */
276 0 : opts->selTypes = 1;
277 0 : opts->selIndex = 1;
278 0 : simple_string_list_append(&opts->indexNames, optarg);
279 0 : break;
280 0 : case 'T': /* Trigger */
281 0 : opts->selTypes = 1;
282 0 : opts->selTrigger = 1;
283 0 : simple_string_list_append(&opts->triggerNames, optarg);
284 0 : break;
285 3 : case 's': /* dump schema only */
286 3 : schema_only = true;
287 3 : break;
288 0 : case 'S': /* Superuser username */
289 0 : if (strlen(optarg) != 0)
290 0 : opts->superuser = pg_strdup(optarg);
291 0 : break;
292 0 : case 't': /* Dump specified table(s) only */
293 0 : opts->selTypes = 1;
294 0 : opts->selTable = 1;
295 0 : simple_string_list_append(&opts->tableNames, optarg);
296 0 : break;
297 :
298 34 : case 'U':
299 34 : opts->cparams.username = pg_strdup(optarg);
300 34 : break;
301 :
302 37 : case 'v': /* verbose */
303 37 : opts->verbose = 1;
304 37 : pg_logging_increase_verbosity();
305 37 : break;
306 :
307 0 : case 'w':
308 0 : opts->cparams.promptPassword = TRI_NO;
309 0 : break;
310 :
311 0 : case 'W':
312 0 : opts->cparams.promptPassword = TRI_YES;
313 0 : break;
314 :
315 0 : case 'x': /* skip ACL dump */
316 0 : opts->aclsSkip = 1;
317 0 : break;
318 :
319 3 : case '1': /* Restore data in a single transaction */
320 3 : opts->single_txn = true;
321 3 : opts->exit_on_error = true;
322 3 : break;
323 :
324 23 : case 0:
325 :
326 : /*
327 : * This covers the long options without a short equivalent.
328 : */
329 23 : break;
330 :
331 0 : case 2: /* SET ROLE */
332 0 : opts->use_role = pg_strdup(optarg);
333 0 : break;
334 :
335 1 : case 3: /* section */
336 1 : set_dump_section(optarg, &(opts->dumpSections));
337 1 : break;
338 :
339 10 : case 4: /* filter */
340 10 : read_restore_filters(optarg, opts);
341 6 : break;
342 :
343 33 : case 5: /* transaction-size */
344 33 : if (!option_parse_int(optarg, "--transaction-size",
345 : 1, INT_MAX,
346 : &opts->txn_size))
347 0 : exit(1);
348 33 : opts->exit_on_error = true;
349 33 : break;
350 :
351 0 : case 6:
352 0 : opts->restrict_key = pg_strdup(optarg);
353 0 : break;
354 :
355 3 : case 7: /* database patterns to skip */
356 3 : simple_string_list_append(&db_exclude_patterns, optarg);
357 3 : break;
358 :
359 1 : default:
360 : /* getopt_long already emitted a complaint */
361 1 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
362 1 : exit_nicely(1);
363 : }
364 : }
365 :
366 : /* Get file name from command line */
367 107 : if (optind < argc)
368 94 : inputFileSpec = argv[optind++];
369 : else
370 13 : inputFileSpec = NULL;
371 :
372 : /* Complain if any arguments remain */
373 107 : if (optind < argc)
374 : {
375 1 : pg_log_error("too many command-line arguments (first is \"%s\")",
376 : argv[optind]);
377 1 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
378 1 : exit_nicely(1);
379 : }
380 :
381 : /* Complain if neither -f nor -d was specified (except if dumping TOC) */
382 106 : if (!opts->cparams.dbname && !opts->filename && !opts->tocSummary)
383 1 : pg_fatal("one of -d/--dbname and -f/--file must be specified");
384 :
385 : /* --exclude-database and --globals-only are incompatible */
386 105 : check_mut_excl_opts(db_exclude_patterns.head, "--exclude-database",
387 : globals_only, "-g/--globals-only");
388 :
389 : /* Should get at most one of -d and -f, else user is confused */
390 104 : check_mut_excl_opts(opts->cparams.dbname, "-d/--dbname",
391 : opts->filename, "-f/--file");
392 :
393 : /* --dbname and --restrict-key are incompatible */
394 103 : check_mut_excl_opts(opts->cparams.dbname, "-d/--dbname",
395 : opts->restrict_key, "--restrict-key");
396 :
397 103 : if (opts->cparams.dbname)
398 43 : opts->useDB = 1;
399 : else
400 : {
401 : /*
402 : * If you don't provide a restrict key, one will be appointed for you.
403 : */
404 60 : if (!opts->restrict_key)
405 60 : opts->restrict_key = generate_restrict_key();
406 60 : if (!opts->restrict_key)
407 0 : pg_fatal("could not generate restrict key");
408 60 : if (!valid_restrict_key(opts->restrict_key))
409 0 : pg_fatal("invalid restrict key");
410 : }
411 :
412 : /* *-only options are incompatible with each other */
413 103 : check_mut_excl_opts(data_only, "-a/--data-only",
414 : globals_only, "-g/--globals-only",
415 : schema_only, "-s/--schema-only",
416 : statistics_only, "--statistics-only");
417 :
418 : /* --no-* and *-only for same thing are incompatible */
419 96 : check_mut_excl_opts(data_only, "-a/--data-only",
420 : no_data, "--no-data");
421 96 : check_mut_excl_opts(globals_only, "-g/--globals-only",
422 : no_globals, "--no-globals");
423 95 : check_mut_excl_opts(schema_only, "-s/--schema-only",
424 : no_schema, "--no-schema");
425 95 : check_mut_excl_opts(statistics_only, "--statistics-only",
426 : no_statistics, "--no-statistics");
427 :
428 : /* --statistics and --no-statistics are incompatible */
429 95 : check_mut_excl_opts(with_statistics, "--statistics",
430 : no_statistics, "--no-statistics");
431 :
432 : /* --statistics is incompatible with *-only (except --statistics-only) */
433 95 : check_mut_excl_opts(with_statistics, "--statistics",
434 : data_only, "-a/--data-only",
435 : globals_only, "-g/--globals-only",
436 : schema_only, "-s/--schema-only");
437 :
438 : /* --clean and --data-only are incompatible */
439 94 : check_mut_excl_opts(opts->dropSchema, "-c/--clean",
440 : data_only, "-a/--data-only");
441 :
442 : /*
443 : * --globals-only, --single-transaction, and --transaction-size are
444 : * incompatible.
445 : */
446 93 : check_mut_excl_opts(globals_only, "-g/--globals-only",
447 : opts->single_txn, "-1/--single-transaction",
448 : opts->txn_size, "--transaction-size");
449 :
450 : /* --exit-on-error and --globals-only are incompatible */
451 91 : check_mut_excl_opts(opts->exit_on_error, "--exit-on-error",
452 : globals_only, "-g/--globals-only");
453 :
454 : /*
455 : * -C is not compatible with -1, because we can't create a database inside
456 : * a transaction block.
457 : */
458 90 : check_mut_excl_opts(opts->createDB, "-C/--create",
459 : opts->single_txn, "-1/--single-transaction");
460 :
461 : /* Can't do single-txn mode with multiple connections */
462 89 : if (opts->single_txn && numWorkers > 1)
463 1 : pg_fatal("cannot specify both --single-transaction and multiple jobs");
464 :
465 : /*
466 : * Set derivative flags. Ambiguous or nonsensical combinations, e.g.
467 : * "--schema-only --no-schema", will have already caused an error in one
468 : * of the checks above.
469 : */
470 88 : opts->dumpData = ((opts->dumpData && !schema_only && !statistics_only) ||
471 176 : data_only) && !no_data;
472 88 : opts->dumpSchema = ((opts->dumpSchema && !data_only && !statistics_only) ||
473 176 : schema_only) && !no_schema;
474 88 : opts->dumpStatistics = ((opts->dumpStatistics && !schema_only && !data_only) ||
475 176 : (statistics_only || with_statistics)) && !no_statistics;
476 :
477 88 : opts->disable_triggers = disable_triggers;
478 88 : opts->enable_row_security = enable_row_security;
479 88 : opts->noDataForFailedTables = no_data_for_failed_tables;
480 88 : opts->noTableAm = outputNoTableAm;
481 88 : opts->noTablespace = outputNoTablespaces;
482 88 : opts->use_setsessauth = use_setsessauth;
483 88 : opts->no_comments = no_comments;
484 88 : opts->no_policies = no_policies;
485 88 : opts->no_publications = no_publications;
486 88 : opts->no_security_labels = no_security_labels;
487 88 : opts->no_subscriptions = no_subscriptions;
488 :
489 88 : if (if_exists && !opts->dropSchema)
490 1 : pg_fatal("option %s requires option %s",
491 : "--if-exists", "-c/--clean");
492 87 : opts->if_exists = if_exists;
493 87 : opts->strict_names = strict_names;
494 :
495 87 : if (opts->formatName)
496 : {
497 70 : if (pg_strcasecmp(opts->formatName, "c") == 0 ||
498 35 : pg_strcasecmp(opts->formatName, "custom") == 0)
499 22 : opts->format = archCustom;
500 26 : else if (pg_strcasecmp(opts->formatName, "d") == 0 ||
501 13 : pg_strcasecmp(opts->formatName, "directory") == 0)
502 9 : opts->format = archDirectory;
503 8 : else if (pg_strcasecmp(opts->formatName, "t") == 0 ||
504 4 : pg_strcasecmp(opts->formatName, "tar") == 0)
505 2 : opts->format = archTar;
506 4 : else if (pg_strcasecmp(opts->formatName, "p") == 0 ||
507 2 : pg_strcasecmp(opts->formatName, "plain") == 0)
508 : {
509 : /* recognize this for consistency with pg_dump */
510 0 : pg_fatal("archive format \"%s\" is not supported; please use psql",
511 : opts->formatName);
512 : }
513 : else
514 2 : pg_fatal("unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"",
515 : opts->formatName);
516 : }
517 :
518 : /*
519 : * If toc.glo file is present, then restore all the databases from
520 : * map.dat, but skip restoring those matching --exclude-database patterns.
521 : */
522 170 : if (inputFileSpec != NULL &&
523 85 : (file_exists_in_directory(inputFileSpec, "toc.glo")))
524 11 : {
525 : char global_path[MAXPGPATH];
526 21 : RestoreOptions *tmpopts = pg_malloc0_object(RestoreOptions);
527 :
528 21 : opts->format = archUnknown;
529 :
530 21 : memcpy(tmpopts, opts, sizeof(RestoreOptions));
531 :
532 : /*
533 : * Can only use --list or --use-list options with a single database
534 : * dump.
535 : */
536 21 : if (opts->tocSummary)
537 1 : pg_fatal("option %s cannot be used when restoring an archive created by pg_dumpall",
538 : "-l/--list");
539 20 : if (opts->tocFile)
540 1 : pg_fatal("option %s cannot be used when restoring an archive created by pg_dumpall",
541 : "-L/--use-list");
542 :
543 19 : if (opts->strict_names)
544 1 : pg_fatal("option %s cannot be used when restoring an archive created by pg_dumpall",
545 : "--strict-names");
546 18 : if (globals_only && opts->dropSchema)
547 1 : pg_fatal("options %s and %s cannot be used together when restoring an archive created by pg_dumpall",
548 : "--clean", "-g/--globals-only");
549 :
550 : /*
551 : * For pg_dumpall archives, --clean implies --if-exists since global
552 : * objects may not exist in the target cluster.
553 : */
554 17 : if (opts->dropSchema && !opts->if_exists)
555 : {
556 1 : opts->if_exists = 1;
557 1 : pg_log_info("--if-exists is implied by --clean for pg_dumpall archives");
558 : }
559 :
560 17 : if (no_schema)
561 1 : pg_fatal("option %s cannot be used when restoring an archive created by pg_dumpall",
562 : "--no-schema");
563 :
564 16 : if (data_only)
565 1 : pg_fatal("option %s cannot be used when restoring an archive created by pg_dumpall",
566 : "-a/--data-only");
567 :
568 15 : if (statistics_only)
569 1 : pg_fatal("option %s cannot be used when restoring an archive created by pg_dumpall",
570 : "--statistics-only");
571 :
572 14 : if (!(opts->dumpSections & DUMP_PRE_DATA))
573 1 : pg_fatal("option %s cannot exclude %s when restoring a pg_dumpall archive",
574 : "--section", "--pre-data");
575 :
576 : /*
577 : * To restore from a pg_dumpall archive, -C (create database) option
578 : * must be specified unless we are only restoring globals or we are
579 : * skipping globals.
580 : */
581 13 : if (!no_globals && !globals_only && opts->createDB != 1)
582 : {
583 1 : pg_log_error("option %s must be specified when restoring an archive created by pg_dumpall",
584 : "-C/--create");
585 1 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
586 1 : pg_log_error_hint("Individual databases can be restored using their specific archives.");
587 1 : exit_nicely(1);
588 : }
589 :
590 : /*
591 : * Restore global objects, even if --exclude-database results in zero
592 : * databases to process. If 'globals-only' is set, exit immediately.
593 : */
594 12 : snprintf(global_path, MAXPGPATH, "%s/toc.glo", inputFileSpec);
595 :
596 12 : if (!no_globals)
597 11 : n_errors = restore_global_objects(global_path, tmpopts);
598 : else
599 1 : pg_log_info("skipping restore of global objects because %s was specified",
600 : "--no-globals");
601 :
602 11 : if (globals_only)
603 1 : pg_log_info("database restoring skipped because option %s was specified",
604 : "-g/--globals-only");
605 : else
606 : {
607 : /* Now restore all the databases from map.dat */
608 10 : n_errors = n_errors + restore_all_databases(inputFileSpec, db_exclude_patterns,
609 : opts, numWorkers);
610 : }
611 :
612 : /* Free db pattern list. */
613 11 : simple_string_list_destroy(&db_exclude_patterns);
614 : }
615 : else
616 : {
617 64 : if (db_exclude_patterns.head != NULL)
618 : {
619 1 : simple_string_list_destroy(&db_exclude_patterns);
620 1 : pg_fatal("option %s can be used only when restoring an archive created by pg_dumpall",
621 : "--exclude-database");
622 : }
623 :
624 63 : if (globals_only)
625 1 : pg_fatal("option %s can be used only when restoring an archive created by pg_dumpall",
626 : "-g/--globals-only");
627 :
628 : /* Process if toc.glo file does not exist. */
629 62 : n_errors = restore_one_database(inputFileSpec, opts, numWorkers, false);
630 : }
631 :
632 : /* Done, print a summary of ignored errors during restore. */
633 73 : if (n_errors)
634 : {
635 0 : pg_log_warning("errors ignored on restore: %d", n_errors);
636 0 : return 1;
637 : }
638 :
639 73 : return 0;
640 : }
641 :
642 : /*
643 : * restore_global_objects
644 : *
645 : * This restore all global objects.
646 : */
647 : static int
648 11 : restore_global_objects(const char *inputFileSpec, RestoreOptions *opts)
649 : {
650 : Archive *AH;
651 11 : int nerror = 0;
652 :
653 : /* Set format as custom so that toc.glo file can be read. */
654 11 : opts->format = archCustom;
655 11 : opts->txn_size = 0;
656 :
657 11 : AH = OpenArchive(inputFileSpec, opts->format);
658 :
659 11 : SetArchiveOptions(AH, NULL, opts);
660 :
661 11 : on_exit_close_archive(AH);
662 :
663 : /* Let the archiver know how noisy to be */
664 11 : AH->verbose = opts->verbose;
665 :
666 : /* Don't output TOC entry comments when restoring globals */
667 11 : ((ArchiveHandle *) AH)->noTocComments = 1;
668 :
669 11 : AH->exit_on_error = false;
670 :
671 : /* Parallel execution is not supported for global object restoration. */
672 11 : AH->numWorkers = 1;
673 :
674 11 : ProcessArchiveRestoreOptions(AH);
675 11 : RestoreArchive(AH, false);
676 :
677 10 : nerror = AH->n_errors;
678 :
679 : /* AH may be freed in CloseArchive? */
680 10 : CloseArchive(AH);
681 :
682 10 : return nerror;
683 : }
684 :
685 : /*
686 : * restore_one_database
687 : *
688 : * This will restore one database using toc.dat file.
689 : *
690 : * returns the number of errors while doing restore.
691 : */
692 : static int
693 139 : restore_one_database(const char *inputFileSpec, RestoreOptions *opts,
694 : int numWorkers, bool append_data)
695 : {
696 : Archive *AH;
697 : int n_errors;
698 :
699 139 : AH = OpenArchive(inputFileSpec, opts->format);
700 :
701 139 : SetArchiveOptions(AH, NULL, opts);
702 :
703 : /*
704 : * We don't have a connection yet but that doesn't matter. The connection
705 : * is initialized to NULL and if we terminate through exit_nicely() while
706 : * it's still NULL, the cleanup function will just be a no-op. If we are
707 : * restoring multiple databases, then only update AX handle for cleanup as
708 : * the previous entry was already in the array and we had closed previous
709 : * connection, so we can use the same array slot.
710 : */
711 139 : if (!append_data)
712 62 : on_exit_close_archive(AH);
713 : else
714 77 : replace_on_exit_close_archive(AH);
715 :
716 : /* Let the archiver know how noisy to be */
717 139 : AH->verbose = opts->verbose;
718 :
719 : /*
720 : * Whether to keep submitting sql commands as "pg_restore ... | psql ... "
721 : */
722 139 : AH->exit_on_error = opts->exit_on_error;
723 :
724 139 : if (opts->tocFile)
725 0 : SortTocFromFile(AH);
726 :
727 139 : AH->numWorkers = numWorkers;
728 :
729 139 : if (opts->tocSummary)
730 4 : PrintTOCSummary(AH);
731 : else
732 : {
733 135 : ProcessArchiveRestoreOptions(AH);
734 135 : RestoreArchive(AH, append_data);
735 : }
736 :
737 139 : n_errors = AH->n_errors;
738 :
739 : /* AH may be freed in CloseArchive? */
740 139 : CloseArchive(AH);
741 :
742 139 : return n_errors;
743 : }
744 :
745 : static void
746 1 : usage(const char *progname)
747 : {
748 1 : printf(_("%s restores PostgreSQL databases from archives created by pg_dump or pg_dumpall.\n\n"), progname);
749 1 : printf(_("Usage:\n"));
750 1 : printf(_(" %s [OPTION]... [FILE]\n"), progname);
751 :
752 1 : printf(_("\nGeneral options:\n"));
753 1 : printf(_(" -d, --dbname=NAME connect to database name\n"));
754 1 : printf(_(" -f, --file=FILENAME output file name (- for stdout)\n"));
755 1 : printf(_(" -F, --format=c|d|t backup file format (should be automatic)\n"));
756 1 : printf(_(" -l, --list print summarized TOC of the archive\n"));
757 1 : printf(_(" -v, --verbose verbose mode\n"));
758 1 : printf(_(" -V, --version output version information, then exit\n"));
759 1 : printf(_(" -?, --help show this help, then exit\n"));
760 :
761 1 : printf(_("\nOptions controlling the restore:\n"));
762 1 : printf(_(" -a, --data-only restore only the data, no schema\n"));
763 1 : printf(_(" -c, --clean clean (drop) database objects before recreating\n"));
764 1 : printf(_(" -C, --create create the target database\n"));
765 1 : printf(_(" -e, --exit-on-error exit on error, default is to continue\n"));
766 1 : printf(_(" -g, --globals-only restore only global objects, no databases\n"));
767 1 : printf(_(" -I, --index=NAME restore named index\n"));
768 1 : printf(_(" -j, --jobs=NUM use this many parallel jobs to restore\n"));
769 1 : printf(_(" -L, --use-list=FILENAME use table of contents from this file for\n"
770 : " selecting/ordering output\n"));
771 1 : printf(_(" -n, --schema=NAME restore only objects in this schema\n"));
772 1 : printf(_(" -N, --exclude-schema=NAME do not restore objects in this schema\n"));
773 1 : printf(_(" -O, --no-owner skip restoration of object ownership\n"));
774 1 : printf(_(" -P, --function=NAME(args) restore named function\n"));
775 1 : printf(_(" -s, --schema-only restore only the schema, no data\n"));
776 1 : printf(_(" -S, --superuser=NAME superuser user name to use for disabling triggers\n"));
777 1 : printf(_(" -t, --table=NAME restore named relation (table, view, etc.)\n"));
778 1 : printf(_(" -T, --trigger=NAME restore named trigger\n"));
779 1 : printf(_(" -x, --no-privileges skip restoration of access privileges (grant/revoke)\n"));
780 1 : printf(_(" -1, --single-transaction restore as a single transaction\n"));
781 1 : printf(_(" --disable-triggers disable triggers during data-only restore\n"));
782 1 : printf(_(" --enable-row-security enable row security\n"));
783 1 : printf(_(" --exclude-database=PATTERN do not restore the specified database(s)\n"));
784 1 : printf(_(" --filter=FILENAME restore or skip objects based on expressions\n"
785 : " in FILENAME\n"));
786 1 : printf(_(" --if-exists use IF EXISTS when dropping objects\n"));
787 1 : printf(_(" --no-comments do not restore comment commands\n"));
788 1 : printf(_(" --no-data do not restore data\n"));
789 1 : printf(_(" --no-data-for-failed-tables do not restore data of tables that could not be\n"
790 : " created\n"));
791 1 : printf(_(" --no-policies do not restore row security policies\n"));
792 1 : printf(_(" --no-publications do not restore publications\n"));
793 1 : printf(_(" --no-schema do not restore schema\n"));
794 1 : printf(_(" --no-security-labels do not restore security labels\n"));
795 1 : printf(_(" --no-statistics do not restore statistics\n"));
796 1 : printf(_(" --no-subscriptions do not restore subscriptions\n"));
797 1 : printf(_(" --no-globals do not restore global objects (roles and tablespaces)\n"));
798 1 : printf(_(" --no-table-access-method do not restore table access methods\n"));
799 1 : printf(_(" --no-tablespaces do not restore tablespace assignments\n"));
800 1 : printf(_(" --restrict-key=RESTRICT_KEY use provided string as psql \\restrict key\n"));
801 1 : printf(_(" --section=SECTION restore named section (pre-data, data, or post-data)\n"));
802 1 : printf(_(" --statistics restore the statistics\n"));
803 1 : printf(_(" --statistics-only restore only the statistics, not schema or data\n"));
804 1 : printf(_(" --strict-names require table and/or schema include patterns to\n"
805 : " match at least one entity each\n"));
806 1 : printf(_(" --transaction-size=N commit after every N objects\n"));
807 1 : printf(_(" --use-set-session-authorization\n"
808 : " use SET SESSION AUTHORIZATION commands instead of\n"
809 : " ALTER OWNER commands to set ownership\n"));
810 :
811 1 : printf(_("\nConnection options:\n"));
812 1 : printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
813 1 : printf(_(" -p, --port=PORT database server port number\n"));
814 1 : printf(_(" -U, --username=NAME connect as specified database user\n"));
815 1 : printf(_(" -w, --no-password never prompt for password\n"));
816 1 : printf(_(" -W, --password force password prompt (should happen automatically)\n"));
817 1 : printf(_(" --role=ROLENAME do SET ROLE before restore\n"));
818 :
819 1 : printf(_("\n"
820 : "The options -I, -n, -N, -P, -t, -T, --section, and --exclude-database can be\n"
821 : "combined and specified multiple times to select multiple objects.\n"));
822 1 : printf(_("\nIf no input file name is supplied, then standard input is used.\n\n"));
823 1 : printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
824 1 : printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
825 1 : }
826 :
827 : /*
828 : * read_restore_filters - retrieve object identifier patterns from file
829 : *
830 : * Parse the specified filter file for include and exclude patterns, and add
831 : * them to the relevant lists. If the filename is "-" then filters will be
832 : * read from STDIN rather than a file.
833 : */
834 : static void
835 10 : read_restore_filters(const char *filename, RestoreOptions *opts)
836 : {
837 : FilterStateData fstate;
838 : char *objname;
839 : FilterCommandType comtype;
840 : FilterObjectType objtype;
841 :
842 10 : filter_init(&fstate, filename, exit_nicely);
843 :
844 27 : while (filter_read_item(&fstate, &objname, &comtype, &objtype))
845 : {
846 11 : if (comtype == FILTER_COMMAND_TYPE_INCLUDE)
847 : {
848 8 : switch (objtype)
849 : {
850 0 : case FILTER_OBJECT_TYPE_NONE:
851 0 : break;
852 2 : case FILTER_OBJECT_TYPE_TABLE_DATA:
853 : case FILTER_OBJECT_TYPE_TABLE_DATA_AND_CHILDREN:
854 : case FILTER_OBJECT_TYPE_TABLE_AND_CHILDREN:
855 : case FILTER_OBJECT_TYPE_DATABASE:
856 : case FILTER_OBJECT_TYPE_EXTENSION:
857 : case FILTER_OBJECT_TYPE_FOREIGN_DATA:
858 2 : pg_log_filter_error(&fstate, _("%s filter for \"%s\" is not allowed"),
859 : "include",
860 : filter_object_type_name(objtype));
861 2 : exit_nicely(1);
862 :
863 2 : case FILTER_OBJECT_TYPE_FUNCTION:
864 2 : opts->selTypes = 1;
865 2 : opts->selFunction = 1;
866 2 : simple_string_list_append(&opts->functionNames, objname);
867 2 : break;
868 1 : case FILTER_OBJECT_TYPE_INDEX:
869 1 : opts->selTypes = 1;
870 1 : opts->selIndex = 1;
871 1 : simple_string_list_append(&opts->indexNames, objname);
872 1 : break;
873 1 : case FILTER_OBJECT_TYPE_SCHEMA:
874 1 : simple_string_list_append(&opts->schemaNames, objname);
875 1 : break;
876 1 : case FILTER_OBJECT_TYPE_TABLE:
877 1 : opts->selTypes = 1;
878 1 : opts->selTable = 1;
879 1 : simple_string_list_append(&opts->tableNames, objname);
880 1 : break;
881 1 : case FILTER_OBJECT_TYPE_TRIGGER:
882 1 : opts->selTypes = 1;
883 1 : opts->selTrigger = 1;
884 1 : simple_string_list_append(&opts->triggerNames, objname);
885 1 : break;
886 : }
887 : }
888 3 : else if (comtype == FILTER_COMMAND_TYPE_EXCLUDE)
889 : {
890 3 : switch (objtype)
891 : {
892 0 : case FILTER_OBJECT_TYPE_NONE:
893 0 : break;
894 2 : case FILTER_OBJECT_TYPE_TABLE_DATA:
895 : case FILTER_OBJECT_TYPE_TABLE_DATA_AND_CHILDREN:
896 : case FILTER_OBJECT_TYPE_DATABASE:
897 : case FILTER_OBJECT_TYPE_EXTENSION:
898 : case FILTER_OBJECT_TYPE_FOREIGN_DATA:
899 : case FILTER_OBJECT_TYPE_FUNCTION:
900 : case FILTER_OBJECT_TYPE_INDEX:
901 : case FILTER_OBJECT_TYPE_TABLE:
902 : case FILTER_OBJECT_TYPE_TABLE_AND_CHILDREN:
903 : case FILTER_OBJECT_TYPE_TRIGGER:
904 2 : pg_log_filter_error(&fstate, _("%s filter for \"%s\" is not allowed"),
905 : "exclude",
906 : filter_object_type_name(objtype));
907 2 : exit_nicely(1);
908 :
909 1 : case FILTER_OBJECT_TYPE_SCHEMA:
910 1 : simple_string_list_append(&opts->schemaExcludeNames, objname);
911 1 : break;
912 : }
913 : }
914 : else
915 : {
916 : Assert(comtype == FILTER_COMMAND_TYPE_NONE);
917 : Assert(objtype == FILTER_OBJECT_TYPE_NONE);
918 : }
919 :
920 7 : if (objname)
921 7 : free(objname);
922 : }
923 :
924 6 : filter_free(&fstate);
925 6 : }
926 :
927 : /*
928 : * file_exists_in_directory
929 : *
930 : * Returns true if the file exists in the given directory.
931 : */
932 : static bool
933 241 : file_exists_in_directory(const char *dir, const char *filename)
934 : {
935 : struct stat st;
936 : char buf[MAXPGPATH];
937 :
938 241 : if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH)
939 0 : pg_fatal("directory name too long: \"%s\"", dir);
940 :
941 241 : return (stat(buf, &st) == 0 && S_ISREG(st.st_mode));
942 : }
943 :
944 : /*
945 : * get_dbnames_list_to_restore
946 : *
947 : * This will mark for skipping any entries from dbname_oid_list that pattern match an
948 : * entry in the db_exclude_patterns list.
949 : *
950 : * Returns the number of database to be restored.
951 : *
952 : */
953 : static int
954 1 : get_dbnames_list_to_restore(PGconn *conn,
955 : SimplePtrList *dbname_oid_list,
956 : SimpleStringList db_exclude_patterns)
957 : {
958 1 : int count_db = 0;
959 : PQExpBuffer query;
960 : PQExpBuffer db_lit;
961 : PGresult *res;
962 :
963 1 : query = createPQExpBuffer();
964 1 : db_lit = createPQExpBuffer();
965 :
966 : /*
967 : * Process one by one all dbnames and if specified to skip restoring, then
968 : * remove dbname from list.
969 : */
970 1 : for (SimplePtrListCell *db_cell = dbname_oid_list->head;
971 7 : db_cell; db_cell = db_cell->next)
972 : {
973 6 : DbOidName *dbidname = (DbOidName *) db_cell->ptr;
974 6 : bool skip_db_restore = false;
975 :
976 6 : resetPQExpBuffer(query);
977 6 : resetPQExpBuffer(db_lit);
978 :
979 6 : appendStringLiteralConn(db_lit, dbidname->str, conn);
980 :
981 11 : for (SimpleStringListCell *pat_cell = db_exclude_patterns.head; pat_cell; pat_cell = pat_cell->next)
982 : {
983 : /*
984 : * If there is an exact match then we don't need to try a pattern
985 : * match
986 : */
987 6 : if (pg_strcasecmp(dbidname->str, pat_cell->val) == 0)
988 1 : skip_db_restore = true;
989 : /* Otherwise, try a pattern match if there is a connection */
990 : else
991 : {
992 : int dotcnt;
993 :
994 5 : appendPQExpBufferStr(query, "SELECT 1 ");
995 5 : processSQLNamePattern(conn, query, pat_cell->val, false,
996 5 : false, NULL, db_lit->data,
997 : NULL, NULL, NULL, &dotcnt);
998 :
999 5 : if (dotcnt > 0)
1000 : {
1001 0 : pg_log_error("improper qualified name (too many dotted names): %s",
1002 : dbidname->str);
1003 0 : PQfinish(conn);
1004 0 : exit_nicely(1);
1005 : }
1006 :
1007 5 : res = executeQuery(conn, query->data);
1008 :
1009 5 : if (PQntuples(res))
1010 : {
1011 0 : skip_db_restore = true;
1012 0 : pg_log_info("database name \"%s\" matches --exclude-database pattern \"%s\"", dbidname->str, pat_cell->val);
1013 : }
1014 :
1015 5 : PQclear(res);
1016 5 : resetPQExpBuffer(query);
1017 : }
1018 :
1019 6 : if (skip_db_restore)
1020 1 : break;
1021 : }
1022 :
1023 : /*
1024 : * Mark db to be skipped or increment the counter of dbs to be
1025 : * restored
1026 : */
1027 6 : if (skip_db_restore)
1028 : {
1029 1 : pg_log_info("excluding database \"%s\"", dbidname->str);
1030 1 : dbidname->oid = InvalidOid;
1031 : }
1032 : else
1033 5 : count_db++;
1034 : }
1035 :
1036 1 : destroyPQExpBuffer(query);
1037 1 : destroyPQExpBuffer(db_lit);
1038 :
1039 1 : return count_db;
1040 : }
1041 :
1042 : /*
1043 : * get_dbname_oid_list_from_mfile
1044 : *
1045 : * Open map.dat file and read line by line and then prepare a list of database
1046 : * names and corresponding db_oid.
1047 : *
1048 : * Returns, total number of database names in map.dat file.
1049 : */
1050 : static int
1051 10 : get_dbname_oid_list_from_mfile(const char *dumpdirpath,
1052 : SimplePtrList *dbname_oid_list)
1053 : {
1054 : StringInfoData linebuf;
1055 : FILE *pfile;
1056 : char map_file_path[MAXPGPATH];
1057 10 : int count = 0;
1058 :
1059 : /*
1060 : * If there is no map.dat file in the dump, then return from here as there
1061 : * is no database to restore.
1062 : */
1063 10 : if (!file_exists_in_directory(dumpdirpath, "map.dat"))
1064 : {
1065 0 : pg_log_info("database restoring is skipped because file \"%s\" does not exist in directory \"%s\"", "map.dat", dumpdirpath);
1066 0 : return 0;
1067 : }
1068 :
1069 10 : snprintf(map_file_path, MAXPGPATH, "%s/map.dat", dumpdirpath);
1070 :
1071 : /* Open map.dat file. */
1072 10 : pfile = fopen(map_file_path, PG_BINARY_R);
1073 :
1074 10 : if (pfile == NULL)
1075 0 : pg_fatal("could not open file \"%s\": %m", map_file_path);
1076 :
1077 10 : initStringInfo(&linebuf);
1078 :
1079 : /* Append all the dbname/db_oid combinations to the list. */
1080 189 : while (pg_get_line_buf(pfile, &linebuf))
1081 : {
1082 179 : Oid db_oid = InvalidOid;
1083 : char *dbname;
1084 : DbOidName *dbidname;
1085 : int namelen;
1086 179 : char *p = linebuf.data;
1087 :
1088 : /* look for the dboid. */
1089 489 : while (isdigit((unsigned char) *p))
1090 310 : p++;
1091 :
1092 : /* ignore lines that don't begin with a digit */
1093 179 : if (p == linebuf.data)
1094 101 : continue;
1095 :
1096 78 : if (*p == ' ')
1097 : {
1098 78 : sscanf(linebuf.data, "%u", &db_oid);
1099 78 : p++;
1100 : }
1101 :
1102 : /* dbname is the rest of the line */
1103 78 : dbname = p;
1104 78 : namelen = strlen(dbname);
1105 :
1106 : /* Strip trailing newline */
1107 78 : if (namelen > 0 && dbname[namelen - 1] == '\n')
1108 78 : dbname[--namelen] = '\0';
1109 :
1110 : /* Report error and exit if the file has any corrupted data. */
1111 78 : if (!OidIsValid(db_oid) || namelen < 1)
1112 0 : pg_fatal("invalid entry in file \"%s\" on line %d", map_file_path,
1113 : count + 1);
1114 :
1115 78 : dbidname = pg_malloc(offsetof(DbOidName, str) + namelen + 1);
1116 78 : dbidname->oid = db_oid;
1117 78 : strlcpy(dbidname->str, dbname, namelen + 1);
1118 :
1119 78 : pg_log_info("found database \"%s\" (OID: %u) in file \"%s\"",
1120 : dbidname->str, db_oid, map_file_path);
1121 :
1122 78 : simple_ptr_list_append(dbname_oid_list, dbidname);
1123 78 : count++;
1124 : }
1125 :
1126 : /* Close map.dat file. */
1127 10 : fclose(pfile);
1128 :
1129 10 : pfree(linebuf.data);
1130 :
1131 10 : return count;
1132 : }
1133 :
1134 : /*
1135 : * restore_all_databases
1136 : *
1137 : * This will restore databases those dumps are present in
1138 : * directory based on map.dat file mapping.
1139 : *
1140 : * This will skip restoring for databases that are specified with
1141 : * exclude-database option.
1142 : *
1143 : * returns, number of errors while doing restore.
1144 : */
1145 : static int
1146 10 : restore_all_databases(const char *inputFileSpec,
1147 : SimpleStringList db_exclude_patterns, RestoreOptions *opts,
1148 : int numWorkers)
1149 : {
1150 10 : SimplePtrList dbname_oid_list = {NULL, NULL};
1151 10 : int num_db_restore = 0;
1152 : int num_total_db;
1153 10 : int n_errors_total = 0;
1154 10 : char *connected_db = NULL;
1155 10 : PGconn *conn = NULL;
1156 10 : RestoreOptions *original_opts = pg_malloc0_object(RestoreOptions);
1157 10 : RestoreOptions *tmpopts = pg_malloc0_object(RestoreOptions);
1158 :
1159 10 : memcpy(original_opts, opts, sizeof(RestoreOptions));
1160 :
1161 : /* Save db name to reuse it for all the database. */
1162 10 : if (opts->cparams.dbname)
1163 0 : connected_db = opts->cparams.dbname;
1164 :
1165 10 : num_total_db = get_dbname_oid_list_from_mfile(inputFileSpec, &dbname_oid_list);
1166 :
1167 10 : pg_log_info(ngettext("found %d database name in \"%s\"",
1168 : "found %d database names in \"%s\"",
1169 : num_total_db),
1170 : num_total_db, "map.dat");
1171 :
1172 : /*
1173 : * If exclude-patterns is given, connect to the database to process them.
1174 : */
1175 10 : if (db_exclude_patterns.head != NULL)
1176 : {
1177 1 : if (opts->cparams.dbname)
1178 : {
1179 0 : conn = ConnectDatabase(opts->cparams.dbname, NULL, opts->cparams.pghost,
1180 0 : opts->cparams.pgport, opts->cparams.username, TRI_DEFAULT,
1181 : false, progname, NULL, NULL, NULL, NULL);
1182 :
1183 0 : if (!conn)
1184 0 : pg_fatal("could not connect to database \"%s\"", opts->cparams.dbname);
1185 : }
1186 :
1187 1 : if (!conn)
1188 : {
1189 1 : pg_log_info("trying to connect to database \"%s\"", "postgres");
1190 :
1191 1 : conn = ConnectDatabase("postgres", NULL, opts->cparams.pghost,
1192 1 : opts->cparams.pgport, opts->cparams.username, TRI_DEFAULT,
1193 : false, progname, NULL, NULL, NULL, NULL);
1194 :
1195 : /* Try with template1. */
1196 1 : if (!conn)
1197 : {
1198 0 : pg_log_info("trying to connect to database \"%s\"", "template1");
1199 :
1200 0 : conn = ConnectDatabase("template1", NULL, opts->cparams.pghost,
1201 0 : opts->cparams.pgport, opts->cparams.username, TRI_DEFAULT,
1202 : false, progname, NULL, NULL, NULL, NULL);
1203 0 : if (!conn)
1204 : {
1205 0 : pg_log_error("could not connect to databases \"postgres\" or \"template1\"\n"
1206 : "Please specify an alternative database.");
1207 0 : pg_log_error_hint("Try \"%s --help\" for more information.", progname);
1208 0 : exit_nicely(1);
1209 : }
1210 : }
1211 : }
1212 :
1213 : /* Filter the db list according to the exclude patterns. */
1214 1 : num_db_restore = get_dbnames_list_to_restore(conn, &dbname_oid_list,
1215 : db_exclude_patterns);
1216 1 : PQfinish(conn);
1217 : }
1218 : else
1219 9 : num_db_restore = num_total_db;
1220 :
1221 : /* Exit if no db needs to be restored. */
1222 10 : if (num_db_restore == 0)
1223 : {
1224 0 : pg_log_info(ngettext("no database needs restoring out of %d database",
1225 : "no database needs restoring out of %d databases", num_total_db),
1226 : num_total_db);
1227 0 : pg_free(original_opts);
1228 0 : pg_free(tmpopts);
1229 0 : return 0;
1230 : }
1231 :
1232 10 : pg_log_info("need to restore %d databases out of %d databases", num_db_restore, num_total_db);
1233 :
1234 : /*
1235 : * We have a list of databases to restore after processing the
1236 : * exclude-database switch(es). Now we can restore them one by one.
1237 : */
1238 10 : for (SimplePtrListCell *db_cell = dbname_oid_list.head;
1239 88 : db_cell; db_cell = db_cell->next)
1240 : {
1241 78 : DbOidName *dbidname = (DbOidName *) db_cell->ptr;
1242 : char subdirpath[MAXPGPATH];
1243 : char subdirdbpath[MAXPGPATH];
1244 : char dbfilename[MAXPGPATH];
1245 : int n_errors;
1246 :
1247 : /* ignore dbs marked for skipping */
1248 78 : if (dbidname->oid == InvalidOid)
1249 1 : continue;
1250 :
1251 : /*
1252 : * Since pg_backup_archiver.c may modify RestoreOptions during the
1253 : * previous restore, we must provide a fresh copy of the original
1254 : * "opts" for each call to restore_one_database.
1255 : */
1256 77 : memcpy(tmpopts, original_opts, sizeof(RestoreOptions));
1257 :
1258 77 : snprintf(subdirdbpath, MAXPGPATH, "%s/databases", inputFileSpec);
1259 :
1260 : /*
1261 : * Look for the database dump file/dir. If there is an {oid}.tar or
1262 : * {oid}.dmp file, use it. Otherwise try to use a directory called
1263 : * {oid}
1264 : */
1265 77 : snprintf(dbfilename, MAXPGPATH, "%u.tar", dbidname->oid);
1266 77 : if (file_exists_in_directory(subdirdbpath, dbfilename))
1267 8 : snprintf(subdirpath, MAXPGPATH, "%s/databases/%u.tar", inputFileSpec, dbidname->oid);
1268 : else
1269 : {
1270 69 : snprintf(dbfilename, MAXPGPATH, "%u.dmp", dbidname->oid);
1271 :
1272 69 : if (file_exists_in_directory(subdirdbpath, dbfilename))
1273 16 : snprintf(subdirpath, MAXPGPATH, "%s/databases/%u.dmp", inputFileSpec, dbidname->oid);
1274 : else
1275 53 : snprintf(subdirpath, MAXPGPATH, "%s/databases/%u", inputFileSpec, dbidname->oid);
1276 : }
1277 :
1278 77 : pg_log_info("restoring database \"%s\"", dbidname->str);
1279 :
1280 : /* If database is already created, then don't set createDB flag. */
1281 77 : if (tmpopts->cparams.dbname)
1282 : {
1283 : PGconn *test_conn;
1284 :
1285 0 : test_conn = ConnectDatabase(dbidname->str, NULL, tmpopts->cparams.pghost,
1286 0 : tmpopts->cparams.pgport, tmpopts->cparams.username, TRI_DEFAULT,
1287 : false, progname, NULL, NULL, NULL, NULL);
1288 0 : if (test_conn)
1289 : {
1290 0 : PQfinish(test_conn);
1291 :
1292 : /* Use already created database for connection. */
1293 0 : tmpopts->createDB = 0;
1294 0 : tmpopts->cparams.dbname = dbidname->str;
1295 : }
1296 : else
1297 : {
1298 0 : if (!tmpopts->createDB)
1299 : {
1300 0 : pg_log_info("skipping restore of database \"%s\": database does not exist and %s was not specified",
1301 : dbidname->str, "-C/--create");
1302 0 : continue;
1303 : }
1304 :
1305 : /* We'll have to create it */
1306 0 : tmpopts->createDB = 1;
1307 0 : tmpopts->cparams.dbname = connected_db;
1308 : }
1309 : }
1310 :
1311 : /* Restore the single database. */
1312 77 : n_errors = restore_one_database(subdirpath, tmpopts, numWorkers, true);
1313 :
1314 77 : n_errors_total += n_errors;
1315 :
1316 : /* Print a summary of ignored errors during single database restore. */
1317 77 : if (n_errors)
1318 0 : pg_log_warning("errors ignored on database \"%s\" restore: %d", dbidname->str, n_errors);
1319 : }
1320 :
1321 : /* Log number of processed databases. */
1322 10 : pg_log_info("number of restored databases is %d", num_db_restore);
1323 :
1324 : /* Free dbname and dboid list. */
1325 10 : simple_ptr_list_destroy(&dbname_oid_list);
1326 :
1327 10 : pg_free(original_opts);
1328 10 : pg_free(tmpopts);
1329 :
1330 10 : return n_errors_total;
1331 : }
|