PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_backup_archiver.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_backup_archiver.c
4 *
5 * Private implementation of the archiver routines.
6 *
7 * See the headers to pg_restore for more details.
8 *
9 * Copyright (c) 2000, Philip Warner
10 * Rights are granted to use this software in any way so long
11 * as this notice is not removed.
12 *
13 * The author is not responsible for loss or damages that may
14 * result from its use.
15 *
16 *
17 * IDENTIFICATION
18 * src/bin/pg_dump/pg_backup_archiver.c
19 *
20 *-------------------------------------------------------------------------
21 */
22#include "postgres_fe.h"
23
24#include <ctype.h>
25#include <fcntl.h>
26#include <unistd.h>
27#include <sys/stat.h>
28#include <sys/wait.h>
29#ifdef WIN32
30#include <io.h>
31#endif
32
33#include "catalog/pg_class_d.h"
34#include "catalog/pg_largeobject_metadata_d.h"
35#include "catalog/pg_shdepend_d.h"
36#include "common/string.h"
37#include "compress_io.h"
38#include "dumputils.h"
40#include "lib/binaryheap.h"
41#include "lib/stringinfo.h"
42#include "libpq/libpq-fs.h"
43#include "parallel.h"
44#include "pg_backup_archiver.h"
45#include "pg_backup_db.h"
46#include "pg_backup_utils.h"
47#include "pgtar.h"
48
49#define TEXT_DUMP_HEADER "--\n-- PostgreSQL database dump\n--\n\n"
50#define TEXT_DUMPALL_HEADER "--\n-- PostgreSQL database cluster dump\n--\n\n"
51
52#define TOC_PREFIX_NONE ""
53#define TOC_PREFIX_DATA "Data for "
54#define TOC_PREFIX_STATS "Statistics for "
55
56static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
57 const pg_compress_specification compression_spec,
61static void _getObjectDescription(PQExpBuffer buf, const TocEntry *te);
62static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, const char *pfx);
64static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
65static void _reconnectToDB(ArchiveHandle *AH, const char *dbname);
66static void _becomeUser(ArchiveHandle *AH, const char *user);
67static void _becomeOwner(ArchiveHandle *AH, TocEntry *te);
68static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName);
69static void _selectTablespace(ArchiveHandle *AH, const char *tablespace);
70static void _selectTableAccessMethod(ArchiveHandle *AH, const char *tableam);
72 TocEntry *te);
73static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te);
78static bool _tocEntryIsACL(TocEntry *te);
82static void buildTocEntryArrays(ArchiveHandle *AH);
83static void _moveBefore(TocEntry *pos, TocEntry *te);
85
86static int RestoringToDB(ArchiveHandle *AH);
87static void dump_lo_buf(ArchiveHandle *AH);
88static void dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim);
89static void SetOutput(ArchiveHandle *AH, const char *filename,
90 const pg_compress_specification compression_spec);
93
94static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel);
98 ParallelState *pstate,
102static void pending_list_header_init(TocEntry *l);
103static void pending_list_append(TocEntry *l, TocEntry *te);
104static void pending_list_remove(TocEntry *te);
105static int TocEntrySizeCompareQsort(const void *p1, const void *p2);
106static int TocEntrySizeCompareBinaryheap(void *p1, void *p2, void *arg);
111 ParallelState *pstate);
112static void mark_dump_job_done(ArchiveHandle *AH,
113 TocEntry *te,
114 int status,
115 void *callback_data);
117 TocEntry *te,
118 int status,
119 void *callback_data);
120static void fix_dependencies(ArchiveHandle *AH);
124static void reduce_dependencies(ArchiveHandle *AH, TocEntry *te,
126static void mark_create_done(ArchiveHandle *AH, TocEntry *te);
128
129static void StrictNamesCheck(RestoreOptions *ropt);
130
131
132/*
133 * Allocate a new DumpOptions block containing all default values.
134 */
143
144/*
145 * Initialize a DumpOptions struct to all default values
146 */
147void
149{
150 memset(opts, 0, sizeof(DumpOptions));
151 /* set any fields that shouldn't default to zeroes */
152 opts->include_everything = true;
153 opts->cparams.promptPassword = TRI_DEFAULT;
154 opts->dumpSections = DUMP_UNSECTIONED;
155 opts->dumpSchema = true;
156 opts->dumpData = true;
157 opts->dumpStatistics = false;
158}
159
160/*
161 * Create a freshly allocated DumpOptions with options equivalent to those
162 * found in the given RestoreOptions.
163 */
166{
167 DumpOptions *dopt = NewDumpOptions();
168
169 /* this is the inverse of what's at the end of pg_dump.c's main() */
170 dopt->cparams.dbname = ropt->cparams.dbname ? pg_strdup(ropt->cparams.dbname) : NULL;
171 dopt->cparams.pgport = ropt->cparams.pgport ? pg_strdup(ropt->cparams.pgport) : NULL;
172 dopt->cparams.pghost = ropt->cparams.pghost ? pg_strdup(ropt->cparams.pghost) : NULL;
175 dopt->outputClean = ropt->dropSchema;
176 dopt->dumpData = ropt->dumpData;
177 dopt->dumpSchema = ropt->dumpSchema;
178 dopt->dumpSections = ropt->dumpSections;
179 dopt->dumpStatistics = ropt->dumpStatistics;
180 dopt->if_exists = ropt->if_exists;
181 dopt->column_inserts = ropt->column_inserts;
182 dopt->aclsSkip = ropt->aclsSkip;
183 dopt->outputSuperuser = ropt->superuser;
184 dopt->outputCreateDB = ropt->createDB;
185 dopt->outputNoOwner = ropt->noOwner;
186 dopt->outputNoTableAm = ropt->noTableAm;
187 dopt->outputNoTablespaces = ropt->noTablespace;
189 dopt->use_setsessauth = ropt->use_setsessauth;
191 dopt->dump_inserts = ropt->dump_inserts;
192 dopt->no_comments = ropt->no_comments;
193 dopt->no_policies = ropt->no_policies;
194 dopt->no_publications = ropt->no_publications;
197 dopt->lockWaitTimeout = ropt->lockWaitTimeout;
200 dopt->sequence_data = ropt->sequence_data;
201 dopt->restrict_key = ropt->restrict_key ? pg_strdup(ropt->restrict_key) : NULL;
202
203 return dopt;
204}
205
206
207/*
208 * Wrapper functions.
209 *
210 * The objective is to make writing new formats and dumpers as simple
211 * as possible, if necessary at the expense of extra function calls etc.
212 *
213 */
214
215/*
216 * The dump worker setup needs lots of knowledge of the internals of pg_dump,
217 * so it's defined in pg_dump.c and passed into OpenArchive. The restore worker
218 * setup doesn't need to know anything much, so it's defined here.
219 */
220static void
222{
223 ArchiveHandle *AH = (ArchiveHandle *) AHX;
224
225 AH->ReopenPtr(AH);
226}
227
228
229/* Create a new archive */
230/* Public */
231Archive *
233 const pg_compress_specification compression_spec,
234 bool dosync, ArchiveMode mode,
237
238{
239 ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression_spec,
241
242 return (Archive *) AH;
243}
244
245/* Open an existing archive */
246/* Public */
247Archive *
249{
250 ArchiveHandle *AH;
251 pg_compress_specification compression_spec = {0};
252
253 compression_spec.algorithm = PG_COMPRESSION_NONE;
254 AH = _allocAH(FileSpec, fmt, compression_spec, true,
257
258 return (Archive *) AH;
259}
260
261/* Public */
262void
264{
265 ArchiveHandle *AH = (ArchiveHandle *) AHX;
266
267 AH->ClosePtr(AH);
268
269 /* Close the output */
270 errno = 0;
271 if (!EndCompressFileHandle(AH->OF))
272 pg_fatal("could not close output file: %m");
273}
274
275/* Public */
276void
278{
279 /* Caller can omit dump options, in which case we synthesize them */
280 if (dopt == NULL && ropt != NULL)
282
283 /* Save options for later access */
284 AH->dopt = dopt;
285 AH->ropt = ropt;
286}
287
288/* Public */
289void
291{
292 ArchiveHandle *AH = (ArchiveHandle *) AHX;
293 RestoreOptions *ropt = AH->public.ropt;
294 TocEntry *te;
296
297 /* Decide which TOC entries will be dumped/restored, and mark them */
299 for (te = AH->toc->next; te != AH->toc; te = te->next)
300 {
301 /*
302 * When writing an archive, we also take this opportunity to check
303 * that we have generated the entries in a sane order that respects
304 * the section divisions. When reading, don't complain, since buggy
305 * old versions of pg_dump might generate out-of-order archives.
306 */
307 if (AH->mode != archModeRead)
308 {
309 switch (te->section)
310 {
311 case SECTION_NONE:
312 /* ok to be anywhere */
313 break;
314 case SECTION_PRE_DATA:
316 pg_log_warning("archive items not in correct section order");
317 break;
318 case SECTION_DATA:
320 pg_log_warning("archive items not in correct section order");
321 break;
323 /* ok no matter which section we were in */
324 break;
325 default:
326 pg_fatal("unexpected section code %d",
327 (int) te->section);
328 break;
329 }
330 }
331
332 if (te->section != SECTION_NONE)
333 curSection = te->section;
334
335 te->reqs = _tocEntryRequired(te, curSection, AH);
336 }
337
338 /* Enforce strict names checking */
339 if (ropt->strict_names)
340 StrictNamesCheck(ropt);
341}
342
343/* Public */
344void
346{
347 ArchiveHandle *AH = (ArchiveHandle *) AHX;
348 RestoreOptions *ropt = AH->public.ropt;
349 bool parallel_mode;
350 TocEntry *te;
352
354
355 /*
356 * If we're going to do parallel restore, there are some restrictions.
357 */
358 parallel_mode = (AH->public.numWorkers > 1 && ropt->useDB);
359 if (parallel_mode)
360 {
361 /* We haven't got round to making this work for all archive formats */
362 if (AH->ClonePtr == NULL || AH->ReopenPtr == NULL)
363 pg_fatal("parallel restore is not supported with this archive file format");
364
365 /* Doesn't work if the archive represents dependencies as OIDs */
366 if (AH->version < K_VERS_1_8)
367 pg_fatal("parallel restore is not supported with archives made by pre-8.0 pg_dump");
368
369 /*
370 * It's also not gonna work if we can't reopen the input file, so
371 * let's try that immediately.
372 */
373 AH->ReopenPtr(AH);
374 }
375
376 /*
377 * Make sure we won't need (de)compression we haven't got
378 */
379 if (AH->PrintTocDataPtr != NULL)
380 {
381 for (te = AH->toc->next; te != AH->toc; te = te->next)
382 {
383 if (te->hadDumper && (te->reqs & REQ_DATA) != 0)
384 {
386
387 if (errmsg)
388 pg_fatal("cannot restore from compressed archive (%s)",
389 errmsg);
390 else
391 break;
392 }
393 }
394 }
395
396 /*
397 * Prepare index arrays, so we can assume we have them throughout restore.
398 * It's possible we already did this, though.
399 */
400 if (AH->tocsByDumpId == NULL)
402
403 /*
404 * If we're using a DB connection, then connect it.
405 */
406 if (ropt->useDB)
407 {
408 pg_log_info("connecting to database for restore");
409 if (AH->version < K_VERS_1_3)
410 pg_fatal("direct database connections are not supported in pre-1.3 archives");
411
412 /*
413 * We don't want to guess at whether the dump will successfully
414 * restore; allow the attempt regardless of the version of the restore
415 * target.
416 */
417 AHX->minRemoteVersion = 0;
418 AHX->maxRemoteVersion = 9999999;
419
420 ConnectDatabaseAhx(AHX, &ropt->cparams, false);
421
422 /*
423 * If we're talking to the DB directly, don't send comments since they
424 * obscure SQL when displaying errors
425 */
426 AH->noTocComments = 1;
427 }
428
429 /*
430 * Work out if we have an implied schema-less restore. This can happen if
431 * the dump excluded the schema or the user has used a toc list to exclude
432 * all of the schema data. All we do is look for schema entries - if none
433 * are found then we unset the dumpSchema flag.
434 *
435 * We could scan for wanted TABLE entries, but that is not the same as
436 * data-only. At this stage, it seems unnecessary (6-Mar-2001).
437 */
438 if (ropt->dumpSchema)
439 {
440 bool no_schema_found = true;
441
442 for (te = AH->toc->next; te != AH->toc; te = te->next)
443 {
444 if ((te->reqs & REQ_SCHEMA) != 0)
445 {
446 no_schema_found = false;
447 break;
448 }
449 }
450 if (no_schema_found)
451 {
452 ropt->dumpSchema = false;
453 pg_log_info("implied no-schema restore");
454 }
455 }
456
457 /*
458 * Setup the output file if necessary.
459 */
460 sav = SaveOutput(AH);
462 SetOutput(AH, ropt->filename, ropt->compression_spec);
463
464 ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n");
465
466 /*
467 * If generating plain-text output, enter restricted mode to block any
468 * unexpected psql meta-commands. A malicious source might try to inject
469 * a variety of things via bogus responses to queries. While we cannot
470 * prevent such sources from affecting the destination at restore time, we
471 * can block psql meta-commands so that the client machine that runs psql
472 * with the dump output remains unaffected.
473 */
474 if (ropt->restrict_key)
475 ahprintf(AH, "\\restrict %s\n\n", ropt->restrict_key);
476
477 if (AH->archiveRemoteVersion)
478 ahprintf(AH, "-- Dumped from database version %s\n",
480 if (AH->archiveDumpVersion)
481 ahprintf(AH, "-- Dumped by pg_dump version %s\n",
483
484 ahprintf(AH, "\n");
485
486 if (AH->public.verbose)
487 dumpTimestamp(AH, "Started on", AH->createDate);
488
489 if (ropt->single_txn)
490 {
491 if (AH->connection)
492 StartTransaction(AHX);
493 else
494 ahprintf(AH, "BEGIN;\n\n");
495 }
496
497 /*
498 * Establish important parameter values right away.
499 */
501
503
504 /*
505 * Drop the items at the start, in reverse order
506 */
507 if (ropt->dropSchema)
508 {
509 for (te = AH->toc->prev; te != AH->toc; te = te->prev)
510 {
511 AH->currentTE = te;
512
513 /*
514 * In createDB mode, issue a DROP *only* for the database as a
515 * whole. Issuing drops against anything else would be wrong,
516 * because at this point we're connected to the wrong database.
517 * (The DATABASE PROPERTIES entry, if any, should be treated like
518 * the DATABASE entry.)
519 */
520 if (ropt->createDB)
521 {
522 if (strcmp(te->desc, "DATABASE") != 0 &&
523 strcmp(te->desc, "DATABASE PROPERTIES") != 0)
524 continue;
525 }
526
527 /* Otherwise, drop anything that's selected and has a dropStmt */
528 if (((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0) && te->dropStmt)
529 {
530 bool not_allowed_in_txn = false;
531
532 pg_log_info("dropping %s %s", te->desc, te->tag);
533
534 /*
535 * In --transaction-size mode, we have to temporarily exit our
536 * transaction block to drop objects that can't be dropped
537 * within a transaction.
538 */
539 if (ropt->txn_size > 0)
540 {
541 if (strcmp(te->desc, "DATABASE") == 0 ||
542 strcmp(te->desc, "DATABASE PROPERTIES") == 0)
543 {
544 not_allowed_in_txn = true;
545 if (AH->connection)
547 else
548 ahprintf(AH, "COMMIT;\n");
549 }
550 }
551
552 /* Select owner and schema as necessary */
553 _becomeOwner(AH, te);
554 _selectOutputSchema(AH, te->namespace);
555
556 /*
557 * Now emit the DROP command, if the object has one. Note we
558 * don't necessarily emit it verbatim; at this point we add an
559 * appropriate IF EXISTS clause, if the user requested it.
560 */
561 if (strcmp(te->desc, "BLOB METADATA") == 0)
562 {
563 /* We must generate the per-blob commands */
564 if (ropt->if_exists)
565 IssueCommandPerBlob(AH, te,
566 "SELECT pg_catalog.lo_unlink(oid) "
567 "FROM pg_catalog.pg_largeobject_metadata "
568 "WHERE oid = '", "'");
569 else
570 IssueCommandPerBlob(AH, te,
571 "SELECT pg_catalog.lo_unlink('",
572 "')");
573 }
574 else if (*te->dropStmt != '\0')
575 {
576 if (!ropt->if_exists ||
577 strncmp(te->dropStmt, "--", 2) == 0)
578 {
579 /*
580 * Without --if-exists, or if it's just a comment (as
581 * happens for the public schema), print the dropStmt
582 * as-is.
583 */
584 ahprintf(AH, "%s", te->dropStmt);
585 }
586 else
587 {
588 /*
589 * Inject an appropriate spelling of "if exists". For
590 * old-style large objects, we have a routine that
591 * knows how to do it, without depending on
592 * te->dropStmt; use that. For other objects we need
593 * to parse the command.
594 */
595 if (strcmp(te->desc, "BLOB") == 0)
596 {
598 }
599 else
600 {
601 char *dropStmt = pg_strdup(te->dropStmt);
602 char *dropStmtOrig = dropStmt;
604
605 /*
606 * Need to inject IF EXISTS clause after ALTER
607 * TABLE part in ALTER TABLE .. DROP statement
608 */
609 if (strncmp(dropStmt, "ALTER TABLE", 11) == 0)
610 {
612 "ALTER TABLE IF EXISTS");
613 dropStmt = dropStmt + 11;
614 }
615
616 /*
617 * ALTER TABLE..ALTER COLUMN..DROP DEFAULT does
618 * not support the IF EXISTS clause, and therefore
619 * we simply emit the original command for DEFAULT
620 * objects (modulo the adjustment made above).
621 *
622 * Likewise, don't mess with DATABASE PROPERTIES.
623 *
624 * If we used CREATE OR REPLACE VIEW as a means of
625 * quasi-dropping an ON SELECT rule, that should
626 * be emitted unchanged as well.
627 *
628 * For other object types, we need to extract the
629 * first part of the DROP which includes the
630 * object type. Most of the time this matches
631 * te->desc, so search for that; however for the
632 * different kinds of CONSTRAINTs, we know to
633 * search for hardcoded "DROP CONSTRAINT" instead.
634 */
635 if (strcmp(te->desc, "DEFAULT") == 0 ||
636 strcmp(te->desc, "DATABASE PROPERTIES") == 0 ||
637 strncmp(dropStmt, "CREATE OR REPLACE VIEW", 22) == 0)
638 appendPQExpBufferStr(ftStmt, dropStmt);
639 else
640 {
641 char buffer[40];
642 char *mark;
643
644 if (strcmp(te->desc, "CONSTRAINT") == 0 ||
645 strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
646 strcmp(te->desc, "FK CONSTRAINT") == 0)
647 strcpy(buffer, "DROP CONSTRAINT");
648 else
649 snprintf(buffer, sizeof(buffer), "DROP %s",
650 te->desc);
651
652 mark = strstr(dropStmt, buffer);
653
654 if (mark)
655 {
656 *mark = '\0';
657 appendPQExpBuffer(ftStmt, "%s%s IF EXISTS%s",
658 dropStmt, buffer,
659 mark + strlen(buffer));
660 }
661 else
662 {
663 /* complain and emit unmodified command */
664 pg_log_warning("could not find where to insert IF EXISTS in statement \"%s\"",
666 appendPQExpBufferStr(ftStmt, dropStmt);
667 }
668 }
669
670 ahprintf(AH, "%s", ftStmt->data);
671
674 }
675 }
676 }
677
678 /*
679 * In --transaction-size mode, re-establish the transaction
680 * block if needed; otherwise, commit after every N drops.
681 */
682 if (ropt->txn_size > 0)
683 {
685 {
686 if (AH->connection)
687 StartTransaction(AHX);
688 else
689 ahprintf(AH, "BEGIN;\n");
690 AH->txnCount = 0;
691 }
692 else if (++AH->txnCount >= ropt->txn_size)
693 {
694 if (AH->connection)
695 {
697 StartTransaction(AHX);
698 }
699 else
700 ahprintf(AH, "COMMIT;\nBEGIN;\n");
701 AH->txnCount = 0;
702 }
703 }
704 }
705 }
706
707 /*
708 * _selectOutputSchema may have set currSchema to reflect the effect
709 * of a "SET search_path" command it emitted. However, by now we may
710 * have dropped that schema; or it might not have existed in the first
711 * place. In either case the effective value of search_path will not
712 * be what we think. Forcibly reset currSchema so that we will
713 * re-establish the search_path setting when needed (after creating
714 * the schema).
715 *
716 * If we treated users as pg_dump'able objects then we'd need to reset
717 * currUser here too.
718 */
719 free(AH->currSchema);
720 AH->currSchema = NULL;
721 }
722
723 if (parallel_mode)
724 {
725 /*
726 * In parallel mode, turn control over to the parallel-restore logic.
727 */
728 ParallelState *pstate;
730
731 /* The archive format module may need some setup for this */
734
736
737 /* This runs PRE_DATA items and then disconnects from the database */
739 Assert(AH->connection == NULL);
740
741 /* ParallelBackupStart() will actually fork the processes */
742 pstate = ParallelBackupStart(AH);
744 ParallelBackupEnd(AH, pstate);
745
746 /* reconnect the leader and see if we missed something */
748 Assert(AH->connection != NULL);
749 }
750 else
751 {
752 /*
753 * In serial mode, process everything in three phases: normal items,
754 * then ACLs, then post-ACL items. We might be able to skip one or
755 * both extra phases in some cases, eg data-only restores.
756 */
757 bool haveACL = false;
758 bool havePostACL = false;
759
760 for (te = AH->toc->next; te != AH->toc; te = te->next)
761 {
762 if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) == 0)
763 continue; /* ignore if not to be dumped at all */
764
765 switch (_tocEntryRestorePass(te))
766 {
768 (void) restore_toc_entry(AH, te, false);
769 break;
770 case RESTORE_PASS_ACL:
771 haveACL = true;
772 break;
774 havePostACL = true;
775 break;
776 }
777 }
778
779 if (haveACL)
780 {
781 for (te = AH->toc->next; te != AH->toc; te = te->next)
782 {
783 if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0 &&
785 (void) restore_toc_entry(AH, te, false);
786 }
787 }
788
789 if (havePostACL)
790 {
791 for (te = AH->toc->next; te != AH->toc; te = te->next)
792 {
793 if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0 &&
795 (void) restore_toc_entry(AH, te, false);
796 }
797 }
798 }
799
800 /*
801 * Close out any persistent transaction we may have. While these two
802 * cases are started in different places, we can end both cases here.
803 */
804 if (ropt->single_txn || ropt->txn_size > 0)
805 {
806 if (AH->connection)
808 else
809 ahprintf(AH, "COMMIT;\n\n");
810 }
811
812 if (AH->public.verbose)
813 dumpTimestamp(AH, "Completed on", time(NULL));
814
815 ahprintf(AH, "--\n-- PostgreSQL database dump complete\n--\n\n");
816
817 /*
818 * If generating plain-text output, exit restricted mode at the very end
819 * of the script. This is not pro forma; in particular, pg_dumpall
820 * requires this when transitioning from one database to another.
821 */
822 if (ropt->restrict_key)
823 ahprintf(AH, "\\unrestrict %s\n\n", ropt->restrict_key);
824
825 /*
826 * Clean up & we're done.
827 */
829
831 RestoreOutput(AH, sav);
832
833 if (ropt->useDB)
835}
836
837/*
838 * Restore a single TOC item. Used in both parallel and non-parallel restore;
839 * is_parallel is true if we are in a worker child process.
840 *
841 * Returns 0 normally, but WORKER_CREATE_DONE or WORKER_INHIBIT_DATA if
842 * the parallel parent has to make the corresponding status update.
843 */
844static int
846{
847 RestoreOptions *ropt = AH->public.ropt;
848 int status = WORKER_OK;
849 int reqs;
850 bool defnDumped;
851
852 AH->currentTE = te;
853
854 /* Dump any relevant dump warnings to stderr */
855 if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0)
856 {
857 if (ropt->dumpSchema && te->defn != NULL && strlen(te->defn) != 0)
858 pg_log_warning("warning from original dump file: %s", te->defn);
859 else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0)
860 pg_log_warning("warning from original dump file: %s", te->copyStmt);
861 }
862
863 /* Work out what, if anything, we want from this entry */
864 reqs = te->reqs;
865
866 defnDumped = false;
867
868 /*
869 * If it has a schema component that we want, then process that
870 */
871 if ((reqs & REQ_SCHEMA) != 0)
872 {
873 bool object_is_db = false;
874
875 /*
876 * In --transaction-size mode, must exit our transaction block to
877 * create a database or set its properties.
878 */
879 if (strcmp(te->desc, "DATABASE") == 0 ||
880 strcmp(te->desc, "DATABASE PROPERTIES") == 0)
881 {
882 object_is_db = true;
883 if (ropt->txn_size > 0)
884 {
885 if (AH->connection)
887 else
888 ahprintf(AH, "COMMIT;\n\n");
889 }
890 }
891
892 /* Show namespace in log message if available */
893 if (te->namespace)
894 pg_log_info("creating %s \"%s.%s\"",
895 te->desc, te->namespace, te->tag);
896 else
897 pg_log_info("creating %s \"%s\"",
898 te->desc, te->tag);
899
901 defnDumped = true;
902
903 if (strcmp(te->desc, "TABLE") == 0)
904 {
905 if (AH->lastErrorTE == te)
906 {
907 /*
908 * We failed to create the table. If
909 * --no-data-for-failed-tables was given, mark the
910 * corresponding TABLE DATA to be ignored.
911 *
912 * In the parallel case this must be done in the parent, so we
913 * just set the return value.
914 */
915 if (ropt->noDataForFailedTables)
916 {
917 if (is_parallel)
918 status = WORKER_INHIBIT_DATA;
919 else
921 }
922 }
923 else
924 {
925 /*
926 * We created the table successfully. Mark the corresponding
927 * TABLE DATA for possible truncation.
928 *
929 * In the parallel case this must be done in the parent, so we
930 * just set the return value.
931 */
932 if (is_parallel)
933 status = WORKER_CREATE_DONE;
934 else
935 mark_create_done(AH, te);
936 }
937 }
938
939 /*
940 * If we created a DB, connect to it. Also, if we changed DB
941 * properties, reconnect to ensure that relevant GUC settings are
942 * applied to our session. (That also restarts the transaction block
943 * in --transaction-size mode.)
944 */
945 if (object_is_db)
946 {
947 pg_log_info("connecting to new database \"%s\"", te->tag);
948 _reconnectToDB(AH, te->tag);
949 }
950 }
951
952 /*
953 * If it has a data component that we want, then process that
954 */
955 if ((reqs & REQ_DATA) != 0)
956 {
957 /*
958 * hadDumper will be set if there is genuine data component for this
959 * node. Otherwise, we need to check the defn field for statements
960 * that need to be executed in data-only restores.
961 */
962 if (te->hadDumper)
963 {
964 /*
965 * If we can output the data, then restore it.
966 */
967 if (AH->PrintTocDataPtr != NULL)
968 {
970
971 if (strcmp(te->desc, "BLOBS") == 0 ||
972 strcmp(te->desc, "BLOB COMMENTS") == 0)
973 {
974 pg_log_info("processing %s", te->desc);
975
976 _selectOutputSchema(AH, "pg_catalog");
977
978 /* Send BLOB COMMENTS data to ExecuteSimpleCommands() */
979 if (strcmp(te->desc, "BLOB COMMENTS") == 0)
981
982 AH->PrintTocDataPtr(AH, te);
983
985 }
986 else
987 {
988 bool use_truncate;
989
991
992 /* Select owner and schema as necessary */
993 _becomeOwner(AH, te);
994 _selectOutputSchema(AH, te->namespace);
995
996 pg_log_info("processing data for table \"%s.%s\"",
997 te->namespace, te->tag);
998
999 /*
1000 * In parallel restore, if we created the table earlier in
1001 * this run (so that we know it is empty) and we are not
1002 * restoring a load-via-partition-root data item then we
1003 * wrap the COPY in a transaction and precede it with a
1004 * TRUNCATE. If wal_level is set to minimal this prevents
1005 * WAL-logging the COPY. This obtains a speedup similar
1006 * to that from using single_txn mode in non-parallel
1007 * restores.
1008 *
1009 * We mustn't do this for load-via-partition-root cases
1010 * because some data might get moved across partition
1011 * boundaries, risking deadlock and/or loss of previously
1012 * loaded data. (We assume that all partitions of a
1013 * partitioned table will be treated the same way.)
1014 */
1015 use_truncate = is_parallel && te->created &&
1017
1018 if (use_truncate)
1019 {
1020 /*
1021 * Parallel restore is always talking directly to a
1022 * server, so no need to see if we should issue BEGIN.
1023 */
1025
1026 /*
1027 * Issue TRUNCATE with ONLY so that child tables are
1028 * not wiped.
1029 */
1030 ahprintf(AH, "TRUNCATE TABLE ONLY %s;\n\n",
1031 fmtQualifiedId(te->namespace, te->tag));
1032 }
1033
1034 /*
1035 * If we have a copy statement, use it.
1036 */
1037 if (te->copyStmt && strlen(te->copyStmt) > 0)
1038 {
1039 ahprintf(AH, "%s", te->copyStmt);
1041 }
1042 else
1044
1045 AH->PrintTocDataPtr(AH, te);
1046
1047 /*
1048 * Terminate COPY if needed.
1049 */
1050 if (AH->outputKind == OUTPUT_COPYDATA &&
1051 RestoringToDB(AH))
1052 EndDBCopyMode(&AH->public, te->tag);
1054
1055 /* close out the transaction started above */
1056 if (use_truncate)
1058
1060 }
1061 }
1062 }
1063 else if (!defnDumped)
1064 {
1065 /* If we haven't already dumped the defn part, do so now */
1066 pg_log_info("executing %s %s", te->desc, te->tag);
1068 }
1069 }
1070
1071 /*
1072 * If it has a statistics component that we want, then process that
1073 */
1074 if ((reqs & REQ_STATS) != 0)
1076
1077 /*
1078 * If we emitted anything for this TOC entry, that counts as one action
1079 * against the transaction-size limit. Commit if it's time to.
1080 */
1081 if ((reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0 && ropt->txn_size > 0)
1082 {
1083 if (++AH->txnCount >= ropt->txn_size)
1084 {
1085 if (AH->connection)
1086 {
1089 }
1090 else
1091 ahprintf(AH, "COMMIT;\nBEGIN;\n\n");
1092 AH->txnCount = 0;
1093 }
1094 }
1095
1096 if (AH->public.n_errors > 0 && status == WORKER_OK)
1097 status = WORKER_IGNORED_ERRORS;
1098
1099 return status;
1100}
1101
1102/*
1103 * Allocate a new RestoreOptions block.
1104 * This is mainly so we can initialize it, but also for future expansion,
1105 */
1108{
1110
1112
1113 /* set any fields that shouldn't default to zeroes */
1114 opts->format = archUnknown;
1115 opts->cparams.promptPassword = TRI_DEFAULT;
1116 opts->dumpSections = DUMP_UNSECTIONED;
1117 opts->compression_spec.algorithm = PG_COMPRESSION_NONE;
1118 opts->compression_spec.level = 0;
1119 opts->dumpSchema = true;
1120 opts->dumpData = true;
1121 opts->dumpStatistics = true;
1122
1123 return opts;
1124}
1125
1126static void
1128{
1129 RestoreOptions *ropt = AH->public.ropt;
1130
1131 /* This hack is only needed in a data-only restore */
1132 if (ropt->dumpSchema || !ropt->disable_triggers)
1133 return;
1134
1135 pg_log_info("disabling triggers for %s", te->tag);
1136
1137 /*
1138 * Become superuser if possible, since they are the only ones who can
1139 * disable constraint triggers. If -S was not given, assume the initial
1140 * user identity is a superuser. (XXX would it be better to become the
1141 * table owner?)
1142 */
1143 _becomeUser(AH, ropt->superuser);
1144
1145 /*
1146 * Disable them.
1147 */
1148 ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n",
1149 fmtQualifiedId(te->namespace, te->tag));
1150}
1151
1152static void
1154{
1155 RestoreOptions *ropt = AH->public.ropt;
1156
1157 /* This hack is only needed in a data-only restore */
1158 if (ropt->dumpSchema || !ropt->disable_triggers)
1159 return;
1160
1161 pg_log_info("enabling triggers for %s", te->tag);
1162
1163 /*
1164 * Become superuser if possible, since they are the only ones who can
1165 * disable constraint triggers. If -S was not given, assume the initial
1166 * user identity is a superuser. (XXX would it be better to become the
1167 * table owner?)
1168 */
1169 _becomeUser(AH, ropt->superuser);
1170
1171 /*
1172 * Enable them.
1173 */
1174 ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n",
1175 fmtQualifiedId(te->namespace, te->tag));
1176}
1177
1178/*
1179 * Detect whether a TABLE DATA TOC item is performing "load via partition
1180 * root", that is the target table is an ancestor partition rather than the
1181 * table the TOC item is nominally for.
1182 *
1183 * In newer archive files this can be detected by checking for a special
1184 * comment placed in te->defn. In older files we have to fall back to seeing
1185 * if the COPY statement targets the named table or some other one. This
1186 * will not work for data dumped as INSERT commands, so we could give a false
1187 * negative in that case; fortunately, that's a rarely-used option.
1188 */
1189static bool
1191{
1192 if (te->defn &&
1193 strncmp(te->defn, "-- load via partition root ", 27) == 0)
1194 return true;
1195 if (te->copyStmt && *te->copyStmt)
1196 {
1197 PQExpBuffer copyStmt = createPQExpBuffer();
1198 bool result;
1199
1200 /*
1201 * Build the initial part of the COPY as it would appear if the
1202 * nominal target table is the actual target. If we see anything
1203 * else, it must be a load-via-partition-root case.
1204 */
1205 appendPQExpBuffer(copyStmt, "COPY %s ",
1206 fmtQualifiedId(te->namespace, te->tag));
1207 result = strncmp(te->copyStmt, copyStmt->data, copyStmt->len) != 0;
1208 destroyPQExpBuffer(copyStmt);
1209 return result;
1210 }
1211 /* Assume it's not load-via-partition-root */
1212 return false;
1213}
1214
1215/*
1216 * This is a routine that is part of the dumper interface, hence the 'Archive*' parameter.
1217 */
1218
1219/* Public */
1220void
1221WriteData(Archive *AHX, const void *data, size_t dLen)
1222{
1223 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1224
1225 if (!AH->currToc)
1226 pg_fatal("internal error -- WriteData cannot be called outside the context of a DataDumper routine");
1227
1228 AH->WriteDataPtr(AH, data, dLen);
1229}
1230
1231/*
1232 * Create a new TOC entry. The TOC was designed as a TOC, but is now the
1233 * repository for all metadata. But the name has stuck.
1234 *
1235 * The new entry is added to the Archive's TOC list. Most callers can ignore
1236 * the result value because nothing else need be done, but a few want to
1237 * manipulate the TOC entry further.
1238 */
1239
1240/* Public */
1241TocEntry *
1242ArchiveEntry(Archive *AHX, CatalogId catalogId, DumpId dumpId,
1244{
1245 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1247
1249
1250 AH->tocCount++;
1251 if (dumpId > AH->maxDumpId)
1252 AH->maxDumpId = dumpId;
1253
1254 newToc->prev = AH->toc->prev;
1255 newToc->next = AH->toc;
1256 AH->toc->prev->next = newToc;
1257 AH->toc->prev = newToc;
1258
1259 newToc->catalogId = catalogId;
1260 newToc->dumpId = dumpId;
1261 newToc->section = opts->section;
1262
1263 newToc->tag = pg_strdup(opts->tag);
1264 newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL;
1265 newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL;
1266 newToc->tableam = opts->tableam ? pg_strdup(opts->tableam) : NULL;
1267 newToc->relkind = opts->relkind;
1268 newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL;
1269 newToc->desc = pg_strdup(opts->description);
1270 newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL;
1271 newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL;
1272 newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL;
1273
1274 if (opts->nDeps > 0)
1275 {
1276 newToc->dependencies = pg_malloc_array(DumpId, opts->nDeps);
1277 memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId));
1278 newToc->nDeps = opts->nDeps;
1279 }
1280 else
1281 {
1282 newToc->dependencies = NULL;
1283 newToc->nDeps = 0;
1284 }
1285
1286 newToc->dataDumper = opts->dumpFn;
1287 newToc->dataDumperArg = opts->dumpArg;
1288 newToc->hadDumper = opts->dumpFn ? true : false;
1289
1290 newToc->defnDumper = opts->defnFn;
1291 newToc->defnDumperArg = opts->defnArg;
1292
1293 newToc->formatData = NULL;
1294 newToc->dataLength = 0;
1295
1296 if (AH->ArchiveEntryPtr != NULL)
1297 AH->ArchiveEntryPtr(AH, newToc);
1298
1299 return newToc;
1300}
1301
1302/* Public */
1303void
1305{
1306 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1307 RestoreOptions *ropt = AH->public.ropt;
1308 TocEntry *te;
1312 const char *fmtName;
1313 char stamp_str[64];
1314
1315 /* TOC is always uncompressed */
1317
1318 sav = SaveOutput(AH);
1319 if (ropt->filename)
1321
1323 localtime(&AH->createDate)) == 0)
1324 strcpy(stamp_str, "[unknown]");
1325
1326 ahprintf(AH, ";\n; Archive created at %s\n", stamp_str);
1327 ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %s\n",
1328 sanitize_line(AH->archdbname, false),
1329 AH->tocCount,
1331
1332 switch (AH->format)
1333 {
1334 case archCustom:
1335 fmtName = "CUSTOM";
1336 break;
1337 case archDirectory:
1338 fmtName = "DIRECTORY";
1339 break;
1340 case archTar:
1341 fmtName = "TAR";
1342 break;
1343 default:
1344 fmtName = "UNKNOWN";
1345 }
1346
1347 ahprintf(AH, "; Dump Version: %d.%d-%d\n",
1349 ahprintf(AH, "; Format: %s\n", fmtName);
1350 ahprintf(AH, "; Integer: %zu bytes\n", AH->intSize);
1351 ahprintf(AH, "; Offset: %zu bytes\n", AH->offSize);
1352 if (AH->archiveRemoteVersion)
1353 ahprintf(AH, "; Dumped from database version: %s\n",
1355 if (AH->archiveDumpVersion)
1356 ahprintf(AH, "; Dumped by pg_dump version: %s\n",
1357 AH->archiveDumpVersion);
1358
1359 ahprintf(AH, ";\n;\n; Selected TOC Entries:\n;\n");
1360
1362 for (te = AH->toc->next; te != AH->toc; te = te->next)
1363 {
1364 /* This bit must match ProcessArchiveRestoreOptions' marking logic */
1365 if (te->section != SECTION_NONE)
1366 curSection = te->section;
1367 te->reqs = _tocEntryRequired(te, curSection, AH);
1368 /* Now, should we print it? */
1369 if (ropt->verbose ||
1370 (te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) != 0)
1371 {
1372 char *sanitized_name;
1373 char *sanitized_schema;
1374 char *sanitized_owner;
1375
1376 /*
1377 */
1378 sanitized_name = sanitize_line(te->tag, false);
1379 sanitized_schema = sanitize_line(te->namespace, true);
1380 sanitized_owner = sanitize_line(te->owner, false);
1381
1382 ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
1386
1390 }
1391 if (ropt->verbose && te->nDeps > 0)
1392 {
1393 int i;
1394
1395 ahprintf(AH, ";\tdepends on:");
1396 for (i = 0; i < te->nDeps; i++)
1397 ahprintf(AH, " %d", te->dependencies[i]);
1398 ahprintf(AH, "\n");
1399 }
1400 }
1401
1402 /* Enforce strict names checking */
1403 if (ropt->strict_names)
1404 StrictNamesCheck(ropt);
1405
1406 if (ropt->filename)
1407 RestoreOutput(AH, sav);
1408}
1409
1410/***********
1411 * Large Object Archival
1412 ***********/
1413
1414/* Called by a dumper to signal start of a LO */
1415int
1417{
1418 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1419
1420 if (!AH->StartLOPtr)
1421 pg_fatal("large-object output not supported in chosen format");
1422
1423 AH->StartLOPtr(AH, AH->currToc, oid);
1424
1425 return 1;
1426}
1427
1428/* Called by a dumper to signal end of a LO */
1429int
1431{
1432 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1433
1434 if (AH->EndLOPtr)
1435 AH->EndLOPtr(AH, AH->currToc, oid);
1436
1437 return 1;
1438}
1439
1440/**********
1441 * Large Object Restoration
1442 **********/
1443
1444/*
1445 * Called by a format handler before a group of LOs is restored
1446 */
1447void
1449{
1450 RestoreOptions *ropt = AH->public.ropt;
1451
1452 /*
1453 * LOs must be restored within a transaction block, since we need the LO
1454 * handle to stay open while we write it. Establish a transaction unless
1455 * there's one being used globally.
1456 */
1457 if (!(ropt->single_txn || ropt->txn_size > 0))
1458 {
1459 if (AH->connection)
1461 else
1462 ahprintf(AH, "BEGIN;\n\n");
1463 }
1464
1465 AH->loCount = 0;
1466}
1467
1468/*
1469 * Called by a format handler after a group of LOs is restored
1470 */
1471void
1473{
1474 RestoreOptions *ropt = AH->public.ropt;
1475
1476 if (!(ropt->single_txn || ropt->txn_size > 0))
1477 {
1478 if (AH->connection)
1480 else
1481 ahprintf(AH, "COMMIT;\n\n");
1482 }
1483
1484 pg_log_info(ngettext("restored %d large object",
1485 "restored %d large objects",
1486 AH->loCount),
1487 AH->loCount);
1488}
1489
1490
1491/*
1492 * Called by a format handler to initiate restoration of a LO
1493 */
1494void
1496{
1497 bool old_lo_style = (AH->version < K_VERS_1_12);
1498 Oid loOid;
1499
1500 AH->loCount++;
1501
1502 /* Initialize the LO Buffer */
1503 if (AH->lo_buf == NULL)
1504 {
1505 /* First time through (in this process) so allocate the buffer */
1506 AH->lo_buf_size = LOBBUFSIZE;
1508 }
1509 AH->lo_buf_used = 0;
1510
1511 pg_log_info("restoring large object with OID %u", oid);
1512
1513 /* With an old archive we must do drop and create logic here */
1514 if (old_lo_style && drop)
1515 DropLOIfExists(AH, oid);
1516
1517 if (AH->connection)
1518 {
1519 if (old_lo_style)
1520 {
1521 loOid = lo_create(AH->connection, oid);
1522 if (loOid == 0 || loOid != oid)
1523 pg_fatal("could not create large object %u: %s",
1524 oid, PQerrorMessage(AH->connection));
1525 }
1526 AH->loFd = lo_open(AH->connection, oid, INV_WRITE);
1527 if (AH->loFd == -1)
1528 pg_fatal("could not open large object %u: %s",
1529 oid, PQerrorMessage(AH->connection));
1530 }
1531 else
1532 {
1533 if (old_lo_style)
1534 ahprintf(AH, "SELECT pg_catalog.lo_open(pg_catalog.lo_create('%u'), %d);\n",
1535 oid, INV_WRITE);
1536 else
1537 ahprintf(AH, "SELECT pg_catalog.lo_open('%u', %d);\n",
1538 oid, INV_WRITE);
1539 }
1540
1541 AH->writingLO = true;
1542}
1543
1544void
1546{
1547 if (AH->lo_buf_used > 0)
1548 {
1549 /* Write remaining bytes from the LO buffer */
1550 dump_lo_buf(AH);
1551 }
1552
1553 AH->writingLO = false;
1554
1555 if (AH->connection)
1556 {
1557 lo_close(AH->connection, AH->loFd);
1558 AH->loFd = -1;
1559 }
1560 else
1561 {
1562 ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n");
1563 }
1564}
1565
1566/***********
1567 * Sorting and Reordering
1568 ***********/
1569
1570void
1572{
1573 ArchiveHandle *AH = (ArchiveHandle *) AHX;
1574 RestoreOptions *ropt = AH->public.ropt;
1575 FILE *fh;
1577
1578 /* Allocate space for the 'wanted' array, and init it */
1579 ropt->idWanted = pg_malloc0_array(bool, AH->maxDumpId);
1580
1581 /* Setup the file */
1582 fh = fopen(ropt->tocFile, PG_BINARY_R);
1583 if (!fh)
1584 pg_fatal("could not open TOC file \"%s\": %m", ropt->tocFile);
1585
1587
1588 while (pg_get_line_buf(fh, &linebuf))
1589 {
1590 char *cmnt;
1591 char *endptr;
1592 DumpId id;
1593 TocEntry *te;
1594
1595 /* Truncate line at comment, if any */
1596 cmnt = strchr(linebuf.data, ';');
1597 if (cmnt != NULL)
1598 {
1599 cmnt[0] = '\0';
1600 linebuf.len = cmnt - linebuf.data;
1601 }
1602
1603 /* Ignore if all blank */
1604 if (strspn(linebuf.data, " \t\r\n") == linebuf.len)
1605 continue;
1606
1607 /* Get an ID, check it's valid and not already seen */
1608 id = strtol(linebuf.data, &endptr, 10);
1609 if (endptr == linebuf.data || id <= 0 || id > AH->maxDumpId ||
1610 ropt->idWanted[id - 1])
1611 {
1612 pg_log_warning("line ignored: %s", linebuf.data);
1613 continue;
1614 }
1615
1616 /* Find TOC entry */
1617 te = getTocEntryByDumpId(AH, id);
1618 if (!te)
1619 pg_fatal("could not find entry for ID %d",
1620 id);
1621
1622 /* Mark it wanted */
1623 ropt->idWanted[id - 1] = true;
1624
1625 /*
1626 * Move each item to the end of the list as it is selected, so that
1627 * they are placed in the desired order. Any unwanted items will end
1628 * up at the front of the list, which may seem unintuitive but it's
1629 * what we need. In an ordinary serial restore that makes no
1630 * difference, but in a parallel restore we need to mark unrestored
1631 * items' dependencies as satisfied before we start examining
1632 * restorable items. Otherwise they could have surprising
1633 * side-effects on the order in which restorable items actually get
1634 * restored.
1635 */
1636 _moveBefore(AH->toc, te);
1637 }
1638
1639 pg_free(linebuf.data);
1640
1641 if (fclose(fh) != 0)
1642 pg_fatal("could not close TOC file: %m");
1643}
1644
1645/**********************
1646 * Convenience functions that look like standard IO functions
1647 * for writing data when in dump mode.
1648 **********************/
1649
1650/* Public */
1651void
1652archputs(const char *s, Archive *AH)
1653{
1654 WriteData(AH, s, strlen(s));
1655}
1656
1657/* Public */
1658int
1659archprintf(Archive *AH, const char *fmt, ...)
1660{
1661 int save_errno = errno;
1662 char *p;
1663 size_t len = 128; /* initial assumption about buffer size */
1664 size_t cnt;
1665
1666 for (;;)
1667 {
1668 va_list args;
1669
1670 /* Allocate work buffer. */
1671 p = (char *) pg_malloc(len);
1672
1673 /* Try to format the data. */
1674 errno = save_errno;
1675 va_start(args, fmt);
1676 cnt = pvsnprintf(p, len, fmt, args);
1677 va_end(args);
1678
1679 if (cnt < len)
1680 break; /* success */
1681
1682 /* Release buffer and loop around to try again with larger len. */
1683 free(p);
1684 len = cnt;
1685 }
1686
1687 WriteData(AH, p, cnt);
1688 free(p);
1689 return (int) cnt;
1690}
1691
1692
1693/*******************************
1694 * Stuff below here should be 'private' to the archiver routines
1695 *******************************/
1696
1697static void
1699 const pg_compress_specification compression_spec)
1700{
1702 const char *mode;
1703 int fn = -1;
1704
1705 if (filename)
1706 {
1707 if (strcmp(filename, "-") == 0)
1708 fn = fileno(stdout);
1709 }
1710 else if (AH->FH)
1711 fn = fileno(AH->FH);
1712 else if (AH->fSpec)
1713 {
1714 filename = AH->fSpec;
1715 }
1716 else
1717 fn = fileno(stdout);
1718
1719 if (AH->mode == archModeAppend)
1720 mode = PG_BINARY_A;
1721 else
1722 mode = PG_BINARY_W;
1723
1724 CFH = InitCompressFileHandle(compression_spec);
1725
1726 if (!CFH->open_func(filename, fn, mode, CFH))
1727 {
1728 if (filename)
1729 pg_fatal("could not open output file \"%s\": %m", filename);
1730 else
1731 pg_fatal("could not open output file: %m");
1732 }
1733
1734 AH->OF = CFH;
1735}
1736
1737static CompressFileHandle *
1739{
1740 return (CompressFileHandle *) AH->OF;
1741}
1742
1743static void
1745{
1746 errno = 0;
1747 if (!EndCompressFileHandle(AH->OF))
1748 pg_fatal("could not close output file: %m");
1749
1750 AH->OF = savedOutput;
1751}
1752
1753
1754
1755/*
1756 * Print formatted text to the output file (usually stdout).
1757 */
1758int
1759ahprintf(ArchiveHandle *AH, const char *fmt, ...)
1760{
1761 int save_errno = errno;
1762 char *p;
1763 size_t len = 128; /* initial assumption about buffer size */
1764 size_t cnt;
1765
1766 for (;;)
1767 {
1768 va_list args;
1769
1770 /* Allocate work buffer. */
1771 p = (char *) pg_malloc(len);
1772
1773 /* Try to format the data. */
1774 errno = save_errno;
1775 va_start(args, fmt);
1776 cnt = pvsnprintf(p, len, fmt, args);
1777 va_end(args);
1778
1779 if (cnt < len)
1780 break; /* success */
1781
1782 /* Release buffer and loop around to try again with larger len. */
1783 free(p);
1784 len = cnt;
1785 }
1786
1787 ahwrite(p, 1, cnt, AH);
1788 free(p);
1789 return (int) cnt;
1790}
1791
1792/*
1793 * Single place for logic which says 'We are restoring to a direct DB connection'.
1794 */
1795static int
1797{
1798 RestoreOptions *ropt = AH->public.ropt;
1799
1800 return (ropt && ropt->useDB && AH->connection);
1801}
1802
1803/*
1804 * Dump the current contents of the LO data buffer while writing a LO
1805 */
1806static void
1808{
1809 if (AH->connection)
1810 {
1811 int res;
1812
1813 res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
1814 pg_log_debug(ngettext("wrote %zu byte of large object data (result = %d)",
1815 "wrote %zu bytes of large object data (result = %d)",
1816 AH->lo_buf_used),
1817 AH->lo_buf_used, res);
1818 /* We assume there are no short writes, only errors */
1819 if (res != AH->lo_buf_used)
1820 warn_or_exit_horribly(AH, "could not write to large object: %s",
1822 }
1823 else
1824 {
1826
1828 (const unsigned char *) AH->lo_buf,
1829 AH->lo_buf_used,
1830 AH);
1831
1832 /* Hack: turn off writingLO so ahwrite doesn't recurse to here */
1833 AH->writingLO = false;
1834 ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data);
1835 AH->writingLO = true;
1836
1838 }
1839 AH->lo_buf_used = 0;
1840}
1841
1842
1843/*
1844 * Write buffer to the output file (usually stdout). This is used for
1845 * outputting 'restore' scripts etc. It is even possible for an archive
1846 * format to create a custom output routine to 'fake' a restore if it
1847 * wants to generate a script (see TAR output).
1848 */
1849void
1850ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
1851{
1852 int bytes_written = 0;
1853
1854 if (AH->writingLO)
1855 {
1856 size_t remaining = size * nmemb;
1857
1858 while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1859 {
1860 size_t avail = AH->lo_buf_size - AH->lo_buf_used;
1861
1862 memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
1863 ptr = (const char *) ptr + avail;
1864 remaining -= avail;
1865 AH->lo_buf_used += avail;
1866 dump_lo_buf(AH);
1867 }
1868
1869 memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1870 AH->lo_buf_used += remaining;
1871
1872 bytes_written = size * nmemb;
1873 }
1874 else if (AH->CustomOutPtr)
1875 bytes_written = AH->CustomOutPtr(AH, ptr, size * nmemb);
1876
1877 /*
1878 * If we're doing a restore, and it's direct to DB, and we're connected
1879 * then send it to the DB.
1880 */
1881 else if (RestoringToDB(AH))
1882 bytes_written = ExecuteSqlCommandBuf(&AH->public, (const char *) ptr, size * nmemb);
1883 else
1884 {
1886
1887 CFH->write_func(ptr, size * nmemb, CFH);
1888 bytes_written = size * nmemb;
1889 }
1890
1891 if (bytes_written != size * nmemb)
1893}
1894
1895/* on some error, we may decide to go on... */
1896void
1898{
1899 va_list ap;
1900
1901 switch (AH->stage)
1902 {
1903
1904 case STAGE_NONE:
1905 /* Do nothing special */
1906 break;
1907
1908 case STAGE_INITIALIZING:
1909 if (AH->stage != AH->lastErrorStage)
1910 pg_log_info("while INITIALIZING:");
1911 break;
1912
1913 case STAGE_PROCESSING:
1914 if (AH->stage != AH->lastErrorStage)
1915 pg_log_info("while PROCESSING TOC:");
1916 break;
1917
1918 case STAGE_FINALIZING:
1919 if (AH->stage != AH->lastErrorStage)
1920 pg_log_info("while FINALIZING:");
1921 break;
1922 }
1923 if (AH->currentTE != NULL && AH->currentTE != AH->lastErrorTE)
1924 {
1925 pg_log_info("from TOC entry %d; %u %u %s %s %s",
1926 AH->currentTE->dumpId,
1928 AH->currentTE->catalogId.oid,
1929 AH->currentTE->desc ? AH->currentTE->desc : "(no desc)",
1930 AH->currentTE->tag ? AH->currentTE->tag : "(no tag)",
1931 AH->currentTE->owner ? AH->currentTE->owner : "(no owner)");
1932 }
1933 AH->lastErrorStage = AH->stage;
1934 AH->lastErrorTE = AH->currentTE;
1935
1936 va_start(ap, fmt);
1938 va_end(ap);
1939
1940 if (AH->public.exit_on_error)
1941 exit_nicely(1);
1942 else
1943 AH->public.n_errors++;
1944}
1945
1946#ifdef NOT_USED
1947
1948static void
1950{
1951 /* Unlink te from list */
1952 te->prev->next = te->next;
1953 te->next->prev = te->prev;
1954
1955 /* and insert it after "pos" */
1956 te->prev = pos;
1957 te->next = pos->next;
1958 pos->next->prev = te;
1959 pos->next = te;
1960}
1961#endif
1962
1963static void
1965{
1966 /* Unlink te from list */
1967 te->prev->next = te->next;
1968 te->next->prev = te->prev;
1969
1970 /* and insert it before "pos" */
1971 te->prev = pos->prev;
1972 te->next = pos;
1973 pos->prev->next = te;
1974 pos->prev = te;
1975}
1976
1977/*
1978 * Build index arrays for the TOC list
1979 *
1980 * This should be invoked only after we have created or read in all the TOC
1981 * items.
1982 *
1983 * The arrays are indexed by dump ID (so entry zero is unused). Note that the
1984 * array entries run only up to maxDumpId. We might see dependency dump IDs
1985 * beyond that (if the dump was partial); so always check the array bound
1986 * before trying to touch an array entry.
1987 */
1988static void
1990{
1991 DumpId maxDumpId = AH->maxDumpId;
1992 TocEntry *te;
1993
1994 AH->tocsByDumpId = pg_malloc0_array(TocEntry *, (maxDumpId + 1));
1995 AH->tableDataId = pg_malloc0_array(DumpId, (maxDumpId + 1));
1996
1997 for (te = AH->toc->next; te != AH->toc; te = te->next)
1998 {
1999 /* this check is purely paranoia, maxDumpId should be correct */
2000 if (te->dumpId <= 0 || te->dumpId > maxDumpId)
2001 pg_fatal("bad dumpId");
2002
2003 /* tocsByDumpId indexes all TOCs by their dump ID */
2004 AH->tocsByDumpId[te->dumpId] = te;
2005
2006 /*
2007 * tableDataId provides the TABLE DATA item's dump ID for each TABLE
2008 * TOC entry that has a DATA item. We compute this by reversing the
2009 * TABLE DATA item's dependency, knowing that a TABLE DATA item has
2010 * just one dependency and it is the TABLE item.
2011 */
2012 if (strcmp(te->desc, "TABLE DATA") == 0 && te->nDeps > 0)
2013 {
2014 DumpId tableId = te->dependencies[0];
2015
2016 /*
2017 * The TABLE item might not have been in the archive, if this was
2018 * a data-only dump; but its dump ID should be less than its data
2019 * item's dump ID, so there should be a place for it in the array.
2020 */
2021 if (tableId <= 0 || tableId > maxDumpId)
2022 pg_fatal("bad table dumpId for TABLE DATA item");
2023
2024 AH->tableDataId[tableId] = te->dumpId;
2025 }
2026 }
2027}
2028
2029TocEntry *
2031{
2032 /* build index arrays if we didn't already */
2033 if (AH->tocsByDumpId == NULL)
2035
2036 if (id > 0 && id <= AH->maxDumpId)
2037 return AH->tocsByDumpId[id];
2038
2039 return NULL;
2040}
2041
2042int
2044{
2045 TocEntry *te = getTocEntryByDumpId(AH, id);
2046
2047 if (!te)
2048 return 0;
2049
2050 return te->reqs;
2051}
2052
2053size_t
2055{
2056 int off;
2057
2058 /* Save the flag */
2059 AH->WriteBytePtr(AH, wasSet);
2060
2061 /* Write out pgoff_t smallest byte first, prevents endian mismatch */
2062 for (off = 0; off < sizeof(pgoff_t); off++)
2063 {
2064 AH->WriteBytePtr(AH, o & 0xFF);
2065 o >>= 8;
2066 }
2067 return sizeof(pgoff_t) + 1;
2068}
2069
2070int
2072{
2073 int i;
2074 int off;
2075 int offsetFlg;
2076
2077 /* Initialize to zero */
2078 *o = 0;
2079
2080 /* Check for old version */
2081 if (AH->version < K_VERS_1_7)
2082 {
2083 /* Prior versions wrote offsets using WriteInt */
2084 i = ReadInt(AH);
2085 /* -1 means not set */
2086 if (i < 0)
2087 return K_OFFSET_POS_NOT_SET;
2088 else if (i == 0)
2089 return K_OFFSET_NO_DATA;
2090
2091 /* Cast to pgoff_t because it was written as an int. */
2092 *o = (pgoff_t) i;
2093 return K_OFFSET_POS_SET;
2094 }
2095
2096 /*
2097 * Read the flag indicating the state of the data pointer. Check if valid
2098 * and die if not.
2099 *
2100 * This used to be handled by a negative or zero pointer, now we use an
2101 * extra byte specifically for the state.
2102 */
2103 offsetFlg = AH->ReadBytePtr(AH) & 0xFF;
2104
2105 switch (offsetFlg)
2106 {
2108 case K_OFFSET_NO_DATA:
2109 case K_OFFSET_POS_SET:
2110
2111 break;
2112
2113 default:
2114 pg_fatal("unexpected data offset flag %d", offsetFlg);
2115 }
2116
2117 /*
2118 * Read the bytes
2119 */
2120 for (off = 0; off < AH->offSize; off++)
2121 {
2122 if (off < sizeof(pgoff_t))
2123 *o |= ((pgoff_t) (AH->ReadBytePtr(AH))) << (off * 8);
2124 else
2125 {
2126 if (AH->ReadBytePtr(AH) != 0)
2127 pg_fatal("file offset in dump file is too large");
2128 }
2129 }
2130
2131 return offsetFlg;
2132}
2133
2134size_t
2136{
2137 int b;
2138
2139 /*
2140 * This is a bit yucky, but I don't want to make the binary format very
2141 * dependent on representation, and not knowing much about it, I write out
2142 * a sign byte. If you change this, don't forget to change the file
2143 * version #, and modify ReadInt to read the new format AS WELL AS the old
2144 * formats.
2145 */
2146
2147 /* SIGN byte */
2148 if (i < 0)
2149 {
2150 AH->WriteBytePtr(AH, 1);
2151 i = -i;
2152 }
2153 else
2154 AH->WriteBytePtr(AH, 0);
2155
2156 for (b = 0; b < AH->intSize; b++)
2157 {
2158 AH->WriteBytePtr(AH, i & 0xFF);
2159 i >>= 8;
2160 }
2161
2162 return AH->intSize + 1;
2163}
2164
2165int
2167{
2168 int res = 0;
2169 int bv,
2170 b;
2171 int sign = 0; /* Default positive */
2172 int bitShift = 0;
2173
2174 if (AH->version > K_VERS_1_0)
2175 /* Read a sign byte */
2176 sign = AH->ReadBytePtr(AH);
2177
2178 for (b = 0; b < AH->intSize; b++)
2179 {
2180 bv = AH->ReadBytePtr(AH) & 0xFF;
2181 if (bv != 0)
2182 res = res + (bv << bitShift);
2183 bitShift += 8;
2184 }
2185
2186 if (sign)
2187 res = -res;
2188
2189 return res;
2190}
2191
2192size_t
2193WriteStr(ArchiveHandle *AH, const char *c)
2194{
2195 size_t res;
2196
2197 if (c)
2198 {
2199 int len = strlen(c);
2200
2201 res = WriteInt(AH, len);
2202 AH->WriteBufPtr(AH, c, len);
2203 res += len;
2204 }
2205 else
2206 res = WriteInt(AH, -1);
2207
2208 return res;
2209}
2210
2211char *
2213{
2214 char *buf;
2215 int l;
2216
2217 l = ReadInt(AH);
2218 if (l < 0)
2219 buf = NULL;
2220 else
2221 {
2222 buf = (char *) pg_malloc(l + 1);
2223 AH->ReadBufPtr(AH, buf, l);
2224
2225 buf[l] = '\0';
2226 }
2227
2228 return buf;
2229}
2230
2231static bool
2232_fileExistsInDirectory(const char *dir, const char *filename)
2233{
2234 struct stat st;
2235 char buf[MAXPGPATH];
2236
2237 if (snprintf(buf, MAXPGPATH, "%s/%s", dir, filename) >= MAXPGPATH)
2238 pg_fatal("directory name too long: \"%s\"", dir);
2239
2240 return (stat(buf, &st) == 0 && S_ISREG(st.st_mode));
2241}
2242
2243static int
2245{
2246 FILE *fh;
2247 char sig[6]; /* More than enough */
2248 size_t cnt;
2249 int wantClose = 0;
2250
2251 pg_log_debug("attempting to ascertain archive format");
2252
2253 free(AH->lookahead);
2254
2255 AH->readHeader = 0;
2256 AH->lookaheadSize = 512;
2257 AH->lookahead = pg_malloc0(512);
2258 AH->lookaheadLen = 0;
2259 AH->lookaheadPos = 0;
2260
2261 if (AH->fSpec)
2262 {
2263 struct stat st;
2264
2265 wantClose = 1;
2266
2267 /*
2268 * Check if the specified archive is a directory. If so, check if
2269 * there's a "toc.dat" (or "toc.dat.{gz,lz4,zst}") file in it.
2270 */
2271 if (stat(AH->fSpec, &st) == 0 && S_ISDIR(st.st_mode))
2272 {
2273 AH->format = archDirectory;
2274 if (_fileExistsInDirectory(AH->fSpec, "toc.dat"))
2275 return AH->format;
2276#ifdef HAVE_LIBZ
2277 if (_fileExistsInDirectory(AH->fSpec, "toc.dat.gz"))
2278 return AH->format;
2279#endif
2280#ifdef USE_LZ4
2281 if (_fileExistsInDirectory(AH->fSpec, "toc.dat.lz4"))
2282 return AH->format;
2283#endif
2284#ifdef USE_ZSTD
2285 if (_fileExistsInDirectory(AH->fSpec, "toc.dat.zst"))
2286 return AH->format;
2287#endif
2288 pg_fatal("directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)",
2289 AH->fSpec);
2290 fh = NULL; /* keep compiler quiet */
2291 }
2292 else
2293 {
2294 fh = fopen(AH->fSpec, PG_BINARY_R);
2295 if (!fh)
2296 pg_fatal("could not open input file \"%s\": %m", AH->fSpec);
2297 }
2298 }
2299 else
2300 {
2301 fh = stdin;
2302 if (!fh)
2303 pg_fatal("could not open input file: %m");
2304 }
2305
2306 if ((cnt = fread(sig, 1, 5, fh)) != 5)
2307 {
2308 if (ferror(fh))
2309 pg_fatal("could not read input file: %m");
2310 else
2311 pg_fatal("input file is too short (read %zu, expected 5)", cnt);
2312 }
2313
2314 /* Save it, just in case we need it later */
2315 memcpy(&AH->lookahead[0], sig, 5);
2316 AH->lookaheadLen = 5;
2317
2318 if (strncmp(sig, "PGDMP", 5) == 0)
2319 {
2320 /* It's custom format, stop here */
2321 AH->format = archCustom;
2322 AH->readHeader = 1;
2323 }
2324 else
2325 {
2326 /*
2327 * *Maybe* we have a tar archive format file or a text dump ... So,
2328 * read first 512 byte header...
2329 */
2330 cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh);
2331 /* read failure is checked below */
2332 AH->lookaheadLen += cnt;
2333
2337 {
2338 /*
2339 * looks like it's probably a text format dump. so suggest they
2340 * try psql
2341 */
2342 pg_fatal("input file appears to be a text format dump. Please use psql.");
2343 }
2344
2345 if (AH->lookaheadLen != 512)
2346 {
2347 if (feof(fh))
2348 pg_fatal("input file does not appear to be a valid archive (too short?)");
2349 else
2351 }
2352
2353 if (!isValidTarHeader(AH->lookahead))
2354 pg_fatal("input file does not appear to be a valid tar archive");
2355
2356 AH->format = archTar;
2357 }
2358
2359 /* Close the file if we opened it */
2360 if (wantClose)
2361 {
2362 if (fclose(fh) != 0)
2363 pg_fatal("could not close input file: %m");
2364 /* Forget lookahead, since we'll re-read header after re-opening */
2365 AH->readHeader = 0;
2366 AH->lookaheadLen = 0;
2367 }
2368
2369 return AH->format;
2370}
2371
2372
2373/*
2374 * Allocate an archive handle
2375 */
2376static ArchiveHandle *
2378 const pg_compress_specification compression_spec,
2379 bool dosync, ArchiveMode mode,
2381{
2382 ArchiveHandle *AH;
2385
2386 pg_log_debug("allocating AH for %s, format %d",
2387 FileSpec ? FileSpec : "(stdio)", fmt);
2388
2390
2391 AH->version = K_VERS_SELF;
2392
2393 /* initialize for backwards compatible string processing */
2394 AH->public.encoding = 0; /* PG_SQL_ASCII */
2395 AH->public.std_strings = false;
2396
2397 /* sql error handling */
2398 AH->public.exit_on_error = true;
2399 AH->public.n_errors = 0;
2400
2402
2403 AH->createDate = time(NULL);
2404
2405 AH->intSize = sizeof(int);
2406 AH->offSize = sizeof(pgoff_t);
2407 if (FileSpec)
2408 {
2409 AH->fSpec = pg_strdup(FileSpec);
2410
2411 /*
2412 * Not used; maybe later....
2413 *
2414 * AH->workDir = pg_strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
2415 * i--) if (AH->workDir[i-1] == '/')
2416 */
2417 }
2418 else
2419 AH->fSpec = NULL;
2420
2421 AH->currUser = NULL; /* unknown */
2422 AH->currSchema = NULL; /* ditto */
2423 AH->currTablespace = NULL; /* ditto */
2424 AH->currTableAm = NULL; /* ditto */
2425
2427
2428 AH->toc->next = AH->toc;
2429 AH->toc->prev = AH->toc;
2430
2431 AH->mode = mode;
2432 AH->compression_spec = compression_spec;
2433 AH->dosync = dosync;
2435
2436 memset(&(AH->sqlparse), 0, sizeof(AH->sqlparse));
2437
2438 /* Open stdout with no compression for AH output handle */
2441 if (!CFH->open_func(NULL, fileno(stdout), PG_BINARY_A, CFH))
2442 pg_fatal("could not open stdout for appending: %m");
2443 AH->OF = CFH;
2444
2445 /*
2446 * On Windows, we need to use binary mode to read/write non-text files,
2447 * which include all archive formats as well as compressed plain text.
2448 * Force stdin/stdout into binary mode if that is what we are using.
2449 */
2450#ifdef WIN32
2451 if ((fmt != archNull || compression_spec.algorithm != PG_COMPRESSION_NONE) &&
2452 (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))
2453 {
2454 if (mode == archModeWrite)
2455 _setmode(fileno(stdout), O_BINARY);
2456 else
2457 _setmode(fileno(stdin), O_BINARY);
2458 }
2459#endif
2460
2462
2463 if (fmt == archUnknown)
2465 else
2466 AH->format = fmt;
2467
2468 switch (AH->format)
2469 {
2470 case archCustom:
2472 break;
2473
2474 case archNull:
2476 break;
2477
2478 case archDirectory:
2480 break;
2481
2482 case archTar:
2484 break;
2485
2486 default:
2487 pg_fatal("unrecognized file format \"%d\"", AH->format);
2488 }
2489
2490 return AH;
2491}
2492
2493/*
2494 * Write out all data (tables & LOs)
2495 */
2496void
2498{
2499 TocEntry *te;
2500
2501 if (pstate && pstate->numWorkers > 1)
2502 {
2503 /*
2504 * In parallel mode, this code runs in the leader process. We
2505 * construct an array of candidate TEs, then sort it into decreasing
2506 * size order, then dispatch each TE to a data-transfer worker. By
2507 * dumping larger tables first, we avoid getting into a situation
2508 * where we're down to one job and it's big, losing parallelism.
2509 */
2510 TocEntry **tes;
2511 int ntes;
2512
2514 ntes = 0;
2515 for (te = AH->toc->next; te != AH->toc; te = te->next)
2516 {
2517 /* Consider only TEs with dataDumper functions ... */
2518 if (!te->dataDumper)
2519 continue;
2520 /* ... and ignore ones not enabled for dump */
2521 if ((te->reqs & REQ_DATA) == 0)
2522 continue;
2523
2524 tes[ntes++] = te;
2525 }
2526
2527 if (ntes > 1)
2529
2530 for (int i = 0; i < ntes; i++)
2531 DispatchJobForTocEntry(AH, pstate, tes[i], ACT_DUMP,
2533
2534 pg_free(tes);
2535
2536 /* Now wait for workers to finish. */
2537 WaitForWorkers(AH, pstate, WFW_ALL_IDLE);
2538 }
2539 else
2540 {
2541 /* Non-parallel mode: just dump all candidate TEs sequentially. */
2542 for (te = AH->toc->next; te != AH->toc; te = te->next)
2543 {
2544 /* Must have same filter conditions as above */
2545 if (!te->dataDumper)
2546 continue;
2547 if ((te->reqs & REQ_DATA) == 0)
2548 continue;
2549
2551 }
2552 }
2553}
2554
2555
2556/*
2557 * Callback function that's invoked in the leader process after a step has
2558 * been parallel dumped.
2559 *
2560 * We don't need to do anything except check for worker failure.
2561 */
2562static void
2564 TocEntry *te,
2565 int status,
2566 void *callback_data)
2567{
2568 pg_log_info("finished item %d %s %s",
2569 te->dumpId, te->desc, te->tag);
2570
2571 if (status != 0)
2572 pg_fatal("worker process failed: exit code %d",
2573 status);
2574}
2575
2576
2577void
2579{
2582
2583 AH->currToc = te;
2584
2585 if (strcmp(te->desc, "BLOBS") == 0)
2586 {
2587 startPtr = AH->StartLOsPtr;
2588 endPtr = AH->EndLOsPtr;
2589 }
2590 else
2591 {
2592 startPtr = AH->StartDataPtr;
2593 endPtr = AH->EndDataPtr;
2594 }
2595
2596 if (startPtr != NULL)
2597 (*startPtr) (AH, te);
2598
2599 /*
2600 * The user-provided DataDumper routine needs to call AH->WriteData
2601 */
2602 te->dataDumper((Archive *) AH, te->dataDumperArg);
2603
2604 if (endPtr != NULL)
2605 (*endPtr) (AH, te);
2606
2607 AH->currToc = NULL;
2608}
2609
2610void
2612{
2613 TocEntry *te;
2614 char workbuf[32];
2615 int tocCount;
2616 int i;
2617
2618 /* count entries that will actually be dumped */
2619 tocCount = 0;
2620 for (te = AH->toc->next; te != AH->toc; te = te->next)
2621 {
2622 if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS | REQ_SPECIAL)) != 0)
2623 tocCount++;
2624 }
2625
2626 /* printf("%d TOC Entries to save\n", tocCount); */
2627
2628 WriteInt(AH, tocCount);
2629
2630 for (te = AH->toc->next; te != AH->toc; te = te->next)
2631 {
2632 if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS | REQ_SPECIAL)) == 0)
2633 continue;
2634
2635 WriteInt(AH, te->dumpId);
2636 WriteInt(AH, te->dataDumper ? 1 : 0);
2637
2638 /* OID is recorded as a string for historical reasons */
2639 sprintf(workbuf, "%u", te->catalogId.tableoid);
2640 WriteStr(AH, workbuf);
2641 sprintf(workbuf, "%u", te->catalogId.oid);
2642 WriteStr(AH, workbuf);
2643
2644 WriteStr(AH, te->tag);
2645 WriteStr(AH, te->desc);
2646 WriteInt(AH, te->section);
2647
2648 if (te->defnLen)
2649 {
2650 /*
2651 * defnLen should only be set for custom format's second call to
2652 * WriteToc(), which rewrites the TOC in place to update data
2653 * offsets. Instead of calling the defnDumper a second time
2654 * (which could involve re-executing queries), just skip writing
2655 * the entry. While regenerating the definition should
2656 * theoretically produce the same result as before, it's expensive
2657 * and feels risky.
2658 *
2659 * The custom format only calls WriteToc() a second time if
2660 * fseeko() is usable (see _CloseArchive() in pg_backup_custom.c),
2661 * so we can safely use it without checking. For other formats,
2662 * we fail because one of our assumptions must no longer hold
2663 * true.
2664 *
2665 * XXX This is a layering violation, but the alternative is an
2666 * awkward and complicated callback infrastructure for this
2667 * special case. This might be worth revisiting in the future.
2668 */
2669 if (AH->format != archCustom)
2670 pg_fatal("unexpected TOC entry in WriteToc(): %d %s %s",
2671 te->dumpId, te->desc, te->tag);
2672
2673 if (fseeko(AH->FH, te->defnLen, SEEK_CUR) != 0)
2674 pg_fatal("error during file seek: %m");
2675 }
2676 else if (te->defnDumper)
2677 {
2678 char *defn = te->defnDumper((Archive *) AH, te->defnDumperArg, te);
2679
2680 te->defnLen = WriteStr(AH, defn);
2681 pg_free(defn);
2682 }
2683 else
2684 WriteStr(AH, te->defn);
2685
2686 WriteStr(AH, te->dropStmt);
2687 WriteStr(AH, te->copyStmt);
2688 WriteStr(AH, te->namespace);
2689 WriteStr(AH, te->tablespace);
2690 WriteStr(AH, te->tableam);
2691 WriteInt(AH, te->relkind);
2692 WriteStr(AH, te->owner);
2693 WriteStr(AH, "false");
2694
2695 /* Dump list of dependencies */
2696 for (i = 0; i < te->nDeps; i++)
2697 {
2698 sprintf(workbuf, "%d", te->dependencies[i]);
2699 WriteStr(AH, workbuf);
2700 }
2701 WriteStr(AH, NULL); /* Terminate List */
2702
2703 if (AH->WriteExtraTocPtr)
2704 AH->WriteExtraTocPtr(AH, te);
2705 }
2706}
2707
2708void
2710{
2711 int i;
2712 char *tmp;
2713 DumpId *deps;
2714 int depIdx;
2715 int depSize;
2716 TocEntry *te;
2717 bool is_supported;
2718
2719 AH->tocCount = ReadInt(AH);
2720 AH->maxDumpId = 0;
2721
2722 for (i = 0; i < AH->tocCount; i++)
2723 {
2725 te->dumpId = ReadInt(AH);
2726
2727 if (te->dumpId > AH->maxDumpId)
2728 AH->maxDumpId = te->dumpId;
2729
2730 /* Sanity check */
2731 if (te->dumpId <= 0)
2732 pg_fatal("entry ID %d out of range -- perhaps a corrupt TOC",
2733 te->dumpId);
2734
2735 te->hadDumper = ReadInt(AH);
2736
2737 if (AH->version >= K_VERS_1_8)
2738 {
2739 tmp = ReadStr(AH);
2740 sscanf(tmp, "%u", &te->catalogId.tableoid);
2741 free(tmp);
2742 }
2743 else
2745 tmp = ReadStr(AH);
2746 sscanf(tmp, "%u", &te->catalogId.oid);
2747 free(tmp);
2748
2749 te->tag = ReadStr(AH);
2750 te->desc = ReadStr(AH);
2751
2752 if (AH->version >= K_VERS_1_11)
2753 {
2754 te->section = ReadInt(AH);
2755 }
2756 else
2757 {
2758 /*
2759 * Rules for pre-8.4 archives wherein pg_dump hasn't classified
2760 * the entries into sections. This list need not cover entry
2761 * types added later than 8.4.
2762 */
2763 if (strcmp(te->desc, "COMMENT") == 0 ||
2764 strcmp(te->desc, "ACL") == 0 ||
2765 strcmp(te->desc, "ACL LANGUAGE") == 0)
2766 te->section = SECTION_NONE;
2767 else if (strcmp(te->desc, "TABLE DATA") == 0 ||
2768 strcmp(te->desc, "BLOBS") == 0 ||
2769 strcmp(te->desc, "BLOB COMMENTS") == 0)
2770 te->section = SECTION_DATA;
2771 else if (strcmp(te->desc, "CONSTRAINT") == 0 ||
2772 strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
2773 strcmp(te->desc, "FK CONSTRAINT") == 0 ||
2774 strcmp(te->desc, "INDEX") == 0 ||
2775 strcmp(te->desc, "RULE") == 0 ||
2776 strcmp(te->desc, "TRIGGER") == 0)
2778 else
2780 }
2781
2782 te->defn = ReadStr(AH);
2783 te->dropStmt = ReadStr(AH);
2784
2785 if (AH->version >= K_VERS_1_3)
2786 te->copyStmt = ReadStr(AH);
2787
2788 if (AH->version >= K_VERS_1_6)
2789 te->namespace = ReadStr(AH);
2790
2791 if (AH->version >= K_VERS_1_10)
2792 te->tablespace = ReadStr(AH);
2793
2794 if (AH->version >= K_VERS_1_14)
2795 te->tableam = ReadStr(AH);
2796
2797 if (AH->version >= K_VERS_1_16)
2798 te->relkind = ReadInt(AH);
2799
2800 te->owner = ReadStr(AH);
2801 is_supported = true;
2802 if (AH->version < K_VERS_1_9)
2803 is_supported = false;
2804 else
2805 {
2806 tmp = ReadStr(AH);
2807
2808 if (strcmp(tmp, "true") == 0)
2809 is_supported = false;
2810
2811 free(tmp);
2812 }
2813
2814 if (!is_supported)
2815 pg_log_warning("restoring tables WITH OIDS is not supported anymore");
2816
2817 /* Read TOC entry dependencies */
2818 if (AH->version >= K_VERS_1_5)
2819 {
2820 depSize = 100;
2822 depIdx = 0;
2823 for (;;)
2824 {
2825 tmp = ReadStr(AH);
2826 if (!tmp)
2827 break; /* end of list */
2828 if (depIdx >= depSize)
2829 {
2830 depSize *= 2;
2831 deps = pg_realloc_array(deps, DumpId, depSize);
2832 }
2833 sscanf(tmp, "%d", &deps[depIdx]);
2834 free(tmp);
2835 depIdx++;
2836 }
2837
2838 if (depIdx > 0) /* We have a non-null entry */
2839 {
2840 deps = pg_realloc_array(deps, DumpId, depIdx);
2841 te->dependencies = deps;
2842 te->nDeps = depIdx;
2843 }
2844 else
2845 {
2846 free(deps);
2847 te->dependencies = NULL;
2848 te->nDeps = 0;
2849 }
2850 }
2851 else
2852 {
2853 te->dependencies = NULL;
2854 te->nDeps = 0;
2855 }
2856 te->dataLength = 0;
2857
2858 if (AH->ReadExtraTocPtr)
2859 AH->ReadExtraTocPtr(AH, te);
2860
2861 pg_log_debug("read TOC entry %d (ID %d) for %s %s",
2862 i, te->dumpId, te->desc, te->tag);
2863
2864 /* link completed entry into TOC circular list */
2865 te->prev = AH->toc->prev;
2866 AH->toc->prev->next = te;
2867 AH->toc->prev = te;
2868 te->next = AH->toc;
2869
2870 /* special processing immediately upon read for some items */
2871 if (strcmp(te->desc, "ENCODING") == 0)
2872 processEncodingEntry(AH, te);
2873 else if (strcmp(te->desc, "STDSTRINGS") == 0)
2874 processStdStringsEntry(AH, te);
2875 else if (strcmp(te->desc, "SEARCHPATH") == 0)
2876 processSearchPathEntry(AH, te);
2877 }
2878}
2879
2880static void
2882{
2883 /* te->defn should have the form SET client_encoding = 'foo'; */
2884 char *defn = pg_strdup(te->defn);
2885 char *ptr1;
2886 char *ptr2 = NULL;
2887 int encoding;
2888
2889 ptr1 = strchr(defn, '\'');
2890 if (ptr1)
2891 ptr2 = strchr(++ptr1, '\'');
2892 if (ptr2)
2893 {
2894 *ptr2 = '\0';
2896 if (encoding < 0)
2897 pg_fatal("unrecognized encoding \"%s\"",
2898 ptr1);
2899 AH->public.encoding = encoding;
2901 }
2902 else
2903 pg_fatal("invalid ENCODING item: %s",
2904 te->defn);
2905
2906 free(defn);
2907}
2908
2909static void
2911{
2912 /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2913 char *ptr1;
2914
2915 ptr1 = strchr(te->defn, '\'');
2916 if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
2917 AH->public.std_strings = true;
2918 else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
2919 AH->public.std_strings = false;
2920 else
2921 pg_fatal("invalid STDSTRINGS item: %s",
2922 te->defn);
2923}
2924
2925static void
2927{
2928 /*
2929 * te->defn should contain a command to set search_path. We just copy it
2930 * verbatim for use later.
2931 */
2932 AH->public.searchpath = pg_strdup(te->defn);
2933}
2934
2935static void
2937{
2938 const char *missing_name;
2939
2940 Assert(ropt->strict_names);
2941
2942 if (ropt->schemaNames.head != NULL)
2943 {
2945 if (missing_name != NULL)
2946 pg_fatal("schema \"%s\" not found", missing_name);
2947 }
2948
2949 if (ropt->tableNames.head != NULL)
2950 {
2952 if (missing_name != NULL)
2953 pg_fatal("table \"%s\" not found", missing_name);
2954 }
2955
2956 if (ropt->indexNames.head != NULL)
2957 {
2959 if (missing_name != NULL)
2960 pg_fatal("index \"%s\" not found", missing_name);
2961 }
2962
2963 if (ropt->functionNames.head != NULL)
2964 {
2966 if (missing_name != NULL)
2967 pg_fatal("function \"%s\" not found", missing_name);
2968 }
2969
2970 if (ropt->triggerNames.head != NULL)
2971 {
2973 if (missing_name != NULL)
2974 pg_fatal("trigger \"%s\" not found", missing_name);
2975 }
2976}
2977
2978/*
2979 * Determine whether we want to restore this TOC entry.
2980 *
2981 * Returns 0 if entry should be skipped, or some combination of the
2982 * REQ_SCHEMA, REQ_DATA, and REQ_STATS bits if we want to restore schema, data
2983 * and/or statistics portions of this TOC entry, or REQ_SPECIAL if it's a
2984 * special entry.
2985 */
2986static int
2988{
2989 int res = REQ_SCHEMA | REQ_DATA;
2990 RestoreOptions *ropt = AH->public.ropt;
2991
2992 /*
2993 * For binary upgrade mode, dump pg_largeobject_metadata and the
2994 * associated pg_shdepend rows. This is faster to restore than the
2995 * equivalent set of large object commands.
2996 */
2997 if (ropt->binary_upgrade && strcmp(te->desc, "TABLE DATA") == 0 &&
3000 return REQ_DATA;
3001
3002 /* These items are treated specially */
3003 if (strcmp(te->desc, "ENCODING") == 0 ||
3004 strcmp(te->desc, "STDSTRINGS") == 0 ||
3005 strcmp(te->desc, "SEARCHPATH") == 0)
3006 return REQ_SPECIAL;
3007
3008 if ((strcmp(te->desc, "STATISTICS DATA") == 0) ||
3009 (strcmp(te->desc, "EXTENDED STATISTICS DATA") == 0))
3010 {
3011 if (!ropt->dumpStatistics)
3012 return 0;
3013
3014 res = REQ_STATS;
3015 }
3016
3017 /*
3018 * DATABASE and DATABASE PROPERTIES also have a special rule: they are
3019 * restored in createDB mode, and not restored otherwise, independently of
3020 * all else.
3021 */
3022 if (strcmp(te->desc, "DATABASE") == 0 ||
3023 strcmp(te->desc, "DATABASE PROPERTIES") == 0)
3024 {
3025 if (ropt->createDB)
3026 return REQ_SCHEMA;
3027 else
3028 return 0;
3029 }
3030
3031 /*
3032 * Process exclusions that affect certain classes of TOC entries.
3033 */
3034
3035 /* If it's an ACL, maybe ignore it */
3036 if (ropt->aclsSkip && _tocEntryIsACL(te))
3037 return 0;
3038
3039 /* If it's a comment, maybe ignore it */
3040 if (ropt->no_comments && strcmp(te->desc, "COMMENT") == 0)
3041 return 0;
3042
3043 /* If it's a policy, maybe ignore it */
3044 if (ropt->no_policies &&
3045 (strcmp(te->desc, "POLICY") == 0 ||
3046 strcmp(te->desc, "ROW SECURITY") == 0))
3047 return 0;
3048
3049 /*
3050 * If it's a comment on a policy, a publication, or a subscription, maybe
3051 * ignore it.
3052 */
3053 if (strcmp(te->desc, "COMMENT") == 0)
3054 {
3055 if (ropt->no_policies &&
3056 strncmp(te->tag, "POLICY", strlen("POLICY")) == 0)
3057 return 0;
3058
3059 if (ropt->no_publications &&
3060 strncmp(te->tag, "PUBLICATION", strlen("PUBLICATION")) == 0)
3061 return 0;
3062
3063 if (ropt->no_subscriptions &&
3064 strncmp(te->tag, "SUBSCRIPTION", strlen("SUBSCRIPTION")) == 0)
3065 return 0;
3066 }
3067
3068 /*
3069 * If it's a publication or a table part of a publication, maybe ignore
3070 * it.
3071 */
3072 if (ropt->no_publications &&
3073 (strcmp(te->desc, "PUBLICATION") == 0 ||
3074 strcmp(te->desc, "PUBLICATION TABLE") == 0 ||
3075 strcmp(te->desc, "PUBLICATION TABLES IN SCHEMA") == 0))
3076 return 0;
3077
3078 /* If it's a security label, maybe ignore it */
3079 if (ropt->no_security_labels && strcmp(te->desc, "SECURITY LABEL") == 0)
3080 return 0;
3081
3082 /*
3083 * If it's a security label on a publication or a subscription, maybe
3084 * ignore it.
3085 */
3086 if (strcmp(te->desc, "SECURITY LABEL") == 0)
3087 {
3088 if (ropt->no_publications &&
3089 strncmp(te->tag, "PUBLICATION", strlen("PUBLICATION")) == 0)
3090 return 0;
3091
3092 if (ropt->no_subscriptions &&
3093 strncmp(te->tag, "SUBSCRIPTION", strlen("SUBSCRIPTION")) == 0)
3094 return 0;
3095 }
3096
3097 /* If it's a subscription, maybe ignore it */
3098 if (ropt->no_subscriptions && strcmp(te->desc, "SUBSCRIPTION") == 0)
3099 return 0;
3100
3101 /* Ignore it if section is not to be dumped/restored */
3102 switch (curSection)
3103 {
3104 case SECTION_PRE_DATA:
3105 if (!(ropt->dumpSections & DUMP_PRE_DATA))
3106 return 0;
3107 break;
3108 case SECTION_DATA:
3109 if (!(ropt->dumpSections & DUMP_DATA))
3110 return 0;
3111 break;
3112 case SECTION_POST_DATA:
3113 if (!(ropt->dumpSections & DUMP_POST_DATA))
3114 return 0;
3115 break;
3116 default:
3117 /* shouldn't get here, really, but ignore it */
3118 return 0;
3119 }
3120
3121 /* Ignore it if rejected by idWanted[] (cf. SortTocFromFile) */
3122 if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1])
3123 return 0;
3124
3125 /*
3126 * Check options for selective dump/restore.
3127 */
3128 if (strcmp(te->desc, "ACL") == 0 ||
3129 strcmp(te->desc, "COMMENT") == 0 ||
3130 strcmp(te->desc, "SECURITY LABEL") == 0)
3131 {
3132 /* Database properties react to createDB, not selectivity options. */
3133 if (strncmp(te->tag, "DATABASE ", 9) == 0)
3134 {
3135 if (!ropt->createDB)
3136 return 0;
3137 }
3138 else if (ropt->schemaNames.head != NULL ||
3139 ropt->schemaExcludeNames.head != NULL ||
3140 ropt->selTypes)
3141 {
3142 /*
3143 * In a selective dump/restore, we want to restore these dependent
3144 * TOC entry types only if their parent object is being restored.
3145 * Without selectivity options, we let through everything in the
3146 * archive. Note there may be such entries with no parent, eg
3147 * non-default ACLs for built-in objects. Also, we make
3148 * per-column ACLs additionally depend on the table's ACL if any
3149 * to ensure correct restore order, so those dependencies should
3150 * be ignored in this check.
3151 *
3152 * This code depends on the parent having been marked already,
3153 * which should be the case; if it isn't, perhaps due to
3154 * SortTocFromFile rearrangement, skipping the dependent entry
3155 * seems prudent anyway.
3156 *
3157 * Ideally we'd handle, eg, table CHECK constraints this way too.
3158 * But it's hard to tell which of their dependencies is the one to
3159 * consult.
3160 */
3161 bool dumpthis = false;
3162
3163 for (int i = 0; i < te->nDeps; i++)
3164 {
3166
3167 if (!pte)
3168 continue; /* probably shouldn't happen */
3169 if (strcmp(pte->desc, "ACL") == 0)
3170 continue; /* ignore dependency on another ACL */
3171 if (pte->reqs == 0)
3172 continue; /* this object isn't marked, so ignore it */
3173 /* Found a parent to be dumped, so we want to dump this too */
3174 dumpthis = true;
3175 break;
3176 }
3177 if (!dumpthis)
3178 return 0;
3179 }
3180 }
3181 else
3182 {
3183 /* Apply selective-restore rules for standalone TOC entries. */
3184 if (ropt->schemaNames.head != NULL)
3185 {
3186 /* If no namespace is specified, it means all. */
3187 if (!te->namespace)
3188 return 0;
3189 if (!simple_string_list_member(&ropt->schemaNames, te->namespace))
3190 return 0;
3191 }
3192
3193 if (ropt->schemaExcludeNames.head != NULL &&
3194 te->namespace &&
3195 simple_string_list_member(&ropt->schemaExcludeNames, te->namespace))
3196 return 0;
3197
3198 if (ropt->selTypes)
3199 {
3200 if (strcmp(te->desc, "STATISTICS DATA") == 0)
3201 {
3202 bool dumpthis = false;
3203
3204 /*
3205 * Statistics data entries can be for tables or indexes. Check
3206 * the parent dependency to determine which type this entry
3207 * belongs to, then apply the appropriate name filter.
3208 */
3209 for (int i = 0; i < te->nDeps; i++)
3210 {
3212
3213 if (!pte)
3214 continue;
3215
3216 if (ropt->selTable &&
3217 (strcmp(pte->desc, "TABLE") == 0 ||
3218 strcmp(pte->desc, "VIEW") == 0 ||
3219 strcmp(pte->desc, "FOREIGN TABLE") == 0 ||
3220 strcmp(pte->desc, "MATERIALIZED VIEW") == 0))
3221 {
3222 if (ropt->tableNames.head == NULL ||
3224 dumpthis = true;
3225 }
3226
3227 if (ropt->selIndex &&
3228 strcmp(pte->desc, "INDEX") == 0)
3229 {
3230 if (ropt->indexNames.head == NULL ||
3232 dumpthis = true;
3233 }
3234 }
3235 if (!dumpthis)
3236 return 0;
3237 }
3238 else if (strcmp(te->desc, "TABLE") == 0 ||
3239 strcmp(te->desc, "TABLE DATA") == 0 ||
3240 strcmp(te->desc, "VIEW") == 0 ||
3241 strcmp(te->desc, "FOREIGN TABLE") == 0 ||
3242 strcmp(te->desc, "MATERIALIZED VIEW") == 0 ||
3243 strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0 ||
3244 strcmp(te->desc, "SEQUENCE") == 0 ||
3245 strcmp(te->desc, "SEQUENCE SET") == 0)
3246 {
3247 if (!ropt->selTable)
3248 return 0;
3249 if (ropt->tableNames.head != NULL &&
3251 return 0;
3252 }
3253 else if (strcmp(te->desc, "INDEX") == 0)
3254 {
3255 if (!ropt->selIndex)
3256 return 0;
3257 if (ropt->indexNames.head != NULL &&
3259 return 0;
3260 }
3261 else if (strcmp(te->desc, "FUNCTION") == 0 ||
3262 strcmp(te->desc, "AGGREGATE") == 0 ||
3263 strcmp(te->desc, "PROCEDURE") == 0)
3264 {
3265 if (!ropt->selFunction)
3266 return 0;
3267 if (ropt->functionNames.head != NULL &&
3269 return 0;
3270 }
3271 else if (strcmp(te->desc, "TRIGGER") == 0)
3272 {
3273 if (!ropt->selTrigger)
3274 return 0;
3275 if (ropt->triggerNames.head != NULL &&
3277 return 0;
3278 }
3279 else
3280 return 0;
3281 }
3282 }
3283
3284
3285 /*
3286 * Determine whether the TOC entry contains schema and/or data components,
3287 * and mask off inapplicable REQ bits. If it had a dataDumper, assume
3288 * it's both schema and data. Otherwise it's probably schema-only, but
3289 * there are exceptions.
3290 */
3291 if (!te->hadDumper)
3292 {
3293 /*
3294 * Special Case: If 'SEQUENCE SET' or anything to do with LOs, then it
3295 * is considered a data entry. We don't need to check for BLOBS or
3296 * old-style BLOB COMMENTS entries, because they will have hadDumper =
3297 * true ... but we do need to check new-style BLOB ACLs, comments,
3298 * etc.
3299 */
3300 if (strcmp(te->desc, "SEQUENCE SET") == 0 ||
3301 strcmp(te->desc, "BLOB") == 0 ||
3302 strcmp(te->desc, "BLOB METADATA") == 0 ||
3303 (strcmp(te->desc, "ACL") == 0 &&
3304 strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
3305 (strcmp(te->desc, "COMMENT") == 0 &&
3306 strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
3307 (strcmp(te->desc, "SECURITY LABEL") == 0 &&
3308 strncmp(te->tag, "LARGE OBJECT", 12) == 0))
3309 res = res & REQ_DATA;
3310 else
3311 res = res & ~REQ_DATA;
3312 }
3313
3314 /*
3315 * If there's no definition command, there's no schema component. Treat
3316 * "load via partition root" comments as not schema.
3317 */
3318 if (!te->defn || !te->defn[0] ||
3319 strncmp(te->defn, "-- load via partition root ", 27) == 0)
3320 res = res & ~REQ_SCHEMA;
3321
3322 /*
3323 * Special case: <Init> type with <Max OID> tag; this is obsolete and we
3324 * always ignore it.
3325 */
3326 if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))
3327 return 0;
3328
3329 /* Mask it if we don't want data */
3330 if (!ropt->dumpData)
3331 {
3332 /*
3333 * The sequence_data option overrides dumpData for SEQUENCE SET.
3334 *
3335 * In binary-upgrade mode, even with dumpData unset, we do not mask
3336 * out large objects. (Only large object definitions, comments and
3337 * other metadata should be generated in binary-upgrade mode, not the
3338 * actual data, but that need not concern us here.)
3339 */
3340 if (!(ropt->sequence_data && strcmp(te->desc, "SEQUENCE SET") == 0) &&
3341 !(ropt->binary_upgrade &&
3342 (strcmp(te->desc, "BLOB") == 0 ||
3343 strcmp(te->desc, "BLOB METADATA") == 0 ||
3344 (strcmp(te->desc, "ACL") == 0 &&
3345 strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
3346 (strcmp(te->desc, "COMMENT") == 0 &&
3347 strncmp(te->tag, "LARGE OBJECT", 12) == 0) ||
3348 (strcmp(te->desc, "SECURITY LABEL") == 0 &&
3349 strncmp(te->tag, "LARGE OBJECT", 12) == 0))))
3350 res = res & (REQ_SCHEMA | REQ_STATS);
3351 }
3352
3353 /* Mask it if we don't want schema */
3354 if (!ropt->dumpSchema)
3355 res = res & (REQ_DATA | REQ_STATS);
3356
3357 return res;
3358}
3359
3360/*
3361 * Identify which pass we should restore this TOC entry in.
3362 *
3363 * See notes with the RestorePass typedef in pg_backup_archiver.h.
3364 */
3365static RestorePass
3367{
3368 /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3369 if (strcmp(te->desc, "ACL") == 0 ||
3370 strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3371 strcmp(te->desc, "DEFAULT ACL") == 0)
3372 return RESTORE_PASS_ACL;
3373 if (strcmp(te->desc, "EVENT TRIGGER") == 0 ||
3374 strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0)
3375 return RESTORE_PASS_POST_ACL;
3376
3377 /*
3378 * Comments and security labels need to be emitted in the same pass as
3379 * their parent objects. ACLs haven't got comments and security labels,
3380 * and neither do matview data objects, but event triggers do.
3381 * (Fortunately, event triggers haven't got ACLs, or we'd need yet another
3382 * weird special case.)
3383 */
3384 if ((strcmp(te->desc, "COMMENT") == 0 ||
3385 strcmp(te->desc, "SECURITY LABEL") == 0) &&
3386 strncmp(te->tag, "EVENT TRIGGER ", 14) == 0)
3387 return RESTORE_PASS_POST_ACL;
3388
3389 /*
3390 * If statistics data is dependent on materialized view data, it must be
3391 * deferred to RESTORE_PASS_POST_ACL. Those entries are already marked as
3392 * SECTION_POST_DATA, and some other stats entries (e.g., index stats)
3393 * will also be marked as SECTION_POST_DATA. Additionally, our lookahead
3394 * code in fetchAttributeStats() assumes that we dump all statistics data
3395 * entries in TOC order. To ensure this assumption holds, we move all
3396 * statistics data entries in SECTION_POST_DATA to RESTORE_PASS_POST_ACL.
3397 */
3398 if (strcmp(te->desc, "STATISTICS DATA") == 0 &&
3400 return RESTORE_PASS_POST_ACL;
3401
3402 /* All else can be handled in the main pass. */
3403 return RESTORE_PASS_MAIN;
3404}
3405
3406/*
3407 * Identify TOC entries that are ACLs.
3408 *
3409 * Note: it seems worth duplicating some code here to avoid a hard-wired
3410 * assumption that these are exactly the same entries that we restore during
3411 * the RESTORE_PASS_ACL phase.
3412 */
3413static bool
3415{
3416 /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
3417 if (strcmp(te->desc, "ACL") == 0 ||
3418 strcmp(te->desc, "ACL LANGUAGE") == 0 ||
3419 strcmp(te->desc, "DEFAULT ACL") == 0)
3420 return true;
3421 return false;
3422}
3423
3424/*
3425 * Issue SET commands for parameters that we want to have set the same way
3426 * at all times during execution of a restore script.
3427 */
3428static void
3430{
3431 RestoreOptions *ropt = AH->public.ropt;
3432
3433 /*
3434 * Disable timeouts to allow for slow commands, idle parallel workers, etc
3435 */
3436 ahprintf(AH, "SET statement_timeout = 0;\n");
3437 ahprintf(AH, "SET lock_timeout = 0;\n");
3438 ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n");
3439 ahprintf(AH, "SET transaction_timeout = 0;\n");
3440
3441 /* Select the correct character set encoding */
3442 ahprintf(AH, "SET client_encoding = '%s';\n",
3444
3445 /* Select the correct string literal syntax */
3446 ahprintf(AH, "SET standard_conforming_strings = %s;\n",
3447 AH->public.std_strings ? "on" : "off");
3448
3449 /* Select the role to be used during restore */
3450 if (ropt && ropt->use_role)
3451 ahprintf(AH, "SET ROLE %s;\n", fmtId(ropt->use_role));
3452
3453 /* Select the dump-time search_path */
3454 if (AH->public.searchpath)
3455 ahprintf(AH, "%s", AH->public.searchpath);
3456
3457 /* Make sure function checking is disabled */
3458 ahprintf(AH, "SET check_function_bodies = false;\n");
3459
3460 /* Ensure that all valid XML data will be accepted */
3461 ahprintf(AH, "SET xmloption = content;\n");
3462
3463 /* Avoid annoying notices etc */
3464 ahprintf(AH, "SET client_min_messages = warning;\n");
3465
3466 /* Adjust row-security state */
3467 if (ropt && ropt->enable_row_security)
3468 ahprintf(AH, "SET row_security = on;\n");
3469 else
3470 ahprintf(AH, "SET row_security = off;\n");
3471
3472 /*
3473 * In --transaction-size mode, we should always be in a transaction when
3474 * we begin to restore objects.
3475 */
3476 if (ropt && ropt->txn_size > 0)
3477 {
3478 if (AH->connection)
3480 else
3481 ahprintf(AH, "\nBEGIN;\n");
3482 AH->txnCount = 0;
3483 }
3484
3485 ahprintf(AH, "\n");
3486}
3487
3488/*
3489 * Issue a SET SESSION AUTHORIZATION command. Caller is responsible
3490 * for updating state if appropriate. If user is NULL or an empty string,
3491 * the specification DEFAULT will be used.
3492 */
3493static void
3495{
3497
3498 appendPQExpBufferStr(cmd, "SET SESSION AUTHORIZATION ");
3499
3500 /*
3501 * SQL requires a string literal here. Might as well be correct.
3502 */
3503 if (user && *user)
3504 appendStringLiteralAHX(cmd, user, AH);
3505 else
3506 appendPQExpBufferStr(cmd, "DEFAULT");
3507 appendPQExpBufferChar(cmd, ';');
3508
3509 if (RestoringToDB(AH))
3510 {
3511 PGresult *res;
3512
3513 res = PQexec(AH->connection, cmd->data);
3514
3515 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3516 /* NOT warn_or_exit_horribly... use -O instead to skip this. */
3517 pg_fatal("could not set session user to \"%s\": %s",
3519
3520 PQclear(res);
3521 }
3522 else
3523 ahprintf(AH, "%s\n\n", cmd->data);
3524
3525 destroyPQExpBuffer(cmd);
3526}
3527
3528
3529/*
3530 * Issue the commands to connect to the specified database.
3531 *
3532 * If we're currently restoring right into a database, this will
3533 * actually establish a connection. Otherwise it puts a \connect into
3534 * the script output.
3535 */
3536static void
3538{
3539 if (RestoringToDB(AH))
3541 else
3542 {
3544 RestoreOptions *ropt = AH->public.ropt;
3545
3546 /*
3547 * We must temporarily exit restricted mode for \connect, etc.
3548 * Anything added between this line and the following \restrict must
3549 * be careful to avoid any possible meta-command injection vectors.
3550 */
3551 ahprintf(AH, "\\unrestrict %s\n", ropt->restrict_key);
3552
3555 ahprintf(AH, "%s", connectbuf.data);
3557
3558 ahprintf(AH, "\\restrict %s\n\n", ropt->restrict_key);
3559 }
3560
3561 /*
3562 * NOTE: currUser keeps track of what the imaginary session user in our
3563 * script is. It's now effectively reset to the original userID.
3564 */
3565 free(AH->currUser);
3566 AH->currUser = NULL;
3567
3568 /* don't assume we still know the output schema, tablespace, etc either */
3569 free(AH->currSchema);
3570 AH->currSchema = NULL;
3571
3572 free(AH->currTableAm);
3573 AH->currTableAm = NULL;
3574
3575 free(AH->currTablespace);
3576 AH->currTablespace = NULL;
3577
3578 /* re-establish fixed state */
3580}
3581
3582/*
3583 * Become the specified user, and update state to avoid redundant commands
3584 *
3585 * NULL or empty argument is taken to mean restoring the session default
3586 */
3587static void
3589{
3590 if (!user)
3591 user = ""; /* avoid null pointers */
3592
3593 if (AH->currUser && strcmp(AH->currUser, user) == 0)
3594 return; /* no need to do anything */
3595
3597
3598 /*
3599 * NOTE: currUser keeps track of what the imaginary session user in our
3600 * script is
3601 */
3602 free(AH->currUser);
3603 AH->currUser = pg_strdup(user);
3604}
3605
3606/*
3607 * Become the owner of the given TOC entry object. If
3608 * changes in ownership are not allowed, this doesn't do anything.
3609 */
3610static void
3612{
3613 RestoreOptions *ropt = AH->public.ropt;
3614
3615 if (ropt && (ropt->noOwner || !ropt->use_setsessauth))
3616 return;
3617
3618 _becomeUser(AH, te->owner);
3619}
3620
3621
3622/*
3623 * Issue the commands to select the specified schema as the current schema
3624 * in the target database.
3625 */
3626static void
3628{
3629 PQExpBuffer qry;
3630
3631 /*
3632 * If there was a SEARCHPATH TOC entry, we're supposed to just stay with
3633 * that search_path rather than switching to entry-specific paths.
3634 * Otherwise, it's an old archive that will not restore correctly unless
3635 * we set the search_path as it's expecting.
3636 */
3637 if (AH->public.searchpath)
3638 return;
3639
3640 if (!schemaName || *schemaName == '\0' ||
3641 (AH->currSchema && strcmp(AH->currSchema, schemaName) == 0))
3642 return; /* no need to do anything */
3643
3644 qry = createPQExpBuffer();
3645
3646 appendPQExpBuffer(qry, "SET search_path = %s",
3647 fmtId(schemaName));
3648 if (strcmp(schemaName, "pg_catalog") != 0)
3649 appendPQExpBufferStr(qry, ", pg_catalog");
3650
3651 if (RestoringToDB(AH))
3652 {
3653 PGresult *res;
3654
3655 res = PQexec(AH->connection, qry->data);
3656
3657 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3659 "could not set \"search_path\" to \"%s\": %s",
3661
3662 PQclear(res);
3663 }
3664 else
3665 ahprintf(AH, "%s;\n\n", qry->data);
3666
3667 free(AH->currSchema);
3669
3670 destroyPQExpBuffer(qry);
3671}
3672
3673/*
3674 * Issue the commands to select the specified tablespace as the current one
3675 * in the target database.
3676 */
3677static void
3679{
3680 RestoreOptions *ropt = AH->public.ropt;
3681 PQExpBuffer qry;
3682 const char *want,
3683 *have;
3684
3685 /* do nothing in --no-tablespaces mode */
3686 if (ropt->noTablespace)
3687 return;
3688
3689 have = AH->currTablespace;
3690 want = tablespace;
3691
3692 /* no need to do anything for non-tablespace object */
3693 if (!want)
3694 return;
3695
3696 if (have && strcmp(want, have) == 0)
3697 return; /* no need to do anything */
3698
3699 qry = createPQExpBuffer();
3700
3701 if (strcmp(want, "") == 0)
3702 {
3703 /* We want the tablespace to be the database's default */
3704 appendPQExpBufferStr(qry, "SET default_tablespace = ''");
3705 }
3706 else
3707 {
3708 /* We want an explicit tablespace */
3709 appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want));
3710 }
3711
3712 if (RestoringToDB(AH))
3713 {
3714 PGresult *res;
3715
3716 res = PQexec(AH->connection, qry->data);
3717
3718 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3720 "could not set \"default_tablespace\" to %s: %s",
3722
3723 PQclear(res);
3724 }
3725 else
3726 ahprintf(AH, "%s;\n\n", qry->data);
3727
3728 free(AH->currTablespace);
3730
3731 destroyPQExpBuffer(qry);
3732}
3733
3734/*
3735 * Set the proper default_table_access_method value for the table.
3736 */
3737static void
3739{
3740 RestoreOptions *ropt = AH->public.ropt;
3741 PQExpBuffer cmd;
3742 const char *want,
3743 *have;
3744
3745 /* do nothing in --no-table-access-method mode */
3746 if (ropt->noTableAm)
3747 return;
3748
3749 have = AH->currTableAm;
3750 want = tableam;
3751
3752 if (!want)
3753 return;
3754
3755 if (have && strcmp(want, have) == 0)
3756 return;
3757
3758 cmd = createPQExpBuffer();
3759 appendPQExpBuffer(cmd, "SET default_table_access_method = %s;", fmtId(want));
3760
3761 if (RestoringToDB(AH))
3762 {
3763 PGresult *res;
3764
3765 res = PQexec(AH->connection, cmd->data);
3766
3767 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3769 "could not set \"default_table_access_method\": %s",
3771
3772 PQclear(res);
3773 }
3774 else
3775 ahprintf(AH, "%s\n\n", cmd->data);
3776
3777 destroyPQExpBuffer(cmd);
3778
3779 free(AH->currTableAm);
3780 AH->currTableAm = pg_strdup(want);
3781}
3782
3783/*
3784 * Set the proper default table access method for a table without storage.
3785 * Currently, this is required only for partitioned tables with a table AM.
3786 */
3787static void
3789{
3790 RestoreOptions *ropt = AH->public.ropt;
3791 const char *tableam = te->tableam;
3792 PQExpBuffer cmd;
3793
3794 /* do nothing in --no-table-access-method mode */
3795 if (ropt->noTableAm)
3796 return;
3797
3798 if (!tableam)
3799 return;
3800
3802
3803 cmd = createPQExpBuffer();
3804
3805 appendPQExpBufferStr(cmd, "ALTER TABLE ");
3806 appendPQExpBuffer(cmd, "%s ", fmtQualifiedId(te->namespace, te->tag));
3807 appendPQExpBuffer(cmd, "SET ACCESS METHOD %s;",
3808 fmtId(tableam));
3809
3810 if (RestoringToDB(AH))
3811 {
3812 PGresult *res;
3813
3814 res = PQexec(AH->connection, cmd->data);
3815
3816 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3818 "could not alter table access method: %s",
3820 PQclear(res);
3821 }
3822 else
3823 ahprintf(AH, "%s\n\n", cmd->data);
3824
3825 destroyPQExpBuffer(cmd);
3826}
3827
3828/*
3829 * Extract an object description for a TOC entry, and append it to buf.
3830 *
3831 * This is used for ALTER ... OWNER TO.
3832 *
3833 * If the object type has no owner, do nothing.
3834 */
3835static void
3837{
3838 const char *type = te->desc;
3839
3840 /* objects that don't require special decoration */
3841 if (strcmp(type, "COLLATION") == 0 ||
3842 strcmp(type, "CONVERSION") == 0 ||
3843 strcmp(type, "DOMAIN") == 0 ||
3844 strcmp(type, "FOREIGN TABLE") == 0 ||
3845 strcmp(type, "MATERIALIZED VIEW") == 0 ||
3846 strcmp(type, "PROPERTY GRAPH") == 0 ||
3847 strcmp(type, "SEQUENCE") == 0 ||
3848 strcmp(type, "STATISTICS") == 0 ||
3849 strcmp(type, "TABLE") == 0 ||
3850 strcmp(type, "TEXT SEARCH DICTIONARY") == 0 ||
3851 strcmp(type, "TEXT SEARCH CONFIGURATION") == 0 ||
3852 strcmp(type, "TYPE") == 0 ||
3853 strcmp(type, "VIEW") == 0 ||
3854 /* non-schema-specified objects */
3855 strcmp(type, "DATABASE") == 0 ||
3856 strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
3857 strcmp(type, "SCHEMA") == 0 ||
3858 strcmp(type, "EVENT TRIGGER") == 0 ||
3859 strcmp(type, "FOREIGN DATA WRAPPER") == 0 ||
3860 strcmp(type, "SERVER") == 0 ||
3861 strcmp(type, "PUBLICATION") == 0 ||
3862 strcmp(type, "SUBSCRIPTION") == 0)
3863 {
3864 appendPQExpBuffer(buf, "%s ", type);
3865 if (te->namespace && *te->namespace)
3866 appendPQExpBuffer(buf, "%s.", fmtId(te->namespace));
3868 }
3869 /* LOs just have a name, but it's numeric so must not use fmtId */
3870 else if (strcmp(type, "BLOB") == 0)
3871 {
3872 appendPQExpBuffer(buf, "LARGE OBJECT %s", te->tag);
3873 }
3874
3875 /*
3876 * These object types require additional decoration. Fortunately, the
3877 * information needed is exactly what's in the DROP command.
3878 */
3879 else if (strcmp(type, "AGGREGATE") == 0 ||
3880 strcmp(type, "FUNCTION") == 0 ||
3881 strcmp(type, "OPERATOR") == 0 ||
3882 strcmp(type, "OPERATOR CLASS") == 0 ||
3883 strcmp(type, "OPERATOR FAMILY") == 0 ||
3884 strcmp(type, "PROCEDURE") == 0)
3885 {
3886 /* Chop "DROP " off the front and make a modifiable copy */
3887 char *first = pg_strdup(te->dropStmt + 5);
3888 char *last;
3889
3890 /* point to last character in string */
3891 last = first + strlen(first) - 1;
3892
3893 /* Strip off any ';' or '\n' at the end */
3894 while (last >= first && (*last == '\n' || *last == ';'))
3895 last--;
3896 *(last + 1) = '\0';
3897
3898 appendPQExpBufferStr(buf, first);
3899
3900 free(first);
3901 return;
3902 }
3903 /* these object types don't have separate owners */
3904 else if (strcmp(type, "CAST") == 0 ||
3905 strcmp(type, "CHECK CONSTRAINT") == 0 ||
3906 strcmp(type, "CONSTRAINT") == 0 ||
3907 strcmp(type, "DATABASE PROPERTIES") == 0 ||
3908 strcmp(type, "DEFAULT") == 0 ||
3909 strcmp(type, "FK CONSTRAINT") == 0 ||
3910 strcmp(type, "INDEX") == 0 ||
3911 strcmp(type, "RULE") == 0 ||
3912 strcmp(type, "TRIGGER") == 0 ||
3913 strcmp(type, "ROW SECURITY") == 0 ||
3914 strcmp(type, "POLICY") == 0 ||
3915 strcmp(type, "USER MAPPING") == 0)
3916 {
3917 /* do nothing */
3918 }
3919 else
3920 pg_fatal("don't know how to set owner for object type \"%s\"", type);
3921}
3922
3923/*
3924 * Emit the SQL commands to create the object represented by a TOC entry
3925 *
3926 * This now also includes issuing an ALTER OWNER command to restore the
3927 * object's ownership, if wanted. But note that the object's permissions
3928 * will remain at default, until the matching ACL TOC entry is restored.
3929 */
3930static void
3932{
3933 RestoreOptions *ropt = AH->public.ropt;
3934
3935 /*
3936 * Select owner, schema, tablespace and default AM as necessary. The
3937 * default access method for partitioned tables is handled after
3938 * generating the object definition, as it requires an ALTER command
3939 * rather than SET.
3940 */
3941 _becomeOwner(AH, te);
3942 _selectOutputSchema(AH, te->namespace);
3946
3947 /* Emit header comment for item */
3948 if (!AH->noTocComments)
3949 {
3950 char *sanitized_name;
3951 char *sanitized_schema;
3952 char *sanitized_owner;
3953
3954 ahprintf(AH, "--\n");
3955 if (AH->public.verbose)
3956 {
3957 ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
3958 te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
3959 if (te->nDeps > 0)
3960 {
3961 int i;
3962
3963 ahprintf(AH, "-- Dependencies:");
3964 for (i = 0; i < te->nDeps; i++)
3965 ahprintf(AH, " %d", te->dependencies[i]);
3966 ahprintf(AH, "\n");
3967 }
3968 }
3969
3970 sanitized_name = sanitize_line(te->tag, false);
3971 sanitized_schema = sanitize_line(te->namespace, true);
3972 sanitized_owner = sanitize_line(ropt->noOwner ? NULL : te->owner, true);
3973
3974 ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
3977
3981
3982 if (te->tablespace && strlen(te->tablespace) > 0 && !ropt->noTablespace)
3983 {
3985
3987 ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
3989 }
3990 ahprintf(AH, "\n");
3991
3992 if (AH->PrintExtraTocPtr != NULL)
3993 AH->PrintExtraTocPtr(AH, te);
3994 ahprintf(AH, "--\n\n");
3995 }
3996
3997 /*
3998 * Actually print the definition. Normally we can just print the defn
3999 * string if any, but we have four special cases:
4000 *
4001 * 1. A crude hack for suppressing AUTHORIZATION clause that old pg_dump
4002 * versions put into CREATE SCHEMA. Don't mutate the variant for schema
4003 * "public" that is a comment. We have to do this when --no-owner mode is
4004 * selected. This is ugly, but I see no other good way ...
4005 *
4006 * 2. BLOB METADATA entries need special processing since their defn
4007 * strings are just lists of OIDs, not complete SQL commands.
4008 *
4009 * 3. ACL LARGE OBJECTS entries need special processing because they
4010 * contain only one copy of the ACL GRANT/REVOKE commands, which we must
4011 * apply to each large object listed in the associated BLOB METADATA.
4012 *
4013 * 4. Entries with a defnDumper need to call it to generate the
4014 * definition. This is primarily intended to provide a way to save memory
4015 * for objects that would otherwise need a lot of it (e.g., statistics
4016 * data).
4017 */
4018 if (ropt->noOwner &&
4019 strcmp(te->desc, "SCHEMA") == 0 && strncmp(te->defn, "--", 2) != 0)
4020 {
4021 ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
4022 }
4023 else if (strcmp(te->desc, "BLOB METADATA") == 0)
4024 {
4025 IssueCommandPerBlob(AH, te, "SELECT pg_catalog.lo_create('", "')");
4026 }
4027 else if (strcmp(te->desc, "ACL") == 0 &&
4028 strncmp(te->tag, "LARGE OBJECTS", 13) == 0)
4029 {
4030 IssueACLPerBlob(AH, te);
4031 }
4032 else if (te->defnLen && AH->format != archTar)
4033 {
4034 /*
4035 * If defnLen is set, the defnDumper has already been called for this
4036 * TOC entry. We don't normally expect a defnDumper to be called for
4037 * a TOC entry a second time in _printTocEntry(), but there's an
4038 * exception. The tar format first calls WriteToc(), which scans the
4039 * entire TOC, and then it later calls RestoreArchive() to generate
4040 * restore.sql, which scans the TOC again. There doesn't appear to be
4041 * a good way to prevent a second defnDumper call in this case without
4042 * storing the definition in memory, which defeats the purpose. This
4043 * second defnDumper invocation should generate the same output as the
4044 * first, but even if it doesn't, the worst-case scenario is that
4045 * restore.sql might have different statistics data than the archive.
4046 *
4047 * In all other cases, encountering a TOC entry a second time in
4048 * _printTocEntry() is unexpected, so we fail because one of our
4049 * assumptions must no longer hold true.
4050 *
4051 * XXX This is a layering violation, but the alternative is an awkward
4052 * and complicated callback infrastructure for this special case. This
4053 * might be worth revisiting in the future.
4054 */
4055 pg_fatal("unexpected TOC entry in _printTocEntry(): %d %s %s",
4056 te->dumpId, te->desc, te->tag);
4057 }
4058 else if (te->defnDumper)
4059 {
4060 char *defn = te->defnDumper((Archive *) AH, te->defnDumperArg, te);
4061
4062 te->defnLen = ahprintf(AH, "%s\n\n", defn);
4063 pg_free(defn);
4064 }
4065 else if (te->defn && strlen(te->defn) > 0)
4066 {
4067 ahprintf(AH, "%s\n\n", te->defn);
4068
4069 /*
4070 * If the defn string contains multiple SQL commands, txn_size mode
4071 * should count it as N actions not one. But rather than build a full
4072 * SQL parser, approximate this by counting semicolons. One case
4073 * where that tends to be badly fooled is function definitions, so
4074 * ignore them. (restore_toc_entry will count one action anyway.)
4075 */
4076 if (ropt->txn_size > 0 &&
4077 strcmp(te->desc, "FUNCTION") != 0 &&
4078 strcmp(te->desc, "PROCEDURE") != 0)
4079 {
4080 const char *p = te->defn;
4081 int nsemis = 0;
4082
4083 while ((p = strchr(p, ';')) != NULL)
4084 {
4085 nsemis++;
4086 p++;
4087 }
4088 if (nsemis > 1)
4089 AH->txnCount += nsemis - 1;
4090 }
4091 }
4092
4093 /*
4094 * If we aren't using SET SESSION AUTH to determine ownership, we must
4095 * instead issue an ALTER OWNER command. Schema "public" is special; when
4096 * a dump emits a comment in lieu of creating it, we use ALTER OWNER even
4097 * when using SET SESSION for all other objects. We assume that anything
4098 * without a DROP command is not a separately ownable object.
4099 */
4100 if (!ropt->noOwner &&
4101 (!ropt->use_setsessauth ||
4102 (strcmp(te->desc, "SCHEMA") == 0 &&
4103 strncmp(te->defn, "--", 2) == 0)) &&
4104 te->owner && strlen(te->owner) > 0 &&
4105 te->dropStmt && strlen(te->dropStmt) > 0)
4106 {
4107 if (strcmp(te->desc, "BLOB METADATA") == 0)
4108 {
4109 /* BLOB METADATA needs special code to handle multiple LOs */
4110 char *cmdEnd = psprintf(" OWNER TO %s", fmtId(te->owner));
4111
4112 IssueCommandPerBlob(AH, te, "ALTER LARGE OBJECT ", cmdEnd);
4113 pg_free(cmdEnd);
4114 }
4115 else
4116 {
4117 /* For all other cases, we can use _getObjectDescription */
4119
4122
4123 /*
4124 * If _getObjectDescription() didn't fill the buffer, then there
4125 * is no owner.
4126 */
4127 if (temp.data[0])
4128 ahprintf(AH, "ALTER %s OWNER TO %s;\n\n",
4129 temp.data, fmtId(te->owner));
4131 }
4132 }
4133
4134 /*
4135 * Select a partitioned table's default AM, once the table definition has
4136 * been generated.
4137 */
4140
4141 /*
4142 * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
4143 * commands, so we can no longer assume we know the current auth setting.
4144 */
4145 if (_tocEntryIsACL(te))
4146 {
4147 free(AH->currUser);
4148 AH->currUser = NULL;
4149 }
4150}
4151
4152/*
4153 * Write the file header for a custom-format archive
4154 */
4155void
4157{
4158 struct tm crtm;
4159
4160 AH->WriteBufPtr(AH, "PGDMP", 5); /* Magic code */
4161 AH->WriteBytePtr(AH, ARCHIVE_MAJOR(AH->version));
4162 AH->WriteBytePtr(AH, ARCHIVE_MINOR(AH->version));
4163 AH->WriteBytePtr(AH, ARCHIVE_REV(AH->version));
4164 AH->WriteBytePtr(AH, AH->intSize);
4165 AH->WriteBytePtr(AH, AH->offSize);
4166 AH->WriteBytePtr(AH, AH->format);
4168 crtm = *localtime(&AH->createDate);
4169 WriteInt(AH, crtm.tm_sec);
4170 WriteInt(AH, crtm.tm_min);
4171 WriteInt(AH, crtm.tm_hour);
4172 WriteInt(AH, crtm.tm_mday);
4173 WriteInt(AH, crtm.tm_mon);
4174 WriteInt(AH, crtm.tm_year);
4175 WriteInt(AH, crtm.tm_isdst);
4176 WriteStr(AH, PQdb(AH->connection));
4178 WriteStr(AH, PG_VERSION);
4179}
4180
4181void
4183{
4184 char *errmsg;
4185 char vmaj,
4186 vmin,
4187 vrev;
4188 int fmt;
4189
4190 /*
4191 * If we haven't already read the header, do so.
4192 *
4193 * NB: this code must agree with _discoverArchiveFormat(). Maybe find a
4194 * way to unify the cases?
4195 */
4196 if (!AH->readHeader)
4197 {
4198 char tmpMag[7];
4199
4200 AH->ReadBufPtr(AH, tmpMag, 5);
4201
4202 if (strncmp(tmpMag, "PGDMP", 5) != 0)
4203 pg_fatal("did not find magic string in file header");
4204 }
4205
4206 vmaj = AH->ReadBytePtr(AH);
4207 vmin = AH->ReadBytePtr(AH);
4208
4209 if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */
4210 vrev = AH->ReadBytePtr(AH);
4211 else
4212 vrev = 0;
4213
4215
4216 if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
4217 pg_fatal("unsupported version (%d.%d) in file header",
4218 vmaj, vmin);
4219
4220 AH->intSize = AH->ReadBytePtr(AH);
4221 if (AH->intSize > 32)
4222 pg_fatal("sanity check on integer size (%zu) failed", AH->intSize);
4223
4224 if (AH->intSize > sizeof(int))
4225 pg_log_warning("archive was made on a machine with larger integers, some operations might fail");
4226
4227 if (AH->version >= K_VERS_1_7)
4228 AH->offSize = AH->ReadBytePtr(AH);
4229 else
4230 AH->offSize = AH->intSize;
4231
4232 fmt = AH->ReadBytePtr(AH);
4233
4234 if (AH->format != fmt)
4235 pg_fatal("expected format (%d) differs from format found in file (%d)",
4236 AH->format, fmt);
4237
4238 if (AH->version >= K_VERS_1_15)
4240 else if (AH->version >= K_VERS_1_2)
4241 {
4242 /* Guess the compression method based on the level */
4243 if (AH->version < K_VERS_1_4)
4244 AH->compression_spec.level = AH->ReadBytePtr(AH);
4245 else
4246 AH->compression_spec.level = ReadInt(AH);
4247
4248 if (AH->compression_spec.level != 0)
4250 }
4251 else
4253
4255 if (errmsg)
4256 {
4257 pg_log_warning("archive is compressed, but this installation does not support compression (%s) -- no data will be available",
4258 errmsg);
4259 pg_free(errmsg);
4260 }
4261
4262 if (AH->version >= K_VERS_1_4)
4263 {
4264 struct tm crtm;
4265
4266 crtm.tm_sec = ReadInt(AH);
4267 crtm.tm_min = ReadInt(AH);
4268 crtm.tm_hour = ReadInt(AH);
4269 crtm.tm_mday = ReadInt(AH);
4270 crtm.tm_mon = ReadInt(AH);
4271 crtm.tm_year = ReadInt(AH);
4272 crtm.tm_isdst = ReadInt(AH);
4273
4274 /*
4275 * Newer versions of glibc have mktime() report failure if tm_isdst is
4276 * inconsistent with the prevailing timezone, e.g. tm_isdst = 1 when
4277 * TZ=UTC. This is problematic when restoring an archive under a
4278 * different timezone setting. If we get a failure, try again with
4279 * tm_isdst set to -1 ("don't know").
4280 *
4281 * XXX with or without this hack, we reconstruct createDate
4282 * incorrectly when the prevailing timezone is different from
4283 * pg_dump's. Next time we bump the archive version, we should flush
4284 * this representation and store a plain seconds-since-the-Epoch
4285 * timestamp instead.
4286 */
4287 AH->createDate = mktime(&crtm);
4288 if (AH->createDate == (time_t) -1)
4289 {
4290 crtm.tm_isdst = -1;
4291 AH->createDate = mktime(&crtm);
4292 if (AH->createDate == (time_t) -1)
4293 pg_log_warning("invalid creation date in header");
4294 }
4295 }
4296
4297 if (AH->version >= K_VERS_1_4)
4298 {
4299 AH->archdbname = ReadStr(AH);
4300 }
4301
4302 if (AH->version >= K_VERS_1_10)
4303 {
4304 AH->archiveRemoteVersion = ReadStr(AH);
4305 AH->archiveDumpVersion = ReadStr(AH);
4306 }
4307}
4308
4309
4310/*
4311 * checkSeek
4312 * check to see if ftell/fseek can be performed.
4313 */
4314bool
4316{
4317 pgoff_t tpos;
4318
4319 /* Check that ftello works on this file */
4320 tpos = ftello(fp);
4321 if (tpos < 0)
4322 return false;
4323
4324 /*
4325 * Check that fseeko(SEEK_SET) works, too. NB: we used to try to test
4326 * this with fseeko(fp, 0, SEEK_CUR). But some platforms treat that as a
4327 * successful no-op even on files that are otherwise unseekable.
4328 */
4329 if (fseeko(fp, tpos, SEEK_SET) != 0)
4330 return false;
4331
4332 return true;
4333}
4334
4335
4336/*
4337 * dumpTimestamp
4338 */
4339static void
4341{
4342 char buf[64];
4343
4344 if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&tim)) != 0)
4345 ahprintf(AH, "-- %s %s\n\n", msg, buf);
4346}
4347
4348/*
4349 * Main engine for parallel restore.
4350 *
4351 * Parallel restore is done in three phases. In this first phase,
4352 * we'll process all SECTION_PRE_DATA TOC entries that are allowed to be
4353 * processed in the RESTORE_PASS_MAIN pass. (In practice, that's all
4354 * PRE_DATA items other than ACLs.) Entries we can't process now are
4355 * added to the pending_list for later phases to deal with.
4356 */
4357static void
4359{
4360 bool skipped_some;
4362
4363 pg_log_debug("entering restore_toc_entries_prefork");
4364
4365 /* Adjust dependency information */
4366 fix_dependencies(AH);
4367
4368 /*
4369 * Do all the early stuff in a single connection in the parent. There's no
4370 * great point in running it in parallel, in fact it will actually run
4371 * faster in a single connection because we avoid all the connection and
4372 * setup overhead. Also, pre-9.2 pg_dump versions were not very good
4373 * about showing all the dependencies of SECTION_PRE_DATA items, so we do
4374 * not risk trying to process them out-of-order.
4375 *
4376 * Stuff that we can't do immediately gets added to the pending_list.
4377 * Note: we don't yet filter out entries that aren't going to be restored.
4378 * They might participate in dependency chains connecting entries that
4379 * should be restored, so we treat them as live until we actually process
4380 * them.
4381 *
4382 * Note: as of 9.2, it should be guaranteed that all PRE_DATA items appear
4383 * before DATA items, and all DATA items before POST_DATA items. That is
4384 * not certain to be true in older archives, though, and in any case use
4385 * of a list file would destroy that ordering (cf. SortTocFromFile). So
4386 * this loop cannot assume that it holds.
4387 */
4389 skipped_some = false;
4391 {
4392 bool do_now = true;
4393
4394 if (next_work_item->section != SECTION_PRE_DATA)
4395 {
4396 /* DATA and POST_DATA items are just ignored for now */
4397 if (next_work_item->section == SECTION_DATA ||
4399 {
4400 do_now = false;
4401 skipped_some = true;
4402 }
4403 else
4404 {
4405 /*
4406 * SECTION_NONE items, such as comments, can be processed now
4407 * if we are still in the PRE_DATA part of the archive. Once
4408 * we've skipped any items, we have to consider whether the
4409 * comment's dependencies are satisfied, so skip it for now.
4410 */
4411 if (skipped_some)
4412 do_now = false;
4413 }
4414 }
4415
4416 /*
4417 * Also skip items that need to be forced into later passes. We need
4418 * not set skipped_some in this case, since by assumption no main-pass
4419 * items could depend on these.
4420 */
4422 do_now = false;
4423
4424 if (do_now)
4425 {
4426 /* OK, restore the item and update its dependencies */
4427 pg_log_info("processing item %d %s %s",
4428 next_work_item->dumpId,
4429 next_work_item->desc, next_work_item->tag);
4430
4432
4433 /* Reduce dependencies, but don't move anything to ready_heap */
4435 }
4436 else
4437 {
4438 /* Nope, so add it to pending_list */
4440 }
4441 }
4442
4443 /*
4444 * In --transaction-size mode, we must commit the open transaction before
4445 * dropping the database connection. This also ensures that child workers
4446 * can see the objects we've created so far.
4447 */
4448 if (AH->public.ropt->txn_size > 0)
4450
4451 /*
4452 * Now close parent connection in prep for parallel steps. We do this
4453 * mainly to ensure that we don't exceed the specified number of parallel
4454 * connections.
4455 */
4457
4458 /* blow away any transient state from the old connection */
4459 free(AH->currUser);
4460 AH->currUser = NULL;
4461 free(AH->currSchema);
4462 AH->currSchema = NULL;
4463 free(AH->currTablespace);
4464 AH->currTablespace = NULL;
4465 free(AH->currTableAm);
4466 AH->currTableAm = NULL;
4467}
4468
4469/*
4470 * Main engine for parallel restore.
4471 *
4472 * Parallel restore is done in three phases. In this second phase,
4473 * we process entries by dispatching them to parallel worker children
4474 * (processes on Unix, threads on Windows), each of which connects
4475 * separately to the database. Inter-entry dependencies are respected,
4476 * and so is the RestorePass multi-pass structure. When we can no longer
4477 * make any entries ready to process, we exit. Normally, there will be
4478 * nothing left to do; but if there is, the third phase will mop up.
4479 */
4480static void
4483{
4486
4487 pg_log_debug("entering restore_toc_entries_parallel");
4488
4489 /* Set up ready_heap with enough room for all known TocEntrys */
4492 NULL);
4493
4494 /*
4495 * The pending_list contains all items that we need to restore. Move all
4496 * items that are available to process immediately into the ready_heap.
4497 * After this setup, the pending list is everything that needs to be done
4498 * but is blocked by one or more dependencies, while the ready heap
4499 * contains items that have no remaining dependencies and are OK to
4500 * process in the current restore pass.
4501 */
4504
4505 /*
4506 * main parent loop
4507 *
4508 * Keep going until there is no worker still running AND there is no work
4509 * left to be done. Note invariant: at top of loop, there should always
4510 * be at least one worker available to dispatch a job to.
4511 */
4512 pg_log_info("entering main parallel loop");
4513
4514 for (;;)
4515 {
4516 /* Look for an item ready to be dispatched to a worker */
4518 if (next_work_item != NULL)
4519 {
4520 /* If not to be restored, don't waste time launching a worker */
4521 if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA | REQ_STATS)) == 0)
4522 {
4523 pg_log_info("skipping item %d %s %s",
4524 next_work_item->dumpId,
4525 next_work_item->desc, next_work_item->tag);
4526 /* Update its dependencies as though we'd completed it */
4528 /* Loop around to see if anything else can be dispatched */
4529 continue;
4530 }
4531
4532 pg_log_info("launching item %d %s %s",
4533 next_work_item->dumpId,
4534 next_work_item->desc, next_work_item->tag);
4535
4536 /* Dispatch to some worker */
4539 }
4540 else if (IsEveryWorkerIdle(pstate))
4541 {
4542 /*
4543 * Nothing is ready and no worker is running, so we're done with
4544 * the current pass or maybe with the whole process.
4545 */
4546 if (AH->restorePass == RESTORE_PASS_LAST)
4547 break; /* No more parallel processing is possible */
4548
4549 /* Advance to next restore pass */
4550 AH->restorePass++;
4551 /* That probably allows some stuff to be made ready */
4553 /* Loop around to see if anything's now ready */
4554 continue;
4555 }
4556 else
4557 {
4558 /*
4559 * We have nothing ready, but at least one child is working, so
4560 * wait for some subjob to finish.
4561 */
4562 }
4563
4564 /*
4565 * Before dispatching another job, check to see if anything has
4566 * finished. We should check every time through the loop so as to
4567 * reduce dependencies as soon as possible. If we were unable to
4568 * dispatch any job this time through, wait until some worker finishes
4569 * (and, hopefully, unblocks some pending item). If we did dispatch
4570 * something, continue as soon as there's at least one idle worker.
4571 * Note that in either case, there's guaranteed to be at least one
4572 * idle worker when we return to the top of the loop. This ensures we
4573 * won't block inside DispatchJobForTocEntry, which would be
4574 * undesirable: we'd rather postpone dispatching until we see what's
4575 * been unblocked by finished jobs.
4576 */
4577 WaitForWorkers(AH, pstate,
4579 }
4580
4581 /* There should now be nothing in ready_heap. */
4583
4585
4586 pg_log_info("finished main parallel loop");
4587}
4588
4589/*
4590 * Main engine for parallel restore.
4591 *
4592 * Parallel restore is done in three phases. In this third phase,
4593 * we mop up any remaining TOC entries by processing them serially.
4594 * This phase normally should have nothing to do, but if we've somehow
4595 * gotten stuck due to circular dependencies or some such, this provides
4596 * at least some chance of completing the restore successfully.
4597 */
4598static void
4600{
4601 RestoreOptions *ropt = AH->public.ropt;
4602 TocEntry *te;
4603
4604 pg_log_debug("entering restore_toc_entries_postfork");
4605
4606 /*
4607 * Now reconnect the single parent connection.
4608 */
4609 ConnectDatabaseAhx((Archive *) AH, &ropt->cparams, true);
4610
4611 /* re-establish fixed state */
4613
4614 /*
4615 * Make sure there is no work left due to, say, circular dependencies, or
4616 * some other pathological condition. If so, do it in the single parent
4617 * connection. We don't sweat about RestorePass ordering; it's likely we
4618 * already violated that.
4619 */
4620 for (te = pending_list->pending_next; te != pending_list; te = te->pending_next)
4621 {
4622 pg_log_info("processing missed item %d %s %s",
4623 te->dumpId, te->desc, te->tag);
4624 (void) restore_toc_entry(AH, te, false);
4625 }
4626}
4627
4628/*
4629 * Check if te1 has an exclusive lock requirement for an item that te2 also
4630 * requires, whether or not te2's requirement is for an exclusive lock.
4631 */
4632static bool
4634{
4635 int j,
4636 k;
4637
4638 for (j = 0; j < te1->nLockDeps; j++)
4639 {
4640 for (k = 0; k < te2->nDeps; k++)
4641 {
4642 if (te1->lockDeps[j] == te2->dependencies[k])
4643 return true;
4644 }
4645 }
4646 return false;
4647}
4648
4649
4650/*
4651 * Initialize the header of the pending-items list.
4652 *
4653 * This is a circular list with a dummy TocEntry as header, just like the
4654 * main TOC list; but we use separate list links so that an entry can be in
4655 * the main TOC list as well as in the pending list.
4656 */
4657static void
4662
4663/* Append te to the end of the pending-list headed by l */
4664static void
4666{
4667 te->pending_prev = l->pending_prev;
4668 l->pending_prev->pending_next = te;
4669 l->pending_prev = te;
4670 te->pending_next = l;
4671}
4672
4673/* Remove te from the pending-list */
4674static void
4682
4683
4684/* qsort comparator for sorting TocEntries by dataLength */
4685static int
4686TocEntrySizeCompareQsort(const void *p1, const void *p2)
4687{
4688 const TocEntry *te1 = *(const TocEntry *const *) p1;
4689 const TocEntry *te2 = *(const TocEntry *const *) p2;
4690
4691 /* Sort by decreasing dataLength */
4692 if (te1->dataLength > te2->dataLength)
4693 return -1;
4694 if (te1->dataLength < te2->dataLength)
4695 return 1;
4696
4697 /* For equal dataLengths, sort by dumpId, just to be stable */
4698 if (te1->dumpId < te2->dumpId)
4699 return -1;
4700 if (te1->dumpId > te2->dumpId)
4701 return 1;
4702
4703 return 0;
4704}
4705
4706/* binaryheap comparator for sorting TocEntries by dataLength */
4707static int
4709{
4710 /* return opposite of qsort comparator for max-heap */
4711 return -TocEntrySizeCompareQsort(&p1, &p2);
4712}
4713
4714
4715/*
4716 * Move all immediately-ready items from pending_list to ready_heap.
4717 *
4718 * Items are considered ready if they have no remaining dependencies and
4719 * they belong in the current restore pass. (See also reduce_dependencies,
4720 * which applies the same logic one-at-a-time.)
4721 */
4722static void
4726{
4727 TocEntry *te;
4729
4730 for (te = pending_list->pending_next; te != pending_list; te = next_te)
4731 {
4732 /* must save list link before possibly removing te from list */
4733 next_te = te->pending_next;
4734
4735 if (te->depCount == 0 &&
4737 {
4738 /* Remove it from pending_list ... */
4740 /* ... and add to ready_heap */
4742 }
4743 }
4744}
4745
4746/*
4747 * Find the next work item (if any) that is capable of being run now,
4748 * and remove it from the ready_heap.
4749 *
4750 * Returns the item, or NULL if nothing is runnable.
4751 *
4752 * To qualify, the item must have no remaining dependencies
4753 * and no requirements for locks that are incompatible with
4754 * items currently running. Items in the ready_heap are known to have
4755 * no remaining dependencies, but we have to check for lock conflicts.
4756 */
4757static TocEntry *
4759 ParallelState *pstate)
4760{
4761 /*
4762 * Search the ready_heap until we find a suitable item. Note that we do a
4763 * sequential scan through the heap nodes, so even though we will first
4764 * try to choose the highest-priority item, we might end up picking
4765 * something with a much lower priority. However, we expect that we will
4766 * typically be able to pick one of the first few items, which should
4767 * usually have a relatively high priority.
4768 */
4769 for (int i = 0; i < binaryheap_size(ready_heap); i++)
4770 {
4772 bool conflicts = false;
4773
4774 /*
4775 * Check to see if the item would need exclusive lock on something
4776 * that a currently running item also needs lock on, or vice versa. If
4777 * so, we don't want to schedule them together.
4778 */
4779 for (int k = 0; k < pstate->numWorkers; k++)
4780 {
4781 TocEntry *running_te = pstate->te[k];
4782
4783 if (running_te == NULL)
4784 continue;
4785 if (has_lock_conflicts(te, running_te) ||
4787 {
4788 conflicts = true;
4789 break;
4790 }
4791 }
4792
4793 if (conflicts)
4794 continue;
4795
4796 /* passed all tests, so this item can run */
4798 return te;
4799 }
4800
4801 pg_log_debug("no item ready");
4802 return NULL;
4803}
4804
4805
4806/*
4807 * Restore a single TOC item in parallel with others
4808 *
4809 * this is run in the worker, i.e. in a thread (Windows) or a separate process
4810 * (everything else). A worker process executes several such work items during
4811 * a parallel backup or restore. Once we terminate here and report back that
4812 * our work is finished, the leader process will assign us a new work item.
4813 */
4814int
4816{
4817 int status;
4818
4819 Assert(AH->connection != NULL);
4820
4821 /* Count only errors associated with this TOC entry */
4822 AH->public.n_errors = 0;
4823
4824 /* Restore the TOC item */
4825 status = restore_toc_entry(AH, te, true);
4826
4827 return status;
4828}
4829
4830
4831/*
4832 * Callback function that's invoked in the leader process after a step has
4833 * been parallel restored.
4834 *
4835 * Update status and reduce the dependency count of any dependent items.
4836 */
4837static void
4839 TocEntry *te,
4840 int status,
4841 void *callback_data)
4842{
4843 binaryheap *ready_heap = (binaryheap *) callback_data;
4844
4845 pg_log_info("finished item %d %s %s",
4846 te->dumpId, te->desc, te->tag);
4847
4848 if (status == WORKER_CREATE_DONE)
4849 mark_create_done(AH, te);
4850 else if (status == WORKER_INHIBIT_DATA)
4851 {
4853 AH->public.n_errors++;
4854 }
4855 else if (status == WORKER_IGNORED_ERRORS)
4856 AH->public.n_errors++;
4857 else if (status != 0)
4858 pg_fatal("worker process failed: exit code %d",
4859 status);
4860
4862}
4863
4864
4865/*
4866 * Process the dependency information into a form useful for parallel restore.
4867 *
4868 * This function takes care of fixing up some missing or badly designed
4869 * dependencies, and then prepares subsidiary data structures that will be
4870 * used in the main parallel-restore logic, including:
4871 * 1. We build the revDeps[] arrays of incoming dependency dumpIds.
4872 * 2. We set up depCount fields that are the number of as-yet-unprocessed
4873 * dependencies for each TOC entry.
4874 *
4875 * We also identify locking dependencies so that we can avoid trying to
4876 * schedule conflicting items at the same time.
4877 */
4878static void
4880{
4881 TocEntry *te;
4882 int i;
4883
4884 /*
4885 * Initialize the depCount/revDeps/nRevDeps fields, and make sure the TOC
4886 * items are marked as not being in any parallel-processing list.
4887 */
4888 for (te = AH->toc->next; te != AH->toc; te = te->next)
4889 {
4890 te->depCount = te->nDeps;
4891 te->revDeps = NULL;
4892 te->nRevDeps = 0;
4893 te->pending_prev = NULL;
4894 te->pending_next = NULL;
4895 }
4896
4897 /*
4898 * POST_DATA items that are shown as depending on a table need to be
4899 * re-pointed to depend on that table's data, instead. This ensures they
4900 * won't get scheduled until the data has been loaded.
4901 */
4903
4904 /*
4905 * Pre-8.4 versions of pg_dump neglected to set up a dependency from BLOB
4906 * COMMENTS to BLOBS. Cope. (We assume there's only one BLOBS and only
4907 * one BLOB COMMENTS in such files.)
4908 */
4909 if (AH->version < K_VERS_1_11)
4910 {
4911 for (te = AH->toc->next; te != AH->toc; te = te->next)
4912 {
4913 if (strcmp(te->desc, "BLOB COMMENTS") == 0 && te->nDeps == 0)
4914 {
4915 TocEntry *te2;
4916
4917 for (te2 = AH->toc->next; te2 != AH->toc; te2 = te2->next)
4918 {
4919 if (strcmp(te2->desc, "BLOBS") == 0)
4920 {
4922 te->dependencies[0] = te2->dumpId;
4923 te->nDeps++;
4924 te->depCount++;
4925 break;
4926 }
4927 }
4928 break;
4929 }
4930 }
4931 }
4932
4933 /*
4934 * At this point we start to build the revDeps reverse-dependency arrays,
4935 * so all changes of dependencies must be complete.
4936 */
4937
4938 /*
4939 * Count the incoming dependencies for each item. Also, it is possible
4940 * that the dependencies list items that are not in the archive at all
4941 * (that should not happen in 9.2 and later, but is highly likely in older
4942 * archives). Subtract such items from the depCounts.
4943 */
4944 for (te = AH->toc->next; te != AH->toc; te = te->next)
4945 {
4946 for (i = 0; i < te->nDeps; i++)
4947 {
4948 DumpId depid = te->dependencies[i];
4949
4950 if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4951 AH->tocsByDumpId[depid]->nRevDeps++;
4952 else
4953 te->depCount--;
4954 }
4955 }
4956
4957 /*
4958 * Allocate space for revDeps[] arrays, and reset nRevDeps so we can use
4959 * it as a counter below.
4960 */
4961 for (te = AH->toc->next; te != AH->toc; te = te->next)
4962 {
4963 if (te->nRevDeps > 0)
4965 te->nRevDeps = 0;
4966 }
4967
4968 /*
4969 * Build the revDeps[] arrays of incoming-dependency dumpIds. This had
4970 * better agree with the loops above.
4971 */
4972 for (te = AH->toc->next; te != AH->toc; te = te->next)
4973 {
4974 for (i = 0; i < te->nDeps; i++)
4975 {
4976 DumpId depid = te->dependencies[i];
4977
4978 if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4979 {
4981
4982 otherte->revDeps[otherte->nRevDeps++] = te->dumpId;
4983 }
4984 }
4985 }
4986
4987 /*
4988 * Lastly, work out the locking dependencies.
4989 */
4990 for (te = AH->toc->next; te != AH->toc; te = te->next)
4991 {
4992 te->lockDeps = NULL;
4993 te->nLockDeps = 0;
4995 }
4996}
4997
4998/*
4999 * Change dependencies on table items to depend on table data items instead,
5000 * but only in POST_DATA items.
5001 *
5002 * Also, for any item having such dependency(s), set its dataLength to the
5003 * largest dataLength of the table data items it depends on. This ensures
5004 * that parallel restore will prioritize larger jobs (index builds, FK
5005 * constraint checks, etc) over smaller ones, avoiding situations where we
5006 * end a restore with only one active job working on a large table.
5007 */
5008static void
5010{
5011 TocEntry *te;
5012 int i;
5013 DumpId olddep;
5014
5015 for (te = AH->toc->next; te != AH->toc; te = te->next)
5016 {
5017 if (te->section != SECTION_POST_DATA)
5018 continue;
5019 for (i = 0; i < te->nDeps; i++)
5020 {
5021 olddep = te->dependencies[i];
5022 if (olddep <= AH->maxDumpId &&
5023 AH->tableDataId[olddep] != 0)
5024 {
5027
5028 te->dependencies[i] = tabledataid;
5029 te->dataLength = Max(te->dataLength, tabledatate->dataLength);
5030 pg_log_debug("transferring dependency %d -> %d to %d",
5031 te->dumpId, olddep, tabledataid);
5032 }
5033 }
5034 }
5035}
5036
5037/*
5038 * Identify which objects we'll need exclusive lock on in order to restore
5039 * the given TOC entry (*other* than the one identified by the TOC entry
5040 * itself). Record their dump IDs in the entry's lockDeps[] array.
5041 */
5042static void
5044{
5045 DumpId *lockids;
5046 int nlockids;
5047 int i;
5048
5049 /*
5050 * We only care about this for POST_DATA items. PRE_DATA items are not
5051 * run in parallel, and DATA items are all independent by assumption.
5052 */
5053 if (te->section != SECTION_POST_DATA)
5054 return;
5055
5056 /* Quick exit if no dependencies at all */
5057 if (te->nDeps == 0)
5058 return;
5059
5060 /*
5061 * Most POST_DATA items are ALTER TABLEs or some moral equivalent of that,
5062 * and hence require exclusive lock. However, we know that CREATE INDEX
5063 * does not. (Maybe someday index-creating CONSTRAINTs will fall in that
5064 * category too ... but today is not that day.)
5065 */
5066 if (strcmp(te->desc, "INDEX") == 0)
5067 return;
5068
5069 /*
5070 * We assume the entry requires exclusive lock on each TABLE or TABLE DATA
5071 * item listed among its dependencies. Originally all of these would have
5072 * been TABLE items, but repoint_table_dependencies would have repointed
5073 * them to the TABLE DATA items if those are present (which they might not
5074 * be, eg in a schema-only dump). Note that all of the entries we are
5075 * processing here are POST_DATA; otherwise there might be a significant
5076 * difference between a dependency on a table and a dependency on its
5077 * data, so that closer analysis would be needed here.
5078 */
5080 nlockids = 0;
5081 for (i = 0; i < te->nDeps; i++)
5082 {
5083 DumpId depid = te->dependencies[i];
5084
5085 if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL &&
5086 ((strcmp(AH->tocsByDumpId[depid]->desc, "TABLE DATA") == 0) ||
5087 strcmp(AH->tocsByDumpId[depid]->desc, "TABLE") == 0))
5088 lockids[nlockids++] = depid;
5089 }
5090
5091 if (nlockids == 0)
5092 {
5093 free(lockids);
5094 return;
5095 }
5096
5098 te->nLockDeps = nlockids;
5099}
5100
5101/*
5102 * Remove the specified TOC entry from the depCounts of items that depend on
5103 * it, thereby possibly making them ready-to-run. Any pending item that
5104 * becomes ready should be moved to the ready_heap, if that's provided.
5105 */
5106static void
5109{
5110 int i;
5111
5112 pg_log_debug("reducing dependencies for %d", te->dumpId);
5113
5114 for (i = 0; i < te->nRevDeps; i++)
5115 {
5116 TocEntry *otherte = AH->tocsByDumpId[te->revDeps[i]];
5117
5118 Assert(otherte->depCount > 0);
5119 otherte->depCount--;
5120
5121 /*
5122 * It's ready if it has no remaining dependencies, and it belongs in
5123 * the current restore pass, and it is currently a member of the
5124 * pending list (that check is needed to prevent double restore in
5125 * some cases where a list-file forces out-of-order restoring).
5126 * However, if ready_heap == NULL then caller doesn't want any list
5127 * memberships changed.
5128 */
5129 if (otherte->depCount == 0 &&
5131 otherte->pending_prev != NULL &&
5132 ready_heap != NULL)
5133 {
5134 /* Remove it from pending list ... */
5136 /* ... and add to ready_heap */
5138 }
5139 }
5140}
5141
5142/*
5143 * Set the created flag on the DATA member corresponding to the given
5144 * TABLE member
5145 */
5146static void
5148{
5149 if (AH->tableDataId[te->dumpId] != 0)
5150 {
5151 TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
5152
5153 ted->created = true;
5154 }
5155}
5156
5157/*
5158 * Mark the DATA member corresponding to the given TABLE member
5159 * as not wanted
5160 */
5161static void
5163{
5164 pg_log_info("table \"%s\" could not be created, will not restore its data",
5165 te->tag);
5166
5167 if (AH->tableDataId[te->dumpId] != 0)
5168 {
5169 TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
5170
5171 ted->reqs = 0;
5172 }
5173}
5174
5175/*
5176 * Clone and de-clone routines used in parallel restoration.
5177 *
5178 * Enough of the structure is cloned to ensure that there is no
5179 * conflict between different threads each with their own clone.
5180 */
5183{
5185
5186 /* Make a "flat" copy */
5188 memcpy(clone, AH, sizeof(ArchiveHandle));
5189
5190 /* Likewise flat-copy the RestoreOptions, so we can alter them locally */
5191 clone->public.ropt = pg_malloc_object(RestoreOptions);
5192 memcpy(clone->public.ropt, AH->public.ropt, sizeof(RestoreOptions));
5193
5194 /* Handle format-independent fields */
5195 memset(&(clone->sqlparse), 0, sizeof(clone->sqlparse));
5196
5197 /* The clone will have its own connection, so disregard connection state */
5198 clone->connection = NULL;
5199 clone->connCancel = NULL;
5200 clone->currUser = NULL;
5201 clone->currSchema = NULL;
5202 clone->currTableAm = NULL;
5203 clone->currTablespace = NULL;
5204
5205 /* savedPassword must be local in case we change it while connecting */
5206 if (clone->savedPassword)
5207 clone->savedPassword = pg_strdup(clone->savedPassword);
5208
5209 /* clone has its own error count, too */
5210 clone->public.n_errors = 0;
5211
5212 /* clones should not share lo_buf */
5213 clone->lo_buf = NULL;
5214
5215 /*
5216 * Clone connections disregard --transaction-size; they must commit after
5217 * each command so that the results are immediately visible to other
5218 * workers.
5219 */
5220 clone->public.ropt->txn_size = 0;
5221
5222 /*
5223 * Connect our new clone object to the database, using the same connection
5224 * parameters used for the original connection.
5225 */
5226 ConnectDatabaseAhx((Archive *) clone, &clone->public.ropt->cparams, true);
5227
5228 /* re-establish fixed state */
5229 if (AH->mode == archModeRead)
5231 /* in write case, setupDumpWorker will fix up connection state */
5232
5233 /* Let the format-specific code have a chance too */
5234 clone->ClonePtr(clone);
5235
5236 Assert(clone->connection != NULL);
5237 return clone;
5238}
5239
5240/*
5241 * Release clone-local storage.
5242 *
5243 * Note: we assume any clone-local connection was already closed.
5244 */
5245void
5247{
5248 /* Should not have an open database connection */
5249 Assert(AH->connection == NULL);
5250
5251 /* Clear format-specific state */
5252 AH->DeClonePtr(AH);
5253
5254 /* Clear state allocated by CloneArchive */
5255 if (AH->sqlparse.curCmd)
5257
5258 /* Clear any connection-local state */
5259 free(AH->currUser);
5260 free(AH->currSchema);
5261 free(AH->currTablespace);
5262 free(AH->currTableAm);
5263 free(AH->savedPassword);
5264
5265 free(AH);
5266}
int lo_write(int fd, const char *buf, int len)
Definition be-fsstubs.c:182
void ParallelBackupEnd(ArchiveHandle *AH, ParallelState *pstate)
Definition parallel.c:1061
void WaitForWorkers(ArchiveHandle *AH, ParallelState *pstate, WFW_WaitOption mode)
Definition parallel.c:1453
ParallelState * ParallelBackupStart(ArchiveHandle *AH)
Definition parallel.c:899
void DispatchJobForTocEntry(ArchiveHandle *AH, ParallelState *pstate, TocEntry *te, T_Action act, ParallelCompletionPtr callback, void *callback_data)
Definition parallel.c:1207
bool IsEveryWorkerIdle(ParallelState *pstate)
Definition parallel.c:1270
@ WFW_ALL_IDLE
Definition parallel.h:35
@ WFW_GOT_STATUS
Definition parallel.h:33
@ WFW_ONE_IDLE
Definition parallel.h:34
void binaryheap_remove_node(binaryheap *heap, int n)
Definition binaryheap.c:223
void binaryheap_add(binaryheap *heap, bh_node_type d)
Definition binaryheap.c:152
void binaryheap_free(binaryheap *heap)
Definition binaryheap.c:73
binaryheap * binaryheap_allocate(int capacity, binaryheap_comparator compare, void *arg)
Definition binaryheap.c:37
#define binaryheap_size(h)
Definition binaryheap.h:66
#define binaryheap_empty(h)
Definition binaryheap.h:65
#define binaryheap_get_node(h, n)
Definition binaryheap.h:67
#define PG_BINARY_R
Definition c.h:1388
#define ngettext(s, p, n)
Definition c.h:1270
#define PG_BINARY_A
Definition c.h:1387
#define Max(x, y)
Definition c.h:1085
#define Assert(condition)
Definition c.h:943
#define PG_BINARY_W
Definition c.h:1389
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
bool EndCompressFileHandle(CompressFileHandle *CFH)
char * supports_compression(const pg_compress_specification compression_spec)
Definition compress_io.c:87
CompressFileHandle * InitCompressFileHandle(const pg_compress_specification compression_spec)
const char * get_compress_algorithm_name(pg_compress_algorithm algorithm)
Definition compression.c:99
@ PG_COMPRESSION_GZIP
Definition compression.h:24
@ PG_COMPRESSION_NONE
Definition compression.h:23
char * sanitize_line(const char *str, bool want_hyphen)
Definition dumputils.c:52
#define PGDUMP_STRFTIME_FMT
Definition dumputils.h:34
Datum arg
Definition elog.c:1323
char * PQdb(const PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
PGresult * PQexec(PGconn *conn, const char *query)
Definition fe-exec.c:2279
int lo_close(PGconn *conn, int fd)
Definition fe-lobj.c:96
int lo_open(PGconn *conn, Oid lobjId, int mode)
Definition fe-lobj.c:57
Oid lo_create(PGconn *conn, Oid lobjId)
Definition fe-lobj.c:474
void * pg_malloc(size_t size)
Definition fe_memutils.c:53
char * pg_strdup(const char *in)
Definition fe_memutils.c:91
void * pg_malloc0(size_t size)
Definition fe_memutils.c:59
void pg_free(void *ptr)
#define pg_realloc_array(pointer, type, count)
Definition fe_memutils.h:74
#define pg_malloc_array(type, count)
Definition fe_memutils.h:66
#define pg_malloc0_object(type)
Definition fe_memutils.h:61
#define pg_malloc_object(type)
Definition fe_memutils.h:60
#define pg_malloc0_array(type, count)
Definition fe_memutils.h:67
DataDirSyncMethod
Definition file_utils.h:28
@ DATA_DIR_SYNC_METHOD_FSYNC
Definition file_utils.h:29
int remaining
Definition informix.c:692
char sign
Definition informix.c:693
static char * encoding
Definition initdb.c:139
static DataDirSyncMethod sync_method
Definition initdb.c:170
int b
Definition isn.c:74
return true
Definition isn.c:130
int j
Definition isn.c:78
int i
Definition isn.c:77
#define PQclear
#define PQresultStatus
@ PGRES_COMMAND_OK
Definition libpq-fe.h:131
#define INV_WRITE
Definition libpq-fs.h:21
static struct pg_tm tm
Definition localtime.c:104
void pg_log_generic_v(enum pg_log_level level, enum pg_log_part part, const char *pg_restrict fmt, va_list ap)
Definition logging.c:233
#define pg_log_info(...)
Definition logging.h:126
@ PG_LOG_PRIMARY
Definition logging.h:67
@ PG_LOG_ERROR
Definition logging.h:43
#define pg_log_debug(...)
Definition logging.h:135
static char * errmsg
static AmcheckOptions opts
Definition pg_amcheck.c:112
@ SECTION_NONE
Definition pg_backup.h:57
@ SECTION_POST_DATA
Definition pg_backup.h:60
@ SECTION_PRE_DATA
Definition pg_backup.h:58
@ SECTION_DATA
Definition pg_backup.h:59
int DumpId
Definition pg_backup.h:285
void(* SetupWorkerPtrType)(Archive *AH)
Definition pg_backup.h:292
enum _archiveFormat ArchiveFormat
void ConnectDatabaseAhx(Archive *AHX, const ConnParams *cparams, bool isReconnect)
@ archModeWrite
Definition pg_backup.h:51
@ archModeAppend
Definition pg_backup.h:50
@ archModeRead
Definition pg_backup.h:52
void DisconnectDatabase(Archive *AHX)
enum _teSection teSection
@ archUnknown
Definition pg_backup.h:41
@ archTar
Definition pg_backup.h:43
@ archCustom
Definition pg_backup.h:42
@ archDirectory
Definition pg_backup.h:45
@ archNull
Definition pg_backup.h:44
static void fix_dependencies(ArchiveHandle *AH)
static void repoint_table_dependencies(ArchiveHandle *AH)
void DeCloneArchive(ArchiveHandle *AH)
static int _discoverArchiveFormat(ArchiveHandle *AH)
#define TEXT_DUMPALL_HEADER
int TocIDRequired(ArchiveHandle *AH, DumpId id)
bool checkSeek(FILE *fp)
void ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
void warn_or_exit_horribly(ArchiveHandle *AH, const char *fmt,...)
void WriteDataChunksForTocEntry(ArchiveHandle *AH, TocEntry *te)
static void _becomeOwner(ArchiveHandle *AH, TocEntry *te)
void WriteHead(ArchiveHandle *AH)
int EndLO(Archive *AHX, Oid oid)
static CompressFileHandle * SaveOutput(ArchiveHandle *AH)
#define TOC_PREFIX_DATA
static void _becomeUser(ArchiveHandle *AH, const char *user)
static void pending_list_append(TocEntry *l, TocEntry *te)
size_t WriteInt(ArchiveHandle *AH, int i)
void ProcessArchiveRestoreOptions(Archive *AHX)
static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)
static void _moveBefore(TocEntry *pos, TocEntry *te)
RestoreOptions * NewRestoreOptions(void)
static bool _tocEntryIsACL(TocEntry *te)
static void move_to_ready_heap(TocEntry *pending_list, binaryheap *ready_heap, RestorePass pass)
char * ReadStr(ArchiveHandle *AH)
static void _getObjectDescription(PQExpBuffer buf, const TocEntry *te)
static void buildTocEntryArrays(ArchiveHandle *AH)
static void identify_locking_dependencies(ArchiveHandle *AH, TocEntry *te)
static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te)
static void processSearchPathEntry(ArchiveHandle *AH, TocEntry *te)
int archprintf(Archive *AH, const char *fmt,...)
static void StrictNamesCheck(RestoreOptions *ropt)
static void mark_restore_job_done(ArchiveHandle *AH, TocEntry *te, int status, void *callback_data)
size_t WriteOffset(ArchiveHandle *AH, pgoff_t o, int wasSet)
static RestorePass _tocEntryRestorePass(TocEntry *te)
TocEntry * ArchiveEntry(Archive *AHX, CatalogId catalogId, DumpId dumpId, ArchiveOpts *opts)
int StartLO(Archive *AHX, Oid oid)
static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, const char *pfx)
#define TOC_PREFIX_STATS
ArchiveHandle * CloneArchive(ArchiveHandle *AH)
static void setupRestoreWorker(Archive *AHX)
static void _reconnectToDB(ArchiveHandle *AH, const char *dbname)
static int TocEntrySizeCompareQsort(const void *p1, const void *p2)
Archive * OpenArchive(const char *FileSpec, const ArchiveFormat fmt)
void StartRestoreLOs(ArchiveHandle *AH)
void CloseArchive(Archive *AHX)
static void pending_list_header_init(TocEntry *l)
static void restore_toc_entries_parallel(ArchiveHandle *AH, ParallelState *pstate, TocEntry *pending_list)
static void SetOutput(ArchiveHandle *AH, const char *filename, const pg_compress_specification compression_spec)
TocEntry * getTocEntryByDumpId(ArchiveHandle *AH, DumpId id)
static void mark_create_done(ArchiveHandle *AH, TocEntry *te)
#define TEXT_DUMP_HEADER
static void _selectTableAccessMethod(ArchiveHandle *AH, const char *tableam)
void WriteDataChunks(ArchiveHandle *AH, ParallelState *pstate)
static void dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim)
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
static void mark_dump_job_done(ArchiveHandle *AH, TocEntry *te, int status, void *callback_data)
static bool is_load_via_partition_root(TocEntry *te)
Archive * CreateArchive(const char *FileSpec, const ArchiveFormat fmt, const pg_compress_specification compression_spec, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupDumpWorker, DataDirSyncMethod sync_method)
static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te)
DumpOptions * NewDumpOptions(void)
void SortTocFromFile(Archive *AHX)
int ReadOffset(ArchiveHandle *AH, pgoff_t *o)
static void inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te)
int ReadInt(ArchiveHandle *AH)
static void restore_toc_entries_prefork(ArchiveHandle *AH, TocEntry *pending_list)
static void _printTableAccessMethodNoStorage(ArchiveHandle *AH, TocEntry *te)
static void restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list)
#define TOC_PREFIX_NONE
static void RestoreOutput(ArchiveHandle *AH, CompressFileHandle *savedOutput)
static void _doSetFixedOutputState(ArchiveHandle *AH)
void PrintTOCSummary(Archive *AHX)
static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te)
static int TocEntrySizeCompareBinaryheap(void *p1, void *p2, void *arg)
static int RestoringToDB(ArchiveHandle *AH)
void ReadHead(ArchiveHandle *AH)
void SetArchiveOptions(Archive *AH, DumpOptions *dopt, RestoreOptions *ropt)
static void pending_list_remove(TocEntry *te)
static bool has_lock_conflicts(TocEntry *te1, TocEntry *te2)
void ReadToc(ArchiveHandle *AH)
static void reduce_dependencies(ArchiveHandle *AH, TocEntry *te, binaryheap *ready_heap)
void EndRestoreLO(ArchiveHandle *AH, Oid oid)
static void _selectTablespace(ArchiveHandle *AH, const char *tablespace)
void RestoreArchive(Archive *AHX)
void WriteToc(ArchiveHandle *AH)
void archputs(const char *s, Archive *AH)
static bool _fileExistsInDirectory(const char *dir, const char *filename)
DumpOptions * dumpOptionsFromRestoreOptions(RestoreOptions *ropt)
static int _tocEntryRequired(TocEntry *te, teSection curSection, ArchiveHandle *AH)
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user)
void EndRestoreLOs(ArchiveHandle *AH)
void StartRestoreLO(ArchiveHandle *AH, Oid oid, bool drop)
void InitDumpOptions(DumpOptions *opts)
static ArchiveHandle * _allocAH(const char *FileSpec, const ArchiveFormat fmt, const pg_compress_specification compression_spec, bool dosync, ArchiveMode mode, SetupWorkerPtrType setupWorkerPtr, DataDirSyncMethod sync_method)
static void dump_lo_buf(ArchiveHandle *AH)
static TocEntry * pop_next_work_item(binaryheap *ready_heap, ParallelState *pstate)
void WriteData(Archive *AHX, const void *data, size_t dLen)
int parallel_restore(ArchiveHandle *AH, TocEntry *te)
size_t WriteStr(ArchiveHandle *AH, const char *c)
static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te)
#define K_VERS_1_15
void InitArchiveFmt_Null(ArchiveHandle *AH)
#define WORKER_CREATE_DONE
#define LOBBUFSIZE
void IssueACLPerBlob(ArchiveHandle *AH, TocEntry *te)
#define K_VERS_1_14
#define appendByteaLiteralAHX(buf, str, len, AH)
void struct _archiveOpts ArchiveOpts
void(* EndDataPtrType)(ArchiveHandle *AH, TocEntry *te)
#define K_VERS_SELF
#define K_VERS_1_10
void(* StartDataPtrType)(ArchiveHandle *AH, TocEntry *te)
#define ARCHIVE_MAJOR(version)
#define ARCHIVE_MINOR(version)
#define K_VERS_1_2
#define RESTORE_PASS_LAST
void InitArchiveFmt_Custom(ArchiveHandle *AH)
#define K_OFFSET_NO_DATA
void InitArchiveFmt_Tar(ArchiveHandle *AH)
#define REQ_SCHEMA
#define K_VERS_1_4
#define appendStringLiteralAHX(buf, str, AH)
void DropLOIfExists(ArchiveHandle *AH, Oid oid)
#define MAKE_ARCHIVE_VERSION(major, minor, rev)
#define K_VERS_1_5
void ReconnectToServer(ArchiveHandle *AH, const char *dbname)
#define ARCHIVE_REV(version)
#define REQ_STATS
#define WRITE_ERROR_EXIT
#define WORKER_IGNORED_ERRORS
#define REQ_SPECIAL
void IssueCommandPerBlob(ArchiveHandle *AH, TocEntry *te, const char *cmdBegin, const char *cmdEnd)
#define K_VERS_1_6
@ STAGE_INITIALIZING
@ STAGE_PROCESSING
@ STAGE_NONE
@ STAGE_FINALIZING
@ ACT_RESTORE
#define K_VERS_1_0
#define K_OFFSET_POS_NOT_SET
#define K_OFFSET_POS_SET
#define K_VERS_MAX
#define K_VERS_1_8
#define WORKER_OK
@ OUTPUT_COPYDATA
@ OUTPUT_SQLCMDS
@ OUTPUT_OTHERDATA
#define K_VERS_1_12
#define REQ_DATA
#define READ_ERROR_EXIT(fd)
void InitArchiveFmt_Directory(ArchiveHandle *AH)
#define K_VERS_1_11
#define K_VERS_1_9
#define WORKER_INHIBIT_DATA
#define K_VERS_1_16
@ RESTORE_PASS_POST_ACL
@ RESTORE_PASS_ACL
@ RESTORE_PASS_MAIN
#define K_VERS_1_3
#define K_VERS_1_7
void EndDBCopyMode(Archive *AHX, const char *tocEntryTag)
int ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen)
void exit_nicely(int code)
#define DUMP_PRE_DATA
#define DUMP_DATA
#define DUMP_UNSECTIONED
#define pg_fatal(...)
#define DUMP_POST_DATA
static PgChecksumMode mode
#define MAXPGPATH
const void size_t len
const void * data
static int sig
Definition pg_ctl.c:81
static bool dosync
Definition pg_dump.c:152
static void setupDumpWorker(Archive *AH)
Definition pg_dump.c:1580
static char * filename
Definition pg_dumpall.c:120
bool pg_get_line_buf(FILE *stream, StringInfo buf)
Definition pg_get_line.c:95
static char * user
Definition pg_regress.c:121
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define pg_encoding_to_char
Definition pg_wchar.h:483
#define pg_char_to_encoding
Definition pg_wchar.h:482
static char * tablespace
Definition pgbench.c:217
#define pg_log_warning(...)
Definition pgfnames.c:24
bool isValidTarHeader(const char *header)
Definition tar.c:112
#define sprintf
Definition port.h:263
#define snprintf
Definition port.h:261
#define qsort(a, b, c, d)
Definition port.h:496
off_t pgoff_t
Definition port.h:422
#define InvalidOid
unsigned int Oid
PQExpBuffer createPQExpBuffer(void)
Definition pqexpbuffer.c:72
void initPQExpBuffer(PQExpBuffer str)
Definition pqexpbuffer.c:90
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void destroyPQExpBuffer(PQExpBuffer str)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
char * c
static int fb(int x)
size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args)
Definition psprintf.c:103
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
const char * simple_string_list_not_touched(SimpleStringList *list)
bool simple_string_list_member(SimpleStringList *list, const char *val)
Definition simple_list.c:87
#define free(a)
char * dbname
Definition streamutil.c:49
const char * fmtQualifiedId(const char *schema, const char *id)
const char * fmtId(const char *rawid)
void setFmtEncoding(int encoding)
void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname)
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
int minRemoteVersion
Definition pg_backup.h:237
char * remoteVersionStr
Definition pg_backup.h:233
DumpOptions * dopt
Definition pg_backup.h:229
bool exit_on_error
Definition pg_backup.h:252
char * searchpath
Definition pg_backup.h:248
int maxRemoteVersion
Definition pg_backup.h:238
int n_errors
Definition pg_backup.h:253
bool std_strings
Definition pg_backup.h:245
int numWorkers
Definition pg_backup.h:240
int encoding
Definition pg_backup.h:244
int verbose
Definition pg_backup.h:232
RestoreOptions * ropt
Definition pg_backup.h:230
Oid tableoid
Definition pg_backup.h:281
TocEntry ** te
Definition parallel.h:59
SimpleStringListCell * head
Definition simple_list.h:42
ArchiverStage stage
RestorePass restorePass
ArchiveFormat format
struct _tocEntry * toc
DeClonePtrType DeClonePtr
EndLOsPtrType EndLOsPtr
DataDirSyncMethod sync_method
struct _tocEntry * lastErrorTE
ReadExtraTocPtrType ReadExtraTocPtr
struct _tocEntry * currentTE
CustomOutPtrType CustomOutPtr
StartLOsPtrType StartLOsPtr
ArchiveEntryPtrType ArchiveEntryPtr
pg_compress_specification compression_spec
WriteDataPtrType WriteDataPtr
StartLOPtrType StartLOPtr
struct _tocEntry ** tocsByDumpId
ClonePtrType ClonePtr
WriteBufPtrType WriteBufPtr
PrepParallelRestorePtrType PrepParallelRestorePtr
EndLOPtrType EndLOPtr
WriteExtraTocPtrType WriteExtraTocPtr
ReadBytePtrType ReadBytePtr
PrintTocDataPtrType PrintTocDataPtr
struct _tocEntry * currToc
WriteBytePtrType WriteBytePtr
sqlparseInfo sqlparse
ReadBufPtrType ReadBufPtr
PrintExtraTocPtrType PrintExtraTocPtr
ArchiverStage lastErrorStage
StartDataPtrType StartDataPtr
ReopenPtrType ReopenPtr
ArchiverOutput outputKind
EndDataPtrType EndDataPtr
SetupWorkerPtrType SetupWorkerPtr
ClosePtrType ClosePtr
char * pgport
Definition pg_backup.h:88
char * pghost
Definition pg_backup.h:89
trivalue promptPassword
Definition pg_backup.h:91
char * username
Definition pg_backup.h:90
char * dbname
Definition pg_backup.h:87
char * restrict_key
Definition pg_backup.h:220
int column_inserts
Definition pg_backup.h:185
int use_setsessauth
Definition pg_backup.h:198
int outputCreateDB
Definition pg_backup.h:206
bool include_everything
Definition pg_backup.h:203
int sequence_data
Definition pg_backup.h:212
int disable_dollar_quoting
Definition pg_backup.h:184
bool dumpSchema
Definition pg_backup.h:216
int outputNoTableAm
Definition pg_backup.h:196
int enable_row_security
Definition pg_backup.h:199
char * outputSuperuser
Definition pg_backup.h:210
int no_security_labels
Definition pg_backup.h:190
bool dumpStatistics
Definition pg_backup.h:218
int no_publications
Definition pg_backup.h:189
ConnParams cparams
Definition pg_backup.h:173
const char * lockWaitTimeout
Definition pg_backup.h:180
int no_subscriptions
Definition pg_backup.h:191
int outputNoTablespaces
Definition pg_backup.h:197
int disable_triggers
Definition pg_backup.h:195
int outputNoOwner
Definition pg_backup.h:209
SimpleStringList schemaExcludeNames
Definition pg_backup.h:141
int suppressDumpWarnings
Definition pg_backup.h:152
ConnParams cparams
Definition pg_backup.h:146
SimpleStringList functionNames
Definition pg_backup.h:139
SimpleStringList tableNames
Definition pg_backup.h:143
SimpleStringList indexNames
Definition pg_backup.h:138
pg_compress_specification compression_spec
Definition pg_backup.h:150
SimpleStringList triggerNames
Definition pg_backup.h:142
int disable_dollar_quoting
Definition pg_backup.h:110
SimpleStringList schemaNames
Definition pg_backup.h:140
char * restrict_key
Definition pg_backup.h:168
const char * filename
Definition pg_backup.h:121
const char * lockWaitTimeout
Definition pg_backup.h:125
int enable_row_security
Definition pg_backup.h:159
int noDataForFailedTables
Definition pg_backup.h:148
struct _tocEntry * pending_next
struct _tocEntry * prev
teSection section
struct _tocEntry * pending_prev
DefnDumperPtr defnDumper
DataDumperPtr dataDumper
CatalogId catalogId
struct _tocEntry * next
const void * dataDumperArg
const void * defnDumperArg
DumpId * dependencies
pg_compress_algorithm algorithm
Definition compression.h:34
int tm_sec
Definition pgtime.h:36
unsigned short st_mode
Definition win32_port.h:258
static void * fn(void *arg)
@ TRI_DEFAULT
Definition vacuumlo.c:36
const char * type
#define stat
Definition win32_port.h:74
#define S_ISDIR(m)
Definition win32_port.h:315
#define ftello(stream)
Definition win32_port.h:209
#define S_ISREG(m)
Definition win32_port.h:318
#define fseeko(stream, offset, origin)
Definition win32_port.h:206
static void StartTransaction(void)
Definition xact.c:2106
static void CommitTransaction(void)
Definition xact.c:2270
ArchiveMode
Definition xlog.h:66