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 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 | #ifdef HAVE_TERMIOS_H |
45 | #include <termios.h> |
46 | #endif |
47 | |
48 | #include "getopt_long.h" |
49 | |
50 | #include "dumputils.h" |
51 | #include "parallel.h" |
52 | #include "pg_backup_utils.h" |
53 | |
54 | |
55 | static void usage(const char *progname); |
56 | |
57 | typedef struct option optType; |
58 | |
59 | int |
60 | main(int argc, char **argv) |
61 | { |
62 | RestoreOptions *opts; |
63 | int c; |
64 | int exit_code; |
65 | int numWorkers = 1; |
66 | Archive *AH; |
67 | char *inputFileSpec; |
68 | static int disable_triggers = 0; |
69 | static int enable_row_security = 0; |
70 | static int if_exists = 0; |
71 | static int no_data_for_failed_tables = 0; |
72 | static int outputNoTablespaces = 0; |
73 | static int use_setsessauth = 0; |
74 | static int = 0; |
75 | static int no_publications = 0; |
76 | static int no_security_labels = 0; |
77 | static int no_subscriptions = 0; |
78 | static int strict_names = 0; |
79 | |
80 | struct option cmdopts[] = { |
81 | {"clean" , 0, NULL, 'c'}, |
82 | {"create" , 0, NULL, 'C'}, |
83 | {"data-only" , 0, NULL, 'a'}, |
84 | {"dbname" , 1, NULL, 'd'}, |
85 | {"exit-on-error" , 0, NULL, 'e'}, |
86 | {"exclude-schema" , 1, NULL, 'N'}, |
87 | {"file" , 1, NULL, 'f'}, |
88 | {"format" , 1, NULL, 'F'}, |
89 | {"function" , 1, NULL, 'P'}, |
90 | {"host" , 1, NULL, 'h'}, |
91 | {"index" , 1, NULL, 'I'}, |
92 | {"jobs" , 1, NULL, 'j'}, |
93 | {"list" , 0, NULL, 'l'}, |
94 | {"no-privileges" , 0, NULL, 'x'}, |
95 | {"no-acl" , 0, NULL, 'x'}, |
96 | {"no-owner" , 0, NULL, 'O'}, |
97 | {"no-reconnect" , 0, NULL, 'R'}, |
98 | {"port" , 1, NULL, 'p'}, |
99 | {"no-password" , 0, NULL, 'w'}, |
100 | {"password" , 0, NULL, 'W'}, |
101 | {"schema" , 1, NULL, 'n'}, |
102 | {"schema-only" , 0, NULL, 's'}, |
103 | {"superuser" , 1, NULL, 'S'}, |
104 | {"table" , 1, NULL, 't'}, |
105 | {"trigger" , 1, NULL, 'T'}, |
106 | {"use-list" , 1, NULL, 'L'}, |
107 | {"username" , 1, NULL, 'U'}, |
108 | {"verbose" , 0, NULL, 'v'}, |
109 | {"single-transaction" , 0, NULL, '1'}, |
110 | |
111 | /* |
112 | * the following options don't have an equivalent short option letter |
113 | */ |
114 | {"disable-triggers" , no_argument, &disable_triggers, 1}, |
115 | {"enable-row-security" , no_argument, &enable_row_security, 1}, |
116 | {"if-exists" , no_argument, &if_exists, 1}, |
117 | {"no-data-for-failed-tables" , no_argument, &no_data_for_failed_tables, 1}, |
118 | {"no-tablespaces" , no_argument, &outputNoTablespaces, 1}, |
119 | {"role" , required_argument, NULL, 2}, |
120 | {"section" , required_argument, NULL, 3}, |
121 | {"strict-names" , no_argument, &strict_names, 1}, |
122 | {"use-set-session-authorization" , no_argument, &use_setsessauth, 1}, |
123 | {"no-comments" , no_argument, &no_comments, 1}, |
124 | {"no-publications" , no_argument, &no_publications, 1}, |
125 | {"no-security-labels" , no_argument, &no_security_labels, 1}, |
126 | {"no-subscriptions" , no_argument, &no_subscriptions, 1}, |
127 | |
128 | {NULL, 0, NULL, 0} |
129 | }; |
130 | |
131 | pg_logging_init(argv[0]); |
132 | pg_logging_set_level(PG_LOG_WARNING); |
133 | set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump" )); |
134 | |
135 | init_parallel_dump_utils(); |
136 | |
137 | opts = NewRestoreOptions(); |
138 | |
139 | progname = get_progname(argv[0]); |
140 | |
141 | if (argc > 1) |
142 | { |
143 | if (strcmp(argv[1], "--help" ) == 0 || strcmp(argv[1], "-?" ) == 0) |
144 | { |
145 | usage(progname); |
146 | exit_nicely(0); |
147 | } |
148 | if (strcmp(argv[1], "--version" ) == 0 || strcmp(argv[1], "-V" ) == 0) |
149 | { |
150 | puts("pg_restore (PostgreSQL) " PG_VERSION); |
151 | exit_nicely(0); |
152 | } |
153 | } |
154 | |
155 | while ((c = getopt_long(argc, argv, "acCd:ef:F:h:I:j:lL:n:N:Op:P:RsS:t:T:U:vwWx1" , |
156 | cmdopts, NULL)) != -1) |
157 | { |
158 | switch (c) |
159 | { |
160 | case 'a': /* Dump data only */ |
161 | opts->dataOnly = 1; |
162 | break; |
163 | case 'c': /* clean (i.e., drop) schema prior to create */ |
164 | opts->dropSchema = 1; |
165 | break; |
166 | case 'C': |
167 | opts->createDB = 1; |
168 | break; |
169 | case 'd': |
170 | opts->dbname = pg_strdup(optarg); |
171 | break; |
172 | case 'e': |
173 | opts->exit_on_error = true; |
174 | break; |
175 | case 'f': /* output file name */ |
176 | opts->filename = pg_strdup(optarg); |
177 | break; |
178 | case 'F': |
179 | if (strlen(optarg) != 0) |
180 | opts->formatName = pg_strdup(optarg); |
181 | break; |
182 | case 'h': |
183 | if (strlen(optarg) != 0) |
184 | opts->pghost = pg_strdup(optarg); |
185 | break; |
186 | |
187 | case 'j': /* number of restore jobs */ |
188 | numWorkers = atoi(optarg); |
189 | break; |
190 | |
191 | case 'l': /* Dump the TOC summary */ |
192 | opts->tocSummary = 1; |
193 | break; |
194 | |
195 | case 'L': /* input TOC summary file name */ |
196 | opts->tocFile = pg_strdup(optarg); |
197 | break; |
198 | |
199 | case 'n': /* Dump data for this schema only */ |
200 | simple_string_list_append(&opts->schemaNames, optarg); |
201 | break; |
202 | |
203 | case 'N': /* Do not dump data for this schema */ |
204 | simple_string_list_append(&opts->schemaExcludeNames, optarg); |
205 | break; |
206 | |
207 | case 'O': |
208 | opts->noOwner = 1; |
209 | break; |
210 | |
211 | case 'p': |
212 | if (strlen(optarg) != 0) |
213 | opts->pgport = pg_strdup(optarg); |
214 | break; |
215 | case 'R': |
216 | /* no-op, still accepted for backwards compatibility */ |
217 | break; |
218 | case 'P': /* Function */ |
219 | opts->selTypes = 1; |
220 | opts->selFunction = 1; |
221 | simple_string_list_append(&opts->functionNames, optarg); |
222 | break; |
223 | case 'I': /* Index */ |
224 | opts->selTypes = 1; |
225 | opts->selIndex = 1; |
226 | simple_string_list_append(&opts->indexNames, optarg); |
227 | break; |
228 | case 'T': /* Trigger */ |
229 | opts->selTypes = 1; |
230 | opts->selTrigger = 1; |
231 | simple_string_list_append(&opts->triggerNames, optarg); |
232 | break; |
233 | case 's': /* dump schema only */ |
234 | opts->schemaOnly = 1; |
235 | break; |
236 | case 'S': /* Superuser username */ |
237 | if (strlen(optarg) != 0) |
238 | opts->superuser = pg_strdup(optarg); |
239 | break; |
240 | case 't': /* Dump specified table(s) only */ |
241 | opts->selTypes = 1; |
242 | opts->selTable = 1; |
243 | simple_string_list_append(&opts->tableNames, optarg); |
244 | break; |
245 | |
246 | case 'U': |
247 | opts->username = pg_strdup(optarg); |
248 | break; |
249 | |
250 | case 'v': /* verbose */ |
251 | opts->verbose = 1; |
252 | pg_logging_set_level(PG_LOG_INFO); |
253 | break; |
254 | |
255 | case 'w': |
256 | opts->promptPassword = TRI_NO; |
257 | break; |
258 | |
259 | case 'W': |
260 | opts->promptPassword = TRI_YES; |
261 | break; |
262 | |
263 | case 'x': /* skip ACL dump */ |
264 | opts->aclsSkip = 1; |
265 | break; |
266 | |
267 | case '1': /* Restore data in a single transaction */ |
268 | opts->single_txn = true; |
269 | opts->exit_on_error = true; |
270 | break; |
271 | |
272 | case 0: |
273 | |
274 | /* |
275 | * This covers the long options without a short equivalent. |
276 | */ |
277 | break; |
278 | |
279 | case 2: /* SET ROLE */ |
280 | opts->use_role = pg_strdup(optarg); |
281 | break; |
282 | |
283 | case 3: /* section */ |
284 | set_dump_section(optarg, &(opts->dumpSections)); |
285 | break; |
286 | |
287 | default: |
288 | fprintf(stderr, _("Try \"%s --help\" for more information.\n" ), progname); |
289 | exit_nicely(1); |
290 | } |
291 | } |
292 | |
293 | /* Get file name from command line */ |
294 | if (optind < argc) |
295 | inputFileSpec = argv[optind++]; |
296 | else |
297 | inputFileSpec = NULL; |
298 | |
299 | /* Complain if any arguments remain */ |
300 | if (optind < argc) |
301 | { |
302 | pg_log_error("too many command-line arguments (first is \"%s\")" , |
303 | argv[optind]); |
304 | fprintf(stderr, _("Try \"%s --help\" for more information.\n" ), |
305 | progname); |
306 | exit_nicely(1); |
307 | } |
308 | |
309 | /* Complain if neither -f nor -d was specified (except if dumping TOC) */ |
310 | if (!opts->dbname && !opts->filename && !opts->tocSummary) |
311 | { |
312 | pg_log_error("one of -d/--dbname and -f/--file must be specified" ); |
313 | exit_nicely(1); |
314 | } |
315 | |
316 | /* Should get at most one of -d and -f, else user is confused */ |
317 | if (opts->dbname) |
318 | { |
319 | if (opts->filename) |
320 | { |
321 | pg_log_error("options -d/--dbname and -f/--file cannot be used together" ); |
322 | fprintf(stderr, _("Try \"%s --help\" for more information.\n" ), |
323 | progname); |
324 | exit_nicely(1); |
325 | } |
326 | opts->useDB = 1; |
327 | } |
328 | |
329 | if (opts->dataOnly && opts->schemaOnly) |
330 | { |
331 | pg_log_error("options -s/--schema-only and -a/--data-only cannot be used together" ); |
332 | exit_nicely(1); |
333 | } |
334 | |
335 | if (opts->dataOnly && opts->dropSchema) |
336 | { |
337 | pg_log_error("options -c/--clean and -a/--data-only cannot be used together" ); |
338 | exit_nicely(1); |
339 | } |
340 | |
341 | /* |
342 | * -C is not compatible with -1, because we can't create a database inside |
343 | * a transaction block. |
344 | */ |
345 | if (opts->createDB && opts->single_txn) |
346 | { |
347 | pg_log_error("options -C/--create and -1/--single-transaction cannot be used together" ); |
348 | exit_nicely(1); |
349 | } |
350 | |
351 | if (numWorkers <= 0) |
352 | { |
353 | pg_log_error("invalid number of parallel jobs" ); |
354 | exit(1); |
355 | } |
356 | |
357 | /* See comments in pg_dump.c */ |
358 | #ifdef WIN32 |
359 | if (numWorkers > MAXIMUM_WAIT_OBJECTS) |
360 | { |
361 | pg_log_error("maximum number of parallel jobs is %d" , |
362 | MAXIMUM_WAIT_OBJECTS); |
363 | exit(1); |
364 | } |
365 | #endif |
366 | |
367 | /* Can't do single-txn mode with multiple connections */ |
368 | if (opts->single_txn && numWorkers > 1) |
369 | { |
370 | pg_log_error("cannot specify both --single-transaction and multiple jobs" ); |
371 | exit_nicely(1); |
372 | } |
373 | |
374 | opts->disable_triggers = disable_triggers; |
375 | opts->enable_row_security = enable_row_security; |
376 | opts->noDataForFailedTables = no_data_for_failed_tables; |
377 | opts->noTablespace = outputNoTablespaces; |
378 | opts->use_setsessauth = use_setsessauth; |
379 | opts->no_comments = no_comments; |
380 | opts->no_publications = no_publications; |
381 | opts->no_security_labels = no_security_labels; |
382 | opts->no_subscriptions = no_subscriptions; |
383 | |
384 | if (if_exists && !opts->dropSchema) |
385 | { |
386 | pg_log_error("option --if-exists requires option -c/--clean" ); |
387 | exit_nicely(1); |
388 | } |
389 | opts->if_exists = if_exists; |
390 | opts->strict_names = strict_names; |
391 | |
392 | if (opts->formatName) |
393 | { |
394 | switch (opts->formatName[0]) |
395 | { |
396 | case 'c': |
397 | case 'C': |
398 | opts->format = archCustom; |
399 | break; |
400 | |
401 | case 'd': |
402 | case 'D': |
403 | opts->format = archDirectory; |
404 | break; |
405 | |
406 | case 't': |
407 | case 'T': |
408 | opts->format = archTar; |
409 | break; |
410 | |
411 | default: |
412 | pg_log_error("unrecognized archive format \"%s\"; please specify \"c\", \"d\", or \"t\"" , |
413 | opts->formatName); |
414 | exit_nicely(1); |
415 | } |
416 | } |
417 | |
418 | AH = OpenArchive(inputFileSpec, opts->format); |
419 | |
420 | SetArchiveOptions(AH, NULL, opts); |
421 | |
422 | /* |
423 | * We don't have a connection yet but that doesn't matter. The connection |
424 | * is initialized to NULL and if we terminate through exit_nicely() while |
425 | * it's still NULL, the cleanup function will just be a no-op. |
426 | */ |
427 | on_exit_close_archive(AH); |
428 | |
429 | /* Let the archiver know how noisy to be */ |
430 | AH->verbose = opts->verbose; |
431 | |
432 | /* |
433 | * Whether to keep submitting sql commands as "pg_restore ... | psql ... " |
434 | */ |
435 | AH->exit_on_error = opts->exit_on_error; |
436 | |
437 | if (opts->tocFile) |
438 | SortTocFromFile(AH); |
439 | |
440 | AH->numWorkers = numWorkers; |
441 | |
442 | if (opts->tocSummary) |
443 | PrintTOCSummary(AH); |
444 | else |
445 | { |
446 | ProcessArchiveRestoreOptions(AH); |
447 | RestoreArchive(AH); |
448 | } |
449 | |
450 | /* done, print a summary of ignored errors */ |
451 | if (AH->n_errors) |
452 | pg_log_warning("errors ignored on restore: %d" , AH->n_errors); |
453 | |
454 | /* AH may be freed in CloseArchive? */ |
455 | exit_code = AH->n_errors ? 1 : 0; |
456 | |
457 | CloseArchive(AH); |
458 | |
459 | return exit_code; |
460 | } |
461 | |
462 | static void |
463 | usage(const char *progname) |
464 | { |
465 | printf(_("%s restores a PostgreSQL database from an archive created by pg_dump.\n\n" ), progname); |
466 | printf(_("Usage:\n" )); |
467 | printf(_(" %s [OPTION]... [FILE]\n" ), progname); |
468 | |
469 | printf(_("\nGeneral options:\n" )); |
470 | printf(_(" -d, --dbname=NAME connect to database name\n" )); |
471 | printf(_(" -f, --file=FILENAME output file name (- for stdout)\n" )); |
472 | printf(_(" -F, --format=c|d|t backup file format (should be automatic)\n" )); |
473 | printf(_(" -l, --list print summarized TOC of the archive\n" )); |
474 | printf(_(" -v, --verbose verbose mode\n" )); |
475 | printf(_(" -V, --version output version information, then exit\n" )); |
476 | printf(_(" -?, --help show this help, then exit\n" )); |
477 | |
478 | printf(_("\nOptions controlling the restore:\n" )); |
479 | printf(_(" -a, --data-only restore only the data, no schema\n" )); |
480 | printf(_(" -c, --clean clean (drop) database objects before recreating\n" )); |
481 | printf(_(" -C, --create create the target database\n" )); |
482 | printf(_(" -e, --exit-on-error exit on error, default is to continue\n" )); |
483 | printf(_(" -I, --index=NAME restore named index\n" )); |
484 | printf(_(" -j, --jobs=NUM use this many parallel jobs to restore\n" )); |
485 | printf(_(" -L, --use-list=FILENAME use table of contents from this file for\n" |
486 | " selecting/ordering output\n" )); |
487 | printf(_(" -n, --schema=NAME restore only objects in this schema\n" )); |
488 | printf(_(" -N, --exclude-schema=NAME do not restore objects in this schema\n" )); |
489 | printf(_(" -O, --no-owner skip restoration of object ownership\n" )); |
490 | printf(_(" -P, --function=NAME(args) restore named function\n" )); |
491 | printf(_(" -s, --schema-only restore only the schema, no data\n" )); |
492 | printf(_(" -S, --superuser=NAME superuser user name to use for disabling triggers\n" )); |
493 | printf(_(" -t, --table=NAME restore named relation (table, view, etc.)\n" )); |
494 | printf(_(" -T, --trigger=NAME restore named trigger\n" )); |
495 | printf(_(" -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" )); |
496 | printf(_(" -1, --single-transaction restore as a single transaction\n" )); |
497 | printf(_(" --disable-triggers disable triggers during data-only restore\n" )); |
498 | printf(_(" --enable-row-security enable row security\n" )); |
499 | printf(_(" --if-exists use IF EXISTS when dropping objects\n" )); |
500 | printf(_(" --no-comments do not restore comments\n" )); |
501 | printf(_(" --no-data-for-failed-tables do not restore data of tables that could not be\n" |
502 | " created\n" )); |
503 | printf(_(" --no-publications do not restore publications\n" )); |
504 | printf(_(" --no-security-labels do not restore security labels\n" )); |
505 | printf(_(" --no-subscriptions do not restore subscriptions\n" )); |
506 | printf(_(" --no-tablespaces do not restore tablespace assignments\n" )); |
507 | printf(_(" --section=SECTION restore named section (pre-data, data, or post-data)\n" )); |
508 | printf(_(" --strict-names require table and/or schema include patterns to\n" |
509 | " match at least one entity each\n" )); |
510 | printf(_(" --use-set-session-authorization\n" |
511 | " use SET SESSION AUTHORIZATION commands instead of\n" |
512 | " ALTER OWNER commands to set ownership\n" )); |
513 | |
514 | printf(_("\nConnection options:\n" )); |
515 | printf(_(" -h, --host=HOSTNAME database server host or socket directory\n" )); |
516 | printf(_(" -p, --port=PORT database server port number\n" )); |
517 | printf(_(" -U, --username=NAME connect as specified database user\n" )); |
518 | printf(_(" -w, --no-password never prompt for password\n" )); |
519 | printf(_(" -W, --password force password prompt (should happen automatically)\n" )); |
520 | printf(_(" --role=ROLENAME do SET ROLE before restore\n" )); |
521 | |
522 | printf(_("\n" |
523 | "The options -I, -n, -N, -P, -t, -T, and --section can be combined and specified\n" |
524 | "multiple times to select multiple objects.\n" )); |
525 | printf(_("\nIf no input file name is supplied, then standard input is used.\n\n" )); |
526 | printf(_("Report bugs to <pgsql-bugs@lists.postgresql.org>.\n" )); |
527 | } |
528 | |