PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 "parallel.h"
34 #include "pg_backup_archiver.h"
35 #include "pg_backup_db.h"
36 #include "pg_backup_utils.h"
37 #include "dumputils.h"
38 #include "fe_utils/string_utils.h"
39 
40 #include "libpq/libpq-fs.h"
41 
42 #define TEXT_DUMP_HEADER "--\n-- PostgreSQL database dump\n--\n\n"
43 #define TEXT_DUMPALL_HEADER "--\n-- PostgreSQL database cluster dump\n--\n\n"
44 
45 /* state needed to save/restore an archive's output target */
46 typedef struct _outputContext
47 {
48  void *OF;
49  int gzOut;
51 
52 /* translator: this is a module name */
53 static const char *modulename = gettext_noop("archiver");
54 
55 
56 static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
57  const int compression, bool dosync, ArchiveMode mode,
58  SetupWorkerPtr setupWorkerPtr);
60  ArchiveHandle *AH);
61 static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData, bool acl_pass);
62 static char *replace_line_endings(const char *str);
63 static void _doSetFixedOutputState(ArchiveHandle *AH);
64 static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
65 static void _doSetWithOids(ArchiveHandle *AH, const bool withOids);
66 static void _reconnectToDB(ArchiveHandle *AH, const char *dbname);
67 static void _becomeUser(ArchiveHandle *AH, const char *user);
68 static void _becomeOwner(ArchiveHandle *AH, TocEntry *te);
69 static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName);
70 static void _selectTablespace(ArchiveHandle *AH, const char *tablespace);
71 static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te);
72 static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te);
73 static teReqs _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt);
74 static bool _tocEntryIsACL(TocEntry *te);
77 static void buildTocEntryArrays(ArchiveHandle *AH);
78 static void _moveBefore(ArchiveHandle *AH, TocEntry *pos, TocEntry *te);
80 
81 static int RestoringToDB(ArchiveHandle *AH);
82 static void dump_lo_buf(ArchiveHandle *AH);
83 static void dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim);
84 static void SetOutput(ArchiveHandle *AH, const char *filename, int compression);
86 static void RestoreOutput(ArchiveHandle *AH, OutputContext savedContext);
87 
88 static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel);
91  TocEntry *pending_list);
92 static void restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list);
93 static void par_list_header_init(TocEntry *l);
94 static void par_list_append(TocEntry *l, TocEntry *te);
95 static void par_list_remove(TocEntry *te);
97  TocEntry *ready_list,
98  ParallelState *pstate);
99 static void mark_dump_job_done(ArchiveHandle *AH,
100  TocEntry *te,
101  int status,
102  void *callback_data);
103 static void mark_restore_job_done(ArchiveHandle *AH,
104  TocEntry *te,
105  int status,
106  void *callback_data);
107 static void fix_dependencies(ArchiveHandle *AH);
108 static bool has_lock_conflicts(TocEntry *te1, TocEntry *te2);
111 static void reduce_dependencies(ArchiveHandle *AH, TocEntry *te,
112  TocEntry *ready_list);
113 static void mark_create_done(ArchiveHandle *AH, TocEntry *te);
115 
116 static void StrictNamesCheck(RestoreOptions *ropt);
117 
118 
119 /*
120  * Allocate a new DumpOptions block containing all default values.
121  */
122 DumpOptions *
124 {
125  DumpOptions *opts = (DumpOptions *) pg_malloc(sizeof(DumpOptions));
126 
127  InitDumpOptions(opts);
128  return opts;
129 }
130 
131 /*
132  * Initialize a DumpOptions struct to all default values
133  */
134 void
136 {
137  memset(opts, 0, sizeof(DumpOptions));
138  /* set any fields that shouldn't default to zeroes */
139  opts->include_everything = true;
141 }
142 
143 /*
144  * Create a freshly allocated DumpOptions with options equivalent to those
145  * found in the given RestoreOptions.
146  */
147 DumpOptions *
149 {
150  DumpOptions *dopt = NewDumpOptions();
151 
152  /* this is the inverse of what's at the end of pg_dump.c's main() */
153  dopt->outputClean = ropt->dropSchema;
154  dopt->dataOnly = ropt->dataOnly;
155  dopt->schemaOnly = ropt->schemaOnly;
156  dopt->if_exists = ropt->if_exists;
157  dopt->column_inserts = ropt->column_inserts;
158  dopt->dumpSections = ropt->dumpSections;
159  dopt->aclsSkip = ropt->aclsSkip;
160  dopt->outputSuperuser = ropt->superuser;
161  dopt->outputCreateDB = ropt->createDB;
162  dopt->outputNoOwner = ropt->noOwner;
163  dopt->outputNoTablespaces = ropt->noTablespace;
164  dopt->disable_triggers = ropt->disable_triggers;
165  dopt->use_setsessauth = ropt->use_setsessauth;
166 
168  dopt->dump_inserts = ropt->dump_inserts;
170  dopt->lockWaitTimeout = ropt->lockWaitTimeout;
173  dopt->sequence_data = ropt->sequence_data;
175 
176  return dopt;
177 }
178 
179 
180 /*
181  * Wrapper functions.
182  *
183  * The objective it to make writing new formats and dumpers as simple
184  * as possible, if necessary at the expense of extra function calls etc.
185  *
186  */
187 
188 /*
189  * The dump worker setup needs lots of knowledge of the internals of pg_dump,
190  * so It's defined in pg_dump.c and passed into OpenArchive. The restore worker
191  * setup doesn't need to know anything much, so it's defined here.
192  */
193 static void
195 {
196  ArchiveHandle *AH = (ArchiveHandle *) AHX;
197 
198  (AH->ReopenPtr) (AH);
199 }
200 
201 
202 /* Create a new archive */
203 /* Public */
204 Archive *
205 CreateArchive(const char *FileSpec, const ArchiveFormat fmt,
206  const int compression, bool dosync, ArchiveMode mode,
208 
209 {
210  ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression, dosync,
211  mode, setupDumpWorker);
212 
213  return (Archive *) AH;
214 }
215 
216 /* Open an existing archive */
217 /* Public */
218 Archive *
219 OpenArchive(const char *FileSpec, const ArchiveFormat fmt)
220 {
221  ArchiveHandle *AH = _allocAH(FileSpec, fmt, 0, true, archModeRead, setupRestoreWorker);
222 
223  return (Archive *) AH;
224 }
225 
226 /* Public */
227 void
229 {
230  int res = 0;
231  ArchiveHandle *AH = (ArchiveHandle *) AHX;
232 
233  (*AH->ClosePtr) (AH);
234 
235  /* Close the output */
236  if (AH->gzOut)
237  res = GZCLOSE(AH->OF);
238  else if (AH->OF != stdout)
239  res = fclose(AH->OF);
240 
241  if (res != 0)
242  exit_horribly(modulename, "could not close output file: %s\n",
243  strerror(errno));
244 }
245 
246 /* Public */
247 void
249 {
250  /* Caller can omit dump options, in which case we synthesize them */
251  if (dopt == NULL && ropt != NULL)
252  dopt = dumpOptionsFromRestoreOptions(ropt);
253 
254  /* Save options for later access */
255  AH->dopt = dopt;
256  AH->ropt = ropt;
257 }
258 
259 /* Public */
260 void
262 {
263  ArchiveHandle *AH = (ArchiveHandle *) AHX;
264  RestoreOptions *ropt = AH->public.ropt;
265  TocEntry *te;
266  teSection curSection;
267 
268  /* Decide which TOC entries will be dumped/restored, and mark them */
269  curSection = SECTION_PRE_DATA;
270  for (te = AH->toc->next; te != AH->toc; te = te->next)
271  {
272  /*
273  * When writing an archive, we also take this opportunity to check
274  * that we have generated the entries in a sane order that respects
275  * the section divisions. When reading, don't complain, since buggy
276  * old versions of pg_dump might generate out-of-order archives.
277  */
278  if (AH->mode != archModeRead)
279  {
280  switch (te->section)
281  {
282  case SECTION_NONE:
283  /* ok to be anywhere */
284  break;
285  case SECTION_PRE_DATA:
286  if (curSection != SECTION_PRE_DATA)
288  "WARNING: archive items not in correct section order\n");
289  break;
290  case SECTION_DATA:
291  if (curSection == SECTION_POST_DATA)
293  "WARNING: archive items not in correct section order\n");
294  break;
295  case SECTION_POST_DATA:
296  /* ok no matter which section we were in */
297  break;
298  default:
299  exit_horribly(modulename, "unexpected section code %d\n",
300  (int) te->section);
301  break;
302  }
303  }
304 
305  if (te->section != SECTION_NONE)
306  curSection = te->section;
307 
308  te->reqs = _tocEntryRequired(te, curSection, ropt);
309  }
310 
311  /* Enforce strict names checking */
312  if (ropt->strict_names)
313  StrictNamesCheck(ropt);
314 }
315 
316 /* Public */
317 void
319 {
320  ArchiveHandle *AH = (ArchiveHandle *) AHX;
321  RestoreOptions *ropt = AH->public.ropt;
322  bool parallel_mode;
323  TocEntry *te;
324  OutputContext sav;
325 
327 
328  /*
329  * Check for nonsensical option combinations.
330  *
331  * -C is not compatible with -1, because we can't create a database inside
332  * a transaction block.
333  */
334  if (ropt->createDB && ropt->single_txn)
335  exit_horribly(modulename, "-C and -1 are incompatible options\n");
336 
337  /*
338  * If we're going to do parallel restore, there are some restrictions.
339  */
340  parallel_mode = (AH->public.numWorkers > 1 && ropt->useDB);
341  if (parallel_mode)
342  {
343  /* We haven't got round to making this work for all archive formats */
344  if (AH->ClonePtr == NULL || AH->ReopenPtr == NULL)
345  exit_horribly(modulename, "parallel restore is not supported with this archive file format\n");
346 
347  /* Doesn't work if the archive represents dependencies as OIDs */
348  if (AH->version < K_VERS_1_8)
349  exit_horribly(modulename, "parallel restore is not supported with archives made by pre-8.0 pg_dump\n");
350 
351  /*
352  * It's also not gonna work if we can't reopen the input file, so
353  * let's try that immediately.
354  */
355  (AH->ReopenPtr) (AH);
356  }
357 
358  /*
359  * Make sure we won't need (de)compression we haven't got
360  */
361 #ifndef HAVE_LIBZ
362  if (AH->compression != 0 && AH->PrintTocDataPtr !=NULL)
363  {
364  for (te = AH->toc->next; te != AH->toc; te = te->next)
365  {
366  if (te->hadDumper && (te->reqs & REQ_DATA) != 0)
367  exit_horribly(modulename, "cannot restore from compressed archive (compression not supported in this installation)\n");
368  }
369  }
370 #endif
371 
372  /*
373  * Prepare index arrays, so we can assume we have them throughout restore.
374  * It's possible we already did this, though.
375  */
376  if (AH->tocsByDumpId == NULL)
378 
379  /*
380  * If we're using a DB connection, then connect it.
381  */
382  if (ropt->useDB)
383  {
384  ahlog(AH, 1, "connecting to database for restore\n");
385  if (AH->version < K_VERS_1_3)
386  exit_horribly(modulename, "direct database connections are not supported in pre-1.3 archives\n");
387 
388  /*
389  * We don't want to guess at whether the dump will successfully
390  * restore; allow the attempt regardless of the version of the restore
391  * target.
392  */
393  AHX->minRemoteVersion = 0;
394  AHX->maxRemoteVersion = 9999999;
395 
396  ConnectDatabase(AHX, ropt->dbname,
397  ropt->pghost, ropt->pgport, ropt->username,
398  ropt->promptPassword);
399 
400  /*
401  * If we're talking to the DB directly, don't send comments since they
402  * obscure SQL when displaying errors
403  */
404  AH->noTocComments = 1;
405  }
406 
407  /*
408  * Work out if we have an implied data-only restore. This can happen if
409  * the dump was data only or if the user has used a toc list to exclude
410  * all of the schema data. All we do is look for schema entries - if none
411  * are found then we set the dataOnly flag.
412  *
413  * We could scan for wanted TABLE entries, but that is not the same as
414  * dataOnly. At this stage, it seems unnecessary (6-Mar-2001).
415  */
416  if (!ropt->dataOnly)
417  {
418  int impliedDataOnly = 1;
419 
420  for (te = AH->toc->next; te != AH->toc; te = te->next)
421  {
422  if ((te->reqs & REQ_SCHEMA) != 0)
423  { /* It's schema, and it's wanted */
424  impliedDataOnly = 0;
425  break;
426  }
427  }
428  if (impliedDataOnly)
429  {
430  ropt->dataOnly = impliedDataOnly;
431  ahlog(AH, 1, "implied data-only restore\n");
432  }
433  }
434 
435  /*
436  * Setup the output file if necessary.
437  */
438  sav = SaveOutput(AH);
439  if (ropt->filename || ropt->compression)
440  SetOutput(AH, ropt->filename, ropt->compression);
441 
442  ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n");
443 
444  if (AH->archiveRemoteVersion)
445  ahprintf(AH, "-- Dumped from database version %s\n",
447  if (AH->archiveDumpVersion)
448  ahprintf(AH, "-- Dumped by pg_dump version %s\n",
449  AH->archiveDumpVersion);
450 
451  ahprintf(AH, "\n");
452 
453  if (AH->public.verbose)
454  dumpTimestamp(AH, "Started on", AH->createDate);
455 
456  if (ropt->single_txn)
457  {
458  if (AH->connection)
459  StartTransaction(AHX);
460  else
461  ahprintf(AH, "BEGIN;\n\n");
462  }
463 
464  /*
465  * Establish important parameter values right away.
466  */
468 
469  AH->stage = STAGE_PROCESSING;
470 
471  /*
472  * Drop the items at the start, in reverse order
473  */
474  if (ropt->dropSchema)
475  {
476  for (te = AH->toc->prev; te != AH->toc; te = te->prev)
477  {
478  AH->currentTE = te;
479 
480  /*
481  * In createDB mode, issue a DROP *only* for the database as a
482  * whole. Issuing drops against anything else would be wrong,
483  * because at this point we're connected to the wrong database.
484  * Conversely, if we're not in createDB mode, we'd better not
485  * issue a DROP against the database at all.
486  */
487  if (ropt->createDB)
488  {
489  if (strcmp(te->desc, "DATABASE") != 0)
490  continue;
491  }
492  else
493  {
494  if (strcmp(te->desc, "DATABASE") == 0)
495  continue;
496  }
497 
498  /* Otherwise, drop anything that's selected and has a dropStmt */
499  if (((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0) && te->dropStmt)
500  {
501  ahlog(AH, 1, "dropping %s %s\n", te->desc, te->tag);
502  /* Select owner and schema as necessary */
503  _becomeOwner(AH, te);
504  _selectOutputSchema(AH, te->namespace);
505 
506  /*
507  * Now emit the DROP command, if the object has one. Note we
508  * don't necessarily emit it verbatim; at this point we add an
509  * appropriate IF EXISTS clause, if the user requested it.
510  */
511  if (*te->dropStmt != '\0')
512  {
513  if (!ropt->if_exists)
514  {
515  /* No --if-exists? Then just use the original */
516  ahprintf(AH, "%s", te->dropStmt);
517  }
518  else
519  {
520  /*
521  * Inject an appropriate spelling of "if exists". For
522  * large objects, we have a separate routine that
523  * knows how to do it, without depending on
524  * te->dropStmt; use that. For other objects we need
525  * to parse the command.
526  */
527  if (strncmp(te->desc, "BLOB", 4) == 0)
528  {
529  DropBlobIfExists(AH, te->catalogId.oid);
530  }
531  else
532  {
533  char *dropStmt = pg_strdup(te->dropStmt);
534  char *dropStmtOrig = dropStmt;
535  PQExpBuffer ftStmt = createPQExpBuffer();
536 
537  /*
538  * Need to inject IF EXISTS clause after ALTER
539  * TABLE part in ALTER TABLE .. DROP statement
540  */
541  if (strncmp(dropStmt, "ALTER TABLE", 11) == 0)
542  {
543  appendPQExpBuffer(ftStmt,
544  "ALTER TABLE IF EXISTS");
545  dropStmt = dropStmt + 11;
546  }
547 
548  /*
549  * ALTER TABLE..ALTER COLUMN..DROP DEFAULT does
550  * not support the IF EXISTS clause, and therefore
551  * we simply emit the original command for DEFAULT
552  * objects (modulo the adjustment made above).
553  *
554  * If we used CREATE OR REPLACE VIEW as a means of
555  * quasi-dropping an ON SELECT rule, that should
556  * be emitted unchanged as well.
557  *
558  * For other object types, we need to extract the
559  * first part of the DROP which includes the
560  * object type. Most of the time this matches
561  * te->desc, so search for that; however for the
562  * different kinds of CONSTRAINTs, we know to
563  * search for hardcoded "DROP CONSTRAINT" instead.
564  */
565  if (strcmp(te->desc, "DEFAULT") == 0 ||
566  strncmp(dropStmt, "CREATE OR REPLACE VIEW", 22) == 0)
567  appendPQExpBufferStr(ftStmt, dropStmt);
568  else
569  {
570  char buffer[40];
571  char *mark;
572 
573  if (strcmp(te->desc, "CONSTRAINT") == 0 ||
574  strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
575  strcmp(te->desc, "FK CONSTRAINT") == 0)
576  strcpy(buffer, "DROP CONSTRAINT");
577  else
578  snprintf(buffer, sizeof(buffer), "DROP %s",
579  te->desc);
580 
581  mark = strstr(dropStmt, buffer);
582 
583  if (mark)
584  {
585  *mark = '\0';
586  appendPQExpBuffer(ftStmt, "%s%s IF EXISTS%s",
587  dropStmt, buffer,
588  mark + strlen(buffer));
589  }
590  else
591  {
592  /* complain and emit unmodified command */
594  "WARNING: could not find where to insert IF EXISTS in statement \"%s\"\n",
595  dropStmtOrig);
596  appendPQExpBufferStr(ftStmt, dropStmt);
597  }
598  }
599 
600  ahprintf(AH, "%s", ftStmt->data);
601 
602  destroyPQExpBuffer(ftStmt);
603  pg_free(dropStmtOrig);
604  }
605  }
606  }
607  }
608  }
609 
610  /*
611  * _selectOutputSchema may have set currSchema to reflect the effect
612  * of a "SET search_path" command it emitted. However, by now we may
613  * have dropped that schema; or it might not have existed in the first
614  * place. In either case the effective value of search_path will not
615  * be what we think. Forcibly reset currSchema so that we will
616  * re-establish the search_path setting when needed (after creating
617  * the schema).
618  *
619  * If we treated users as pg_dump'able objects then we'd need to reset
620  * currUser here too.
621  */
622  if (AH->currSchema)
623  free(AH->currSchema);
624  AH->currSchema = NULL;
625  }
626 
627  /*
628  * In serial mode, we now process each non-ACL TOC entry.
629  *
630  * In parallel mode, turn control over to the parallel-restore logic.
631  */
632  if (parallel_mode)
633  {
634  ParallelState *pstate;
635  TocEntry pending_list;
636 
637  par_list_header_init(&pending_list);
638 
639  /* This runs PRE_DATA items and then disconnects from the database */
641  Assert(AH->connection == NULL);
642 
643  /* ParallelBackupStart() will actually fork the processes */
644  pstate = ParallelBackupStart(AH);
645  restore_toc_entries_parallel(AH, pstate, &pending_list);
646  ParallelBackupEnd(AH, pstate);
647 
648  /* reconnect the master and see if we missed something */
649  restore_toc_entries_postfork(AH, &pending_list);
650  Assert(AH->connection != NULL);
651  }
652  else
653  {
654  for (te = AH->toc->next; te != AH->toc; te = te->next)
655  (void) restore_toc_entry(AH, te, false);
656  }
657 
658  /*
659  * Scan TOC again to output ownership commands and ACLs
660  */
661  for (te = AH->toc->next; te != AH->toc; te = te->next)
662  {
663  AH->currentTE = te;
664 
665  /* Both schema and data objects might now have ownership/ACLs */
666  if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0)
667  {
668  /* Show namespace if available */
669  if (te->namespace)
670  ahlog(AH, 1, "setting owner and privileges for %s \"%s.%s\"\n",
671  te->desc, te->namespace, te->tag);
672  else
673  ahlog(AH, 1, "setting owner and privileges for %s \"%s\"\n",
674  te->desc, te->tag);
675  _printTocEntry(AH, te, false, true);
676  }
677  }
678 
679  if (ropt->single_txn)
680  {
681  if (AH->connection)
682  CommitTransaction(AHX);
683  else
684  ahprintf(AH, "COMMIT;\n\n");
685  }
686 
687  if (AH->public.verbose)
688  dumpTimestamp(AH, "Completed on", time(NULL));
689 
690  ahprintf(AH, "--\n-- PostgreSQL database dump complete\n--\n\n");
691 
692  /*
693  * Clean up & we're done.
694  */
695  AH->stage = STAGE_FINALIZING;
696 
697  if (ropt->filename || ropt->compression)
698  RestoreOutput(AH, sav);
699 
700  if (ropt->useDB)
702 }
703 
704 /*
705  * Restore a single TOC item. Used in both parallel and non-parallel restore;
706  * is_parallel is true if we are in a worker child process.
707  *
708  * Returns 0 normally, but WORKER_CREATE_DONE or WORKER_INHIBIT_DATA if
709  * the parallel parent has to make the corresponding status update.
710  */
711 static int
712 restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)
713 {
714  RestoreOptions *ropt = AH->public.ropt;
715  int status = WORKER_OK;
716  teReqs reqs;
717  bool defnDumped;
718 
719  AH->currentTE = te;
720 
721  /* Work out what, if anything, we want from this entry */
722  if (_tocEntryIsACL(te))
723  reqs = 0; /* ACLs are never restored here */
724  else
725  reqs = te->reqs;
726 
727  /*
728  * Ignore DATABASE entry unless we should create it. We must check this
729  * here, not in _tocEntryRequired, because the createDB option should not
730  * affect emitting a DATABASE entry to an archive file.
731  */
732  if (!ropt->createDB && strcmp(te->desc, "DATABASE") == 0)
733  reqs = 0;
734 
735  /* Dump any relevant dump warnings to stderr */
736  if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0)
737  {
738  if (!ropt->dataOnly && te->defn != NULL && strlen(te->defn) != 0)
739  write_msg(modulename, "warning from original dump file: %s\n", te->defn);
740  else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0)
741  write_msg(modulename, "warning from original dump file: %s\n", te->copyStmt);
742  }
743 
744  defnDumped = false;
745 
746  if ((reqs & REQ_SCHEMA) != 0) /* We want the schema */
747  {
748  /* Show namespace if available */
749  if (te->namespace)
750  ahlog(AH, 1, "creating %s \"%s.%s\"\n",
751  te->desc, te->namespace, te->tag);
752  else
753  ahlog(AH, 1, "creating %s \"%s\"\n", te->desc, te->tag);
754 
755 
756  _printTocEntry(AH, te, false, false);
757  defnDumped = true;
758 
759  if (strcmp(te->desc, "TABLE") == 0)
760  {
761  if (AH->lastErrorTE == te)
762  {
763  /*
764  * We failed to create the table. If
765  * --no-data-for-failed-tables was given, mark the
766  * corresponding TABLE DATA to be ignored.
767  *
768  * In the parallel case this must be done in the parent, so we
769  * just set the return value.
770  */
771  if (ropt->noDataForFailedTables)
772  {
773  if (is_parallel)
774  status = WORKER_INHIBIT_DATA;
775  else
777  }
778  }
779  else
780  {
781  /*
782  * We created the table successfully. Mark the corresponding
783  * TABLE DATA for possible truncation.
784  *
785  * In the parallel case this must be done in the parent, so we
786  * just set the return value.
787  */
788  if (is_parallel)
789  status = WORKER_CREATE_DONE;
790  else
791  mark_create_done(AH, te);
792  }
793  }
794 
795  /* If we created a DB, connect to it... */
796  if (strcmp(te->desc, "DATABASE") == 0)
797  {
799 
800  initPQExpBuffer(&connstr);
801  appendPQExpBufferStr(&connstr, "dbname=");
802  appendConnStrVal(&connstr, te->tag);
803  /* Abandon struct, but keep its buffer until process exit. */
804 
805  ahlog(AH, 1, "connecting to new database \"%s\"\n", te->tag);
806  _reconnectToDB(AH, te->tag);
807  ropt->dbname = connstr.data;
808  }
809  }
810 
811  /*
812  * If we have a data component, then process it
813  */
814  if ((reqs & REQ_DATA) != 0)
815  {
816  /*
817  * hadDumper will be set if there is genuine data component for this
818  * node. Otherwise, we need to check the defn field for statements
819  * that need to be executed in data-only restores.
820  */
821  if (te->hadDumper)
822  {
823  /*
824  * If we can output the data, then restore it.
825  */
826  if (AH->PrintTocDataPtr !=NULL)
827  {
828  _printTocEntry(AH, te, true, false);
829 
830  if (strcmp(te->desc, "BLOBS") == 0 ||
831  strcmp(te->desc, "BLOB COMMENTS") == 0)
832  {
833  ahlog(AH, 1, "processing %s\n", te->desc);
834 
835  _selectOutputSchema(AH, "pg_catalog");
836 
837  /* Send BLOB COMMENTS data to ExecuteSimpleCommands() */
838  if (strcmp(te->desc, "BLOB COMMENTS") == 0)
840 
841  (*AH->PrintTocDataPtr) (AH, te);
842 
844  }
845  else
846  {
848 
849  /* Select owner and schema as necessary */
850  _becomeOwner(AH, te);
851  _selectOutputSchema(AH, te->namespace);
852 
853  ahlog(AH, 1, "processing data for table \"%s.%s\"\n",
854  te->namespace, te->tag);
855 
856  /*
857  * In parallel restore, if we created the table earlier in
858  * the run then we wrap the COPY in a transaction and
859  * precede it with a TRUNCATE. If archiving is not on
860  * this prevents WAL-logging the COPY. This obtains a
861  * speedup similar to that from using single_txn mode in
862  * non-parallel restores.
863  */
864  if (is_parallel && te->created)
865  {
866  /*
867  * Parallel restore is always talking directly to a
868  * server, so no need to see if we should issue BEGIN.
869  */
870  StartTransaction(&AH->public);
871 
872  /*
873  * If the server version is >= 8.4, make sure we issue
874  * TRUNCATE with ONLY so that child tables are not
875  * wiped.
876  */
877  ahprintf(AH, "TRUNCATE TABLE %s%s;\n\n",
878  (PQserverVersion(AH->connection) >= 80400 ?
879  "ONLY " : ""),
880  fmtId(te->tag));
881  }
882 
883  /*
884  * If we have a copy statement, use it.
885  */
886  if (te->copyStmt && strlen(te->copyStmt) > 0)
887  {
888  ahprintf(AH, "%s", te->copyStmt);
890  }
891  else
893 
894  (*AH->PrintTocDataPtr) (AH, te);
895 
896  /*
897  * Terminate COPY if needed.
898  */
899  if (AH->outputKind == OUTPUT_COPYDATA &&
900  RestoringToDB(AH))
901  EndDBCopyMode(&AH->public, te->tag);
903 
904  /* close out the transaction started above */
905  if (is_parallel && te->created)
907 
909  }
910  }
911  }
912  else if (!defnDumped)
913  {
914  /* If we haven't already dumped the defn part, do so now */
915  ahlog(AH, 1, "executing %s %s\n", te->desc, te->tag);
916  _printTocEntry(AH, te, false, false);
917  }
918  }
919 
920  if (AH->public.n_errors > 0 && status == WORKER_OK)
921  status = WORKER_IGNORED_ERRORS;
922 
923  return status;
924 }
925 
926 /*
927  * Allocate a new RestoreOptions block.
928  * This is mainly so we can initialize it, but also for future expansion,
929  */
932 {
933  RestoreOptions *opts;
934 
935  opts = (RestoreOptions *) pg_malloc0(sizeof(RestoreOptions));
936 
937  /* set any fields that shouldn't default to zeroes */
938  opts->format = archUnknown;
939  opts->promptPassword = TRI_DEFAULT;
941 
942  return opts;
943 }
944 
945 static void
947 {
948  RestoreOptions *ropt = AH->public.ropt;
949 
950  /* This hack is only needed in a data-only restore */
951  if (!ropt->dataOnly || !ropt->disable_triggers)
952  return;
953 
954  ahlog(AH, 1, "disabling triggers for %s\n", te->tag);
955 
956  /*
957  * Become superuser if possible, since they are the only ones who can
958  * disable constraint triggers. If -S was not given, assume the initial
959  * user identity is a superuser. (XXX would it be better to become the
960  * table owner?)
961  */
962  _becomeUser(AH, ropt->superuser);
963 
964  /*
965  * Disable them.
966  */
967  _selectOutputSchema(AH, te->namespace);
968 
969  ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n",
970  fmtId(te->tag));
971 }
972 
973 static void
975 {
976  RestoreOptions *ropt = AH->public.ropt;
977 
978  /* This hack is only needed in a data-only restore */
979  if (!ropt->dataOnly || !ropt->disable_triggers)
980  return;
981 
982  ahlog(AH, 1, "enabling triggers for %s\n", te->tag);
983 
984  /*
985  * Become superuser if possible, since they are the only ones who can
986  * disable constraint triggers. If -S was not given, assume the initial
987  * user identity is a superuser. (XXX would it be better to become the
988  * table owner?)
989  */
990  _becomeUser(AH, ropt->superuser);
991 
992  /*
993  * Enable them.
994  */
995  _selectOutputSchema(AH, te->namespace);
996 
997  ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n",
998  fmtId(te->tag));
999 }
1000 
1001 /*
1002  * This is a routine that is part of the dumper interface, hence the 'Archive*' parameter.
1003  */
1004 
1005 /* Public */
1006 void
1007 WriteData(Archive *AHX, const void *data, size_t dLen)
1008 {
1009  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1010 
1011  if (!AH->currToc)
1012  exit_horribly(modulename, "internal error -- WriteData cannot be called outside the context of a DataDumper routine\n");
1013 
1014  (*AH->WriteDataPtr) (AH, data, dLen);
1015 
1016  return;
1017 }
1018 
1019 /*
1020  * Create a new TOC entry. The TOC was designed as a TOC, but is now the
1021  * repository for all metadata. But the name has stuck.
1022  */
1023 
1024 /* Public */
1025 void
1027  CatalogId catalogId, DumpId dumpId,
1028  const char *tag,
1029  const char *namespace,
1030  const char *tablespace,
1031  const char *owner, bool withOids,
1032  const char *desc, teSection section,
1033  const char *defn,
1034  const char *dropStmt, const char *copyStmt,
1035  const DumpId *deps, int nDeps,
1036  DataDumperPtr dumpFn, void *dumpArg)
1037 {
1038  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1039  TocEntry *newToc;
1040 
1041  newToc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
1042 
1043  AH->tocCount++;
1044  if (dumpId > AH->maxDumpId)
1045  AH->maxDumpId = dumpId;
1046 
1047  newToc->prev = AH->toc->prev;
1048  newToc->next = AH->toc;
1049  AH->toc->prev->next = newToc;
1050  AH->toc->prev = newToc;
1051 
1052  newToc->catalogId = catalogId;
1053  newToc->dumpId = dumpId;
1054  newToc->section = section;
1055 
1056  newToc->tag = pg_strdup(tag);
1057  newToc->namespace = namespace ? pg_strdup(namespace) : NULL;
1058  newToc->tablespace = tablespace ? pg_strdup(tablespace) : NULL;
1059  newToc->owner = pg_strdup(owner);
1060  newToc->withOids = withOids;
1061  newToc->desc = pg_strdup(desc);
1062  newToc->defn = pg_strdup(defn);
1063  newToc->dropStmt = pg_strdup(dropStmt);
1064  newToc->copyStmt = copyStmt ? pg_strdup(copyStmt) : NULL;
1065 
1066  if (nDeps > 0)
1067  {
1068  newToc->dependencies = (DumpId *) pg_malloc(nDeps * sizeof(DumpId));
1069  memcpy(newToc->dependencies, deps, nDeps * sizeof(DumpId));
1070  newToc->nDeps = nDeps;
1071  }
1072  else
1073  {
1074  newToc->dependencies = NULL;
1075  newToc->nDeps = 0;
1076  }
1077 
1078  newToc->dataDumper = dumpFn;
1079  newToc->dataDumperArg = dumpArg;
1080  newToc->hadDumper = dumpFn ? true : false;
1081 
1082  newToc->formatData = NULL;
1083 
1084  if (AH->ArchiveEntryPtr !=NULL)
1085  (*AH->ArchiveEntryPtr) (AH, newToc);
1086 }
1087 
1088 /* Public */
1089 void
1091 {
1092  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1093  RestoreOptions *ropt = AH->public.ropt;
1094  TocEntry *te;
1095  teSection curSection;
1096  OutputContext sav;
1097  const char *fmtName;
1098  char stamp_str[64];
1099 
1100  sav = SaveOutput(AH);
1101  if (ropt->filename)
1102  SetOutput(AH, ropt->filename, 0 /* no compression */ );
1103 
1104  if (strftime(stamp_str, sizeof(stamp_str), PGDUMP_STRFTIME_FMT,
1105  localtime(&AH->createDate)) == 0)
1106  strcpy(stamp_str, "[unknown]");
1107 
1108  ahprintf(AH, ";\n; Archive created at %s\n", stamp_str);
1109  ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %d\n",
1111  AH->tocCount, AH->compression);
1112 
1113  switch (AH->format)
1114  {
1115  case archCustom:
1116  fmtName = "CUSTOM";
1117  break;
1118  case archDirectory:
1119  fmtName = "DIRECTORY";
1120  break;
1121  case archTar:
1122  fmtName = "TAR";
1123  break;
1124  default:
1125  fmtName = "UNKNOWN";
1126  }
1127 
1128  ahprintf(AH, "; Dump Version: %d.%d-%d\n",
1130  ahprintf(AH, "; Format: %s\n", fmtName);
1131  ahprintf(AH, "; Integer: %d bytes\n", (int) AH->intSize);
1132  ahprintf(AH, "; Offset: %d bytes\n", (int) AH->offSize);
1133  if (AH->archiveRemoteVersion)
1134  ahprintf(AH, "; Dumped from database version: %s\n",
1135  AH->archiveRemoteVersion);
1136  if (AH->archiveDumpVersion)
1137  ahprintf(AH, "; Dumped by pg_dump version: %s\n",
1138  AH->archiveDumpVersion);
1139 
1140  ahprintf(AH, ";\n;\n; Selected TOC Entries:\n;\n");
1141 
1142  curSection = SECTION_PRE_DATA;
1143  for (te = AH->toc->next; te != AH->toc; te = te->next)
1144  {
1145  if (te->section != SECTION_NONE)
1146  curSection = te->section;
1147  if (ropt->verbose ||
1148  (_tocEntryRequired(te, curSection, ropt) & (REQ_SCHEMA | REQ_DATA)) != 0)
1149  {
1150  char *sanitized_name;
1151  char *sanitized_schema;
1152  char *sanitized_owner;
1153 
1154  /*
1155  * As in _printTocEntry(), sanitize strings that might contain
1156  * newlines, to ensure that each logical output line is in fact
1157  * one physical output line. This prevents confusion when the
1158  * file is read by "pg_restore -L". Note that we currently don't
1159  * bother to quote names, meaning that the name fields aren't
1160  * automatically parseable. "pg_restore -L" doesn't care because
1161  * it only examines the dumpId field, but someday we might want to
1162  * try harder.
1163  */
1164  sanitized_name = replace_line_endings(te->tag);
1165  if (te->namespace)
1166  sanitized_schema = replace_line_endings(te->namespace);
1167  else
1168  sanitized_schema = pg_strdup("-");
1169  sanitized_owner = replace_line_endings(te->owner);
1170 
1171  ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
1172  te->catalogId.tableoid, te->catalogId.oid,
1173  te->desc, sanitized_schema, sanitized_name,
1174  sanitized_owner);
1175 
1176  free(sanitized_name);
1177  free(sanitized_schema);
1178  free(sanitized_owner);
1179  }
1180  if (ropt->verbose && te->nDeps > 0)
1181  {
1182  int i;
1183 
1184  ahprintf(AH, ";\tdepends on:");
1185  for (i = 0; i < te->nDeps; i++)
1186  ahprintf(AH, " %d", te->dependencies[i]);
1187  ahprintf(AH, "\n");
1188  }
1189  }
1190 
1191  /* Enforce strict names checking */
1192  if (ropt->strict_names)
1193  StrictNamesCheck(ropt);
1194 
1195  if (ropt->filename)
1196  RestoreOutput(AH, sav);
1197 }
1198 
1199 /***********
1200  * BLOB Archival
1201  ***********/
1202 
1203 /* Called by a dumper to signal start of a BLOB */
1204 int
1206 {
1207  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1208 
1209  if (!AH->StartBlobPtr)
1210  exit_horribly(modulename, "large-object output not supported in chosen format\n");
1211 
1212  (*AH->StartBlobPtr) (AH, AH->currToc, oid);
1213 
1214  return 1;
1215 }
1216 
1217 /* Called by a dumper to signal end of a BLOB */
1218 int
1219 EndBlob(Archive *AHX, Oid oid)
1220 {
1221  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1222 
1223  if (AH->EndBlobPtr)
1224  (*AH->EndBlobPtr) (AH, AH->currToc, oid);
1225 
1226  return 1;
1227 }
1228 
1229 /**********
1230  * BLOB Restoration
1231  **********/
1232 
1233 /*
1234  * Called by a format handler before any blobs are restored
1235  */
1236 void
1238 {
1239  RestoreOptions *ropt = AH->public.ropt;
1240 
1241  if (!ropt->single_txn)
1242  {
1243  if (AH->connection)
1244  StartTransaction(&AH->public);
1245  else
1246  ahprintf(AH, "BEGIN;\n\n");
1247  }
1248 
1249  AH->blobCount = 0;
1250 }
1251 
1252 /*
1253  * Called by a format handler after all blobs are restored
1254  */
1255 void
1257 {
1258  RestoreOptions *ropt = AH->public.ropt;
1259 
1260  if (!ropt->single_txn)
1261  {
1262  if (AH->connection)
1263  CommitTransaction(&AH->public);
1264  else
1265  ahprintf(AH, "COMMIT;\n\n");
1266  }
1267 
1268  ahlog(AH, 1, ngettext("restored %d large object\n",
1269  "restored %d large objects\n",
1270  AH->blobCount),
1271  AH->blobCount);
1272 }
1273 
1274 
1275 /*
1276  * Called by a format handler to initiate restoration of a blob
1277  */
1278 void
1279 StartRestoreBlob(ArchiveHandle *AH, Oid oid, bool drop)
1280 {
1281  bool old_blob_style = (AH->version < K_VERS_1_12);
1282  Oid loOid;
1283 
1284  AH->blobCount++;
1285 
1286  /* Initialize the LO Buffer */
1287  AH->lo_buf_used = 0;
1288 
1289  ahlog(AH, 1, "restoring large object with OID %u\n", oid);
1290 
1291  /* With an old archive we must do drop and create logic here */
1292  if (old_blob_style && drop)
1293  DropBlobIfExists(AH, oid);
1294 
1295  if (AH->connection)
1296  {
1297  if (old_blob_style)
1298  {
1299  loOid = lo_create(AH->connection, oid);
1300  if (loOid == 0 || loOid != oid)
1301  exit_horribly(modulename, "could not create large object %u: %s",
1302  oid, PQerrorMessage(AH->connection));
1303  }
1304  AH->loFd = lo_open(AH->connection, oid, INV_WRITE);
1305  if (AH->loFd == -1)
1306  exit_horribly(modulename, "could not open large object %u: %s",
1307  oid, PQerrorMessage(AH->connection));
1308  }
1309  else
1310  {
1311  if (old_blob_style)
1312  ahprintf(AH, "SELECT pg_catalog.lo_open(pg_catalog.lo_create('%u'), %d);\n",
1313  oid, INV_WRITE);
1314  else
1315  ahprintf(AH, "SELECT pg_catalog.lo_open('%u', %d);\n",
1316  oid, INV_WRITE);
1317  }
1318 
1319  AH->writingBlob = 1;
1320 }
1321 
1322 void
1324 {
1325  if (AH->lo_buf_used > 0)
1326  {
1327  /* Write remaining bytes from the LO buffer */
1328  dump_lo_buf(AH);
1329  }
1330 
1331  AH->writingBlob = 0;
1332 
1333  if (AH->connection)
1334  {
1335  lo_close(AH->connection, AH->loFd);
1336  AH->loFd = -1;
1337  }
1338  else
1339  {
1340  ahprintf(AH, "SELECT pg_catalog.lo_close(0);\n\n");
1341  }
1342 }
1343 
1344 /***********
1345  * Sorting and Reordering
1346  ***********/
1347 
1348 void
1350 {
1351  ArchiveHandle *AH = (ArchiveHandle *) AHX;
1352  RestoreOptions *ropt = AH->public.ropt;
1353  FILE *fh;
1354  char buf[100];
1355  bool incomplete_line;
1356 
1357  /* Allocate space for the 'wanted' array, and init it */
1358  ropt->idWanted = (bool *) pg_malloc(sizeof(bool) * AH->maxDumpId);
1359  memset(ropt->idWanted, 0, sizeof(bool) * AH->maxDumpId);
1360 
1361  /* Setup the file */
1362  fh = fopen(ropt->tocFile, PG_BINARY_R);
1363  if (!fh)
1364  exit_horribly(modulename, "could not open TOC file \"%s\": %s\n",
1365  ropt->tocFile, strerror(errno));
1366 
1367  incomplete_line = false;
1368  while (fgets(buf, sizeof(buf), fh) != NULL)
1369  {
1370  bool prev_incomplete_line = incomplete_line;
1371  int buflen;
1372  char *cmnt;
1373  char *endptr;
1374  DumpId id;
1375  TocEntry *te;
1376 
1377  /*
1378  * Some lines in the file might be longer than sizeof(buf). This is
1379  * no problem, since we only care about the leading numeric ID which
1380  * can be at most a few characters; but we have to skip continuation
1381  * bufferloads when processing a long line.
1382  */
1383  buflen = strlen(buf);
1384  if (buflen > 0 && buf[buflen - 1] == '\n')
1385  incomplete_line = false;
1386  else
1387  incomplete_line = true;
1388  if (prev_incomplete_line)
1389  continue;
1390 
1391  /* Truncate line at comment, if any */
1392  cmnt = strchr(buf, ';');
1393  if (cmnt != NULL)
1394  cmnt[0] = '\0';
1395 
1396  /* Ignore if all blank */
1397  if (strspn(buf, " \t\r\n") == strlen(buf))
1398  continue;
1399 
1400  /* Get an ID, check it's valid and not already seen */
1401  id = strtol(buf, &endptr, 10);
1402  if (endptr == buf || id <= 0 || id > AH->maxDumpId ||
1403  ropt->idWanted[id - 1])
1404  {
1405  write_msg(modulename, "WARNING: line ignored: %s\n", buf);
1406  continue;
1407  }
1408 
1409  /* Find TOC entry */
1410  te = getTocEntryByDumpId(AH, id);
1411  if (!te)
1412  exit_horribly(modulename, "could not find entry for ID %d\n",
1413  id);
1414 
1415  /* Mark it wanted */
1416  ropt->idWanted[id - 1] = true;
1417 
1418  /*
1419  * Move each item to the end of the list as it is selected, so that
1420  * they are placed in the desired order. Any unwanted items will end
1421  * up at the front of the list, which may seem unintuitive but it's
1422  * what we need. In an ordinary serial restore that makes no
1423  * difference, but in a parallel restore we need to mark unrestored
1424  * items' dependencies as satisfied before we start examining
1425  * restorable items. Otherwise they could have surprising
1426  * side-effects on the order in which restorable items actually get
1427  * restored.
1428  */
1429  _moveBefore(AH, AH->toc, te);
1430  }
1431 
1432  if (fclose(fh) != 0)
1433  exit_horribly(modulename, "could not close TOC file: %s\n",
1434  strerror(errno));
1435 }
1436 
1437 /**********************
1438  * 'Convenience functions that look like standard IO functions
1439  * for writing data when in dump mode.
1440  **********************/
1441 
1442 /* Public */
1443 void
1444 archputs(const char *s, Archive *AH)
1445 {
1446  WriteData(AH, s, strlen(s));
1447  return;
1448 }
1449 
1450 /* Public */
1451 int
1452 archprintf(Archive *AH, const char *fmt,...)
1453 {
1454  char *p;
1455  size_t len = 128; /* initial assumption about buffer size */
1456  size_t cnt;
1457 
1458  for (;;)
1459  {
1460  va_list args;
1461 
1462  /* Allocate work buffer. */
1463  p = (char *) pg_malloc(len);
1464 
1465  /* Try to format the data. */
1466  va_start(args, fmt);
1467  cnt = pvsnprintf(p, len, fmt, args);
1468  va_end(args);
1469 
1470  if (cnt < len)
1471  break; /* success */
1472 
1473  /* Release buffer and loop around to try again with larger len. */
1474  free(p);
1475  len = cnt;
1476  }
1477 
1478  WriteData(AH, p, cnt);
1479  free(p);
1480  return (int) cnt;
1481 }
1482 
1483 
1484 /*******************************
1485  * Stuff below here should be 'private' to the archiver routines
1486  *******************************/
1487 
1488 static void
1489 SetOutput(ArchiveHandle *AH, const char *filename, int compression)
1490 {
1491  int fn;
1492 
1493  if (filename)
1494  fn = -1;
1495  else if (AH->FH)
1496  fn = fileno(AH->FH);
1497  else if (AH->fSpec)
1498  {
1499  fn = -1;
1500  filename = AH->fSpec;
1501  }
1502  else
1503  fn = fileno(stdout);
1504 
1505  /* If compression explicitly requested, use gzopen */
1506 #ifdef HAVE_LIBZ
1507  if (compression != 0)
1508  {
1509  char fmode[10];
1510 
1511  /* Don't use PG_BINARY_x since this is zlib */
1512  sprintf(fmode, "wb%d", compression);
1513  if (fn >= 0)
1514  AH->OF = gzdopen(dup(fn), fmode);
1515  else
1516  AH->OF = gzopen(filename, fmode);
1517  AH->gzOut = 1;
1518  }
1519  else
1520 #endif
1521  { /* Use fopen */
1522  if (AH->mode == archModeAppend)
1523  {
1524  if (fn >= 0)
1525  AH->OF = fdopen(dup(fn), PG_BINARY_A);
1526  else
1527  AH->OF = fopen(filename, PG_BINARY_A);
1528  }
1529  else
1530  {
1531  if (fn >= 0)
1532  AH->OF = fdopen(dup(fn), PG_BINARY_W);
1533  else
1534  AH->OF = fopen(filename, PG_BINARY_W);
1535  }
1536  AH->gzOut = 0;
1537  }
1538 
1539  if (!AH->OF)
1540  {
1541  if (filename)
1542  exit_horribly(modulename, "could not open output file \"%s\": %s\n",
1543  filename, strerror(errno));
1544  else
1545  exit_horribly(modulename, "could not open output file: %s\n",
1546  strerror(errno));
1547  }
1548 }
1549 
1550 static OutputContext
1552 {
1553  OutputContext sav;
1554 
1555  sav.OF = AH->OF;
1556  sav.gzOut = AH->gzOut;
1557 
1558  return sav;
1559 }
1560 
1561 static void
1563 {
1564  int res;
1565 
1566  if (AH->gzOut)
1567  res = GZCLOSE(AH->OF);
1568  else
1569  res = fclose(AH->OF);
1570 
1571  if (res != 0)
1572  exit_horribly(modulename, "could not close output file: %s\n",
1573  strerror(errno));
1574 
1575  AH->gzOut = savedContext.gzOut;
1576  AH->OF = savedContext.OF;
1577 }
1578 
1579 
1580 
1581 /*
1582  * Print formatted text to the output file (usually stdout).
1583  */
1584 int
1585 ahprintf(ArchiveHandle *AH, const char *fmt,...)
1586 {
1587  char *p;
1588  size_t len = 128; /* initial assumption about buffer size */
1589  size_t cnt;
1590 
1591  for (;;)
1592  {
1593  va_list args;
1594 
1595  /* Allocate work buffer. */
1596  p = (char *) pg_malloc(len);
1597 
1598  /* Try to format the data. */
1599  va_start(args, fmt);
1600  cnt = pvsnprintf(p, len, fmt, args);
1601  va_end(args);
1602 
1603  if (cnt < len)
1604  break; /* success */
1605 
1606  /* Release buffer and loop around to try again with larger len. */
1607  free(p);
1608  len = cnt;
1609  }
1610 
1611  ahwrite(p, 1, cnt, AH);
1612  free(p);
1613  return (int) cnt;
1614 }
1615 
1616 void
1617 ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
1618 {
1619  va_list ap;
1620 
1621  if (AH->debugLevel < level && (!AH->public.verbose || level > 1))
1622  return;
1623 
1624  va_start(ap, fmt);
1625  vwrite_msg(NULL, fmt, ap);
1626  va_end(ap);
1627 }
1628 
1629 /*
1630  * Single place for logic which says 'We are restoring to a direct DB connection'.
1631  */
1632 static int
1634 {
1635  RestoreOptions *ropt = AH->public.ropt;
1636 
1637  return (ropt && ropt->useDB && AH->connection);
1638 }
1639 
1640 /*
1641  * Dump the current contents of the LO data buffer while writing a BLOB
1642  */
1643 static void
1645 {
1646  if (AH->connection)
1647  {
1648  size_t res;
1649 
1650  res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
1651  ahlog(AH, 5, ngettext("wrote %lu byte of large object data (result = %lu)\n",
1652  "wrote %lu bytes of large object data (result = %lu)\n",
1653  AH->lo_buf_used),
1654  (unsigned long) AH->lo_buf_used, (unsigned long) res);
1655  if (res != AH->lo_buf_used)
1657  "could not write to large object (result: %lu, expected: %lu)\n",
1658  (unsigned long) res, (unsigned long) AH->lo_buf_used);
1659  }
1660  else
1661  {
1663 
1665  (const unsigned char *) AH->lo_buf,
1666  AH->lo_buf_used,
1667  AH);
1668 
1669  /* Hack: turn off writingBlob so ahwrite doesn't recurse to here */
1670  AH->writingBlob = 0;
1671  ahprintf(AH, "SELECT pg_catalog.lowrite(0, %s);\n", buf->data);
1672  AH->writingBlob = 1;
1673 
1674  destroyPQExpBuffer(buf);
1675  }
1676  AH->lo_buf_used = 0;
1677 }
1678 
1679 
1680 /*
1681  * Write buffer to the output file (usually stdout). This is used for
1682  * outputting 'restore' scripts etc. It is even possible for an archive
1683  * format to create a custom output routine to 'fake' a restore if it
1684  * wants to generate a script (see TAR output).
1685  */
1686 void
1687 ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
1688 {
1689  int bytes_written = 0;
1690 
1691  if (AH->writingBlob)
1692  {
1693  size_t remaining = size * nmemb;
1694 
1695  while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1696  {
1697  size_t avail = AH->lo_buf_size - AH->lo_buf_used;
1698 
1699  memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
1700  ptr = (const void *) ((const char *) ptr + avail);
1701  remaining -= avail;
1702  AH->lo_buf_used += avail;
1703  dump_lo_buf(AH);
1704  }
1705 
1706  memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1707  AH->lo_buf_used += remaining;
1708 
1709  bytes_written = size * nmemb;
1710  }
1711  else if (AH->gzOut)
1712  bytes_written = GZWRITE(ptr, size, nmemb, AH->OF);
1713  else if (AH->CustomOutPtr)
1714  bytes_written = AH->CustomOutPtr (AH, ptr, size * nmemb);
1715 
1716  else
1717  {
1718  /*
1719  * If we're doing a restore, and it's direct to DB, and we're
1720  * connected then send it to the DB.
1721  */
1722  if (RestoringToDB(AH))
1723  bytes_written = ExecuteSqlCommandBuf(&AH->public, (const char *) ptr, size * nmemb);
1724  else
1725  bytes_written = fwrite(ptr, size, nmemb, AH->OF) * size;
1726  }
1727 
1728  if (bytes_written != size * nmemb)
1730 
1731  return;
1732 }
1733 
1734 /* on some error, we may decide to go on... */
1735 void
1737  const char *modulename, const char *fmt,...)
1738 {
1739  va_list ap;
1740 
1741  switch (AH->stage)
1742  {
1743 
1744  case STAGE_NONE:
1745  /* Do nothing special */
1746  break;
1747 
1748  case STAGE_INITIALIZING:
1749  if (AH->stage != AH->lastErrorStage)
1750  write_msg(modulename, "Error while INITIALIZING:\n");
1751  break;
1752 
1753  case STAGE_PROCESSING:
1754  if (AH->stage != AH->lastErrorStage)
1755  write_msg(modulename, "Error while PROCESSING TOC:\n");
1756  break;
1757 
1758  case STAGE_FINALIZING:
1759  if (AH->stage != AH->lastErrorStage)
1760  write_msg(modulename, "Error while FINALIZING:\n");
1761  break;
1762  }
1763  if (AH->currentTE != NULL && AH->currentTE != AH->lastErrorTE)
1764  {
1765  write_msg(modulename, "Error from TOC entry %d; %u %u %s %s %s\n",
1766  AH->currentTE->dumpId,
1768  AH->currentTE->desc, AH->currentTE->tag, AH->currentTE->owner);
1769  }
1770  AH->lastErrorStage = AH->stage;
1771  AH->lastErrorTE = AH->currentTE;
1772 
1773  va_start(ap, fmt);
1774  vwrite_msg(modulename, fmt, ap);
1775  va_end(ap);
1776 
1777  if (AH->public.exit_on_error)
1778  exit_nicely(1);
1779  else
1780  AH->public.n_errors++;
1781 }
1782 
1783 #ifdef NOT_USED
1784 
1785 static void
1786 _moveAfter(ArchiveHandle *AH, TocEntry *pos, TocEntry *te)
1787 {
1788  /* Unlink te from list */
1789  te->prev->next = te->next;
1790  te->next->prev = te->prev;
1791 
1792  /* and insert it after "pos" */
1793  te->prev = pos;
1794  te->next = pos->next;
1795  pos->next->prev = te;
1796  pos->next = te;
1797 }
1798 #endif
1799 
1800 static void
1802 {
1803  /* Unlink te from list */
1804  te->prev->next = te->next;
1805  te->next->prev = te->prev;
1806 
1807  /* and insert it before "pos" */
1808  te->prev = pos->prev;
1809  te->next = pos;
1810  pos->prev->next = te;
1811  pos->prev = te;
1812 }
1813 
1814 /*
1815  * Build index arrays for the TOC list
1816  *
1817  * This should be invoked only after we have created or read in all the TOC
1818  * items.
1819  *
1820  * The arrays are indexed by dump ID (so entry zero is unused). Note that the
1821  * array entries run only up to maxDumpId. We might see dependency dump IDs
1822  * beyond that (if the dump was partial); so always check the array bound
1823  * before trying to touch an array entry.
1824  */
1825 static void
1827 {
1828  DumpId maxDumpId = AH->maxDumpId;
1829  TocEntry *te;
1830 
1831  AH->tocsByDumpId = (TocEntry **) pg_malloc0((maxDumpId + 1) * sizeof(TocEntry *));
1832  AH->tableDataId = (DumpId *) pg_malloc0((maxDumpId + 1) * sizeof(DumpId));
1833 
1834  for (te = AH->toc->next; te != AH->toc; te = te->next)
1835  {
1836  /* this check is purely paranoia, maxDumpId should be correct */
1837  if (te->dumpId <= 0 || te->dumpId > maxDumpId)
1838  exit_horribly(modulename, "bad dumpId\n");
1839 
1840  /* tocsByDumpId indexes all TOCs by their dump ID */
1841  AH->tocsByDumpId[te->dumpId] = te;
1842 
1843  /*
1844  * tableDataId provides the TABLE DATA item's dump ID for each TABLE
1845  * TOC entry that has a DATA item. We compute this by reversing the
1846  * TABLE DATA item's dependency, knowing that a TABLE DATA item has
1847  * just one dependency and it is the TABLE item.
1848  */
1849  if (strcmp(te->desc, "TABLE DATA") == 0 && te->nDeps > 0)
1850  {
1851  DumpId tableId = te->dependencies[0];
1852 
1853  /*
1854  * The TABLE item might not have been in the archive, if this was
1855  * a data-only dump; but its dump ID should be less than its data
1856  * item's dump ID, so there should be a place for it in the array.
1857  */
1858  if (tableId <= 0 || tableId > maxDumpId)
1859  exit_horribly(modulename, "bad table dumpId for TABLE DATA item\n");
1860 
1861  AH->tableDataId[tableId] = te->dumpId;
1862  }
1863  }
1864 }
1865 
1866 TocEntry *
1868 {
1869  /* build index arrays if we didn't already */
1870  if (AH->tocsByDumpId == NULL)
1871  buildTocEntryArrays(AH);
1872 
1873  if (id > 0 && id <= AH->maxDumpId)
1874  return AH->tocsByDumpId[id];
1875 
1876  return NULL;
1877 }
1878 
1879 teReqs
1881 {
1882  TocEntry *te = getTocEntryByDumpId(AH, id);
1883 
1884  if (!te)
1885  return 0;
1886 
1887  return te->reqs;
1888 }
1889 
1890 size_t
1891 WriteOffset(ArchiveHandle *AH, pgoff_t o, int wasSet)
1892 {
1893  int off;
1894 
1895  /* Save the flag */
1896  (*AH->WriteBytePtr) (AH, wasSet);
1897 
1898  /* Write out pgoff_t smallest byte first, prevents endian mismatch */
1899  for (off = 0; off < sizeof(pgoff_t); off++)
1900  {
1901  (*AH->WriteBytePtr) (AH, o & 0xFF);
1902  o >>= 8;
1903  }
1904  return sizeof(pgoff_t) + 1;
1905 }
1906 
1907 int
1909 {
1910  int i;
1911  int off;
1912  int offsetFlg;
1913 
1914  /* Initialize to zero */
1915  *o = 0;
1916 
1917  /* Check for old version */
1918  if (AH->version < K_VERS_1_7)
1919  {
1920  /* Prior versions wrote offsets using WriteInt */
1921  i = ReadInt(AH);
1922  /* -1 means not set */
1923  if (i < 0)
1924  return K_OFFSET_POS_NOT_SET;
1925  else if (i == 0)
1926  return K_OFFSET_NO_DATA;
1927 
1928  /* Cast to pgoff_t because it was written as an int. */
1929  *o = (pgoff_t) i;
1930  return K_OFFSET_POS_SET;
1931  }
1932 
1933  /*
1934  * Read the flag indicating the state of the data pointer. Check if valid
1935  * and die if not.
1936  *
1937  * This used to be handled by a negative or zero pointer, now we use an
1938  * extra byte specifically for the state.
1939  */
1940  offsetFlg = (*AH->ReadBytePtr) (AH) & 0xFF;
1941 
1942  switch (offsetFlg)
1943  {
1944  case K_OFFSET_POS_NOT_SET:
1945  case K_OFFSET_NO_DATA:
1946  case K_OFFSET_POS_SET:
1947 
1948  break;
1949 
1950  default:
1951  exit_horribly(modulename, "unexpected data offset flag %d\n", offsetFlg);
1952  }
1953 
1954  /*
1955  * Read the bytes
1956  */
1957  for (off = 0; off < AH->offSize; off++)
1958  {
1959  if (off < sizeof(pgoff_t))
1960  *o |= ((pgoff_t) ((*AH->ReadBytePtr) (AH))) << (off * 8);
1961  else
1962  {
1963  if ((*AH->ReadBytePtr) (AH) != 0)
1964  exit_horribly(modulename, "file offset in dump file is too large\n");
1965  }
1966  }
1967 
1968  return offsetFlg;
1969 }
1970 
1971 size_t
1973 {
1974  int b;
1975 
1976  /*
1977  * This is a bit yucky, but I don't want to make the binary format very
1978  * dependent on representation, and not knowing much about it, I write out
1979  * a sign byte. If you change this, don't forget to change the file
1980  * version #, and modify readInt to read the new format AS WELL AS the old
1981  * formats.
1982  */
1983 
1984  /* SIGN byte */
1985  if (i < 0)
1986  {
1987  (*AH->WriteBytePtr) (AH, 1);
1988  i = -i;
1989  }
1990  else
1991  (*AH->WriteBytePtr) (AH, 0);
1992 
1993  for (b = 0; b < AH->intSize; b++)
1994  {
1995  (*AH->WriteBytePtr) (AH, i & 0xFF);
1996  i >>= 8;
1997  }
1998 
1999  return AH->intSize + 1;
2000 }
2001 
2002 int
2004 {
2005  int res = 0;
2006  int bv,
2007  b;
2008  int sign = 0; /* Default positive */
2009  int bitShift = 0;
2010 
2011  if (AH->version > K_VERS_1_0)
2012  /* Read a sign byte */
2013  sign = (*AH->ReadBytePtr) (AH);
2014 
2015  for (b = 0; b < AH->intSize; b++)
2016  {
2017  bv = (*AH->ReadBytePtr) (AH) & 0xFF;
2018  if (bv != 0)
2019  res = res + (bv << bitShift);
2020  bitShift += 8;
2021  }
2022 
2023  if (sign)
2024  res = -res;
2025 
2026  return res;
2027 }
2028 
2029 size_t
2030 WriteStr(ArchiveHandle *AH, const char *c)
2031 {
2032  size_t res;
2033 
2034  if (c)
2035  {
2036  int len = strlen(c);
2037 
2038  res = WriteInt(AH, len);
2039  (*AH->WriteBufPtr) (AH, c, len);
2040  res += len;
2041  }
2042  else
2043  res = WriteInt(AH, -1);
2044 
2045  return res;
2046 }
2047 
2048 char *
2050 {
2051  char *buf;
2052  int l;
2053 
2054  l = ReadInt(AH);
2055  if (l < 0)
2056  buf = NULL;
2057  else
2058  {
2059  buf = (char *) pg_malloc(l + 1);
2060  (*AH->ReadBufPtr) (AH, (void *) buf, l);
2061 
2062  buf[l] = '\0';
2063  }
2064 
2065  return buf;
2066 }
2067 
2068 static int
2070 {
2071  FILE *fh;
2072  char sig[6]; /* More than enough */
2073  size_t cnt;
2074  int wantClose = 0;
2075 
2076 #if 0
2077  write_msg(modulename, "attempting to ascertain archive format\n");
2078 #endif
2079 
2080  if (AH->lookahead)
2081  free(AH->lookahead);
2082 
2083  AH->lookaheadSize = 512;
2084  AH->lookahead = pg_malloc0(512);
2085  AH->lookaheadLen = 0;
2086  AH->lookaheadPos = 0;
2087 
2088  if (AH->fSpec)
2089  {
2090  struct stat st;
2091 
2092  wantClose = 1;
2093 
2094  /*
2095  * Check if the specified archive is a directory. If so, check if
2096  * there's a "toc.dat" (or "toc.dat.gz") file in it.
2097  */
2098  if (stat(AH->fSpec, &st) == 0 && S_ISDIR(st.st_mode))
2099  {
2100  char buf[MAXPGPATH];
2101 
2102  if (snprintf(buf, MAXPGPATH, "%s/toc.dat", AH->fSpec) >= MAXPGPATH)
2103  exit_horribly(modulename, "directory name too long: \"%s\"\n",
2104  AH->fSpec);
2105  if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
2106  {
2107  AH->format = archDirectory;
2108  return AH->format;
2109  }
2110 
2111 #ifdef HAVE_LIBZ
2112  if (snprintf(buf, MAXPGPATH, "%s/toc.dat.gz", AH->fSpec) >= MAXPGPATH)
2113  exit_horribly(modulename, "directory name too long: \"%s\"\n",
2114  AH->fSpec);
2115  if (stat(buf, &st) == 0 && S_ISREG(st.st_mode))
2116  {
2117  AH->format = archDirectory;
2118  return AH->format;
2119  }
2120 #endif
2121  exit_horribly(modulename, "directory \"%s\" does not appear to be a valid archive (\"toc.dat\" does not exist)\n",
2122  AH->fSpec);
2123  fh = NULL; /* keep compiler quiet */
2124  }
2125  else
2126  {
2127  fh = fopen(AH->fSpec, PG_BINARY_R);
2128  if (!fh)
2129  exit_horribly(modulename, "could not open input file \"%s\": %s\n",
2130  AH->fSpec, strerror(errno));
2131  }
2132  }
2133  else
2134  {
2135  fh = stdin;
2136  if (!fh)
2137  exit_horribly(modulename, "could not open input file: %s\n",
2138  strerror(errno));
2139  }
2140 
2141  if ((cnt = fread(sig, 1, 5, fh)) != 5)
2142  {
2143  if (ferror(fh))
2144  exit_horribly(modulename, "could not read input file: %s\n", strerror(errno));
2145  else
2146  exit_horribly(modulename, "input file is too short (read %lu, expected 5)\n",
2147  (unsigned long) cnt);
2148  }
2149 
2150  /* Save it, just in case we need it later */
2151  memcpy(&AH->lookahead[0], sig, 5);
2152  AH->lookaheadLen = 5;
2153 
2154  if (strncmp(sig, "PGDMP", 5) == 0)
2155  {
2156  int byteread;
2157  char vmaj,
2158  vmin,
2159  vrev;
2160 
2161  /*
2162  * Finish reading (most of) a custom-format header.
2163  *
2164  * NB: this code must agree with ReadHead().
2165  */
2166  if ((byteread = fgetc(fh)) == EOF)
2167  READ_ERROR_EXIT(fh);
2168 
2169  vmaj = byteread;
2170 
2171  if ((byteread = fgetc(fh)) == EOF)
2172  READ_ERROR_EXIT(fh);
2173 
2174  vmin = byteread;
2175 
2176  /* Save these too... */
2177  AH->lookahead[AH->lookaheadLen++] = vmaj;
2178  AH->lookahead[AH->lookaheadLen++] = vmin;
2179 
2180  /* Check header version; varies from V1.0 */
2181  if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */
2182  {
2183  if ((byteread = fgetc(fh)) == EOF)
2184  READ_ERROR_EXIT(fh);
2185 
2186  vrev = byteread;
2187  AH->lookahead[AH->lookaheadLen++] = vrev;
2188  }
2189  else
2190  vrev = 0;
2191 
2192  AH->version = MAKE_ARCHIVE_VERSION(vmaj, vmin, vrev);
2193 
2194  if ((AH->intSize = fgetc(fh)) == EOF)
2195  READ_ERROR_EXIT(fh);
2196  AH->lookahead[AH->lookaheadLen++] = AH->intSize;
2197 
2198  if (AH->version >= K_VERS_1_7)
2199  {
2200  if ((AH->offSize = fgetc(fh)) == EOF)
2201  READ_ERROR_EXIT(fh);
2202  AH->lookahead[AH->lookaheadLen++] = AH->offSize;
2203  }
2204  else
2205  AH->offSize = AH->intSize;
2206 
2207  if ((byteread = fgetc(fh)) == EOF)
2208  READ_ERROR_EXIT(fh);
2209 
2210  AH->format = byteread;
2211  AH->lookahead[AH->lookaheadLen++] = AH->format;
2212  }
2213  else
2214  {
2215  /*
2216  * *Maybe* we have a tar archive format file or a text dump ... So,
2217  * read first 512 byte header...
2218  */
2219  cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh);
2220  /* read failure is checked below */
2221  AH->lookaheadLen += cnt;
2222 
2223  if (AH->lookaheadLen >= strlen(TEXT_DUMPALL_HEADER) &&
2224  (strncmp(AH->lookahead, TEXT_DUMP_HEADER, strlen(TEXT_DUMP_HEADER)) == 0 ||
2225  strncmp(AH->lookahead, TEXT_DUMPALL_HEADER, strlen(TEXT_DUMPALL_HEADER)) == 0))
2226  {
2227  /*
2228  * looks like it's probably a text format dump. so suggest they
2229  * try psql
2230  */
2231  exit_horribly(modulename, "input file appears to be a text format dump. Please use psql.\n");
2232  }
2233 
2234  if (AH->lookaheadLen != 512)
2235  {
2236  if (feof(fh))
2237  exit_horribly(modulename, "input file does not appear to be a valid archive (too short?)\n");
2238  else
2239  READ_ERROR_EXIT(fh);
2240  }
2241 
2242  if (!isValidTarHeader(AH->lookahead))
2243  exit_horribly(modulename, "input file does not appear to be a valid archive\n");
2244 
2245  AH->format = archTar;
2246  }
2247 
2248  /* If we can't seek, then mark the header as read */
2249  if (fseeko(fh, 0, SEEK_SET) != 0)
2250  {
2251  /*
2252  * NOTE: Formats that use the lookahead buffer can unset this in their
2253  * Init routine.
2254  */
2255  AH->readHeader = 1;
2256  }
2257  else
2258  AH->lookaheadLen = 0; /* Don't bother since we've reset the file */
2259 
2260  /* Close the file */
2261  if (wantClose)
2262  if (fclose(fh) != 0)
2263  exit_horribly(modulename, "could not close input file: %s\n",
2264  strerror(errno));
2265 
2266  return AH->format;
2267 }
2268 
2269 
2270 /*
2271  * Allocate an archive handle
2272  */
2273 static ArchiveHandle *
2274 _allocAH(const char *FileSpec, const ArchiveFormat fmt,
2275  const int compression, bool dosync, ArchiveMode mode,
2276  SetupWorkerPtr setupWorkerPtr)
2277 {
2278  ArchiveHandle *AH;
2279 
2280 #if 0
2281  write_msg(modulename, "allocating AH for %s, format %d\n", FileSpec, fmt);
2282 #endif
2283 
2284  AH = (ArchiveHandle *) pg_malloc0(sizeof(ArchiveHandle));
2285 
2286  /* AH->debugLevel = 100; */
2287 
2288  AH->version = K_VERS_SELF;
2289 
2290  /* initialize for backwards compatible string processing */
2291  AH->public.encoding = 0; /* PG_SQL_ASCII */
2292  AH->public.std_strings = false;
2293 
2294  /* sql error handling */
2295  AH->public.exit_on_error = true;
2296  AH->public.n_errors = 0;
2297 
2298  AH->archiveDumpVersion = PG_VERSION;
2299 
2300  AH->createDate = time(NULL);
2301 
2302  AH->intSize = sizeof(int);
2303  AH->offSize = sizeof(pgoff_t);
2304  if (FileSpec)
2305  {
2306  AH->fSpec = pg_strdup(FileSpec);
2307 
2308  /*
2309  * Not used; maybe later....
2310  *
2311  * AH->workDir = pg_strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
2312  * i--) if (AH->workDir[i-1] == '/')
2313  */
2314  }
2315  else
2316  AH->fSpec = NULL;
2317 
2318  AH->currUser = NULL; /* unknown */
2319  AH->currSchema = NULL; /* ditto */
2320  AH->currTablespace = NULL; /* ditto */
2321  AH->currWithOids = -1; /* force SET */
2322 
2323  AH->toc = (TocEntry *) pg_malloc0(sizeof(TocEntry));
2324 
2325  AH->toc->next = AH->toc;
2326  AH->toc->prev = AH->toc;
2327 
2328  AH->mode = mode;
2329  AH->compression = compression;
2330  AH->dosync = dosync;
2331 
2332  memset(&(AH->sqlparse), 0, sizeof(AH->sqlparse));
2333 
2334  /* Open stdout with no compression for AH output handle */
2335  AH->gzOut = 0;
2336  AH->OF = stdout;
2337 
2338  /*
2339  * On Windows, we need to use binary mode to read/write non-text archive
2340  * formats. Force stdin/stdout into binary mode if that is what we are
2341  * using.
2342  */
2343 #ifdef WIN32
2344  if (fmt != archNull &&
2345  (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))
2346  {
2347  if (mode == archModeWrite)
2348  setmode(fileno(stdout), O_BINARY);
2349  else
2350  setmode(fileno(stdin), O_BINARY);
2351  }
2352 #endif
2353 
2354  AH->SetupWorkerPtr = setupWorkerPtr;
2355 
2356  if (fmt == archUnknown)
2357  AH->format = _discoverArchiveFormat(AH);
2358  else
2359  AH->format = fmt;
2360 
2362 
2363  switch (AH->format)
2364  {
2365  case archCustom:
2367  break;
2368 
2369  case archNull:
2370  InitArchiveFmt_Null(AH);
2371  break;
2372 
2373  case archDirectory:
2375  break;
2376 
2377  case archTar:
2378  InitArchiveFmt_Tar(AH);
2379  break;
2380 
2381  default:
2382  exit_horribly(modulename, "unrecognized file format \"%d\"\n", fmt);
2383  }
2384 
2385  return AH;
2386 }
2387 
2388 /*
2389  * Write out all data (tables & blobs)
2390  */
2391 void
2393 {
2394  TocEntry *te;
2395 
2396  for (te = AH->toc->next; te != AH->toc; te = te->next)
2397  {
2398  if (!te->dataDumper)
2399  continue;
2400 
2401  if ((te->reqs & REQ_DATA) == 0)
2402  continue;
2403 
2404  if (pstate && pstate->numWorkers > 1)
2405  {
2406  /*
2407  * If we are in a parallel backup, then we are always the master
2408  * process. Dispatch each data-transfer job to a worker.
2409  */
2410  DispatchJobForTocEntry(AH, pstate, te, ACT_DUMP,
2412  }
2413  else
2415  }
2416 
2417  /*
2418  * If parallel, wait for workers to finish.
2419  */
2420  if (pstate && pstate->numWorkers > 1)
2421  WaitForWorkers(AH, pstate, WFW_ALL_IDLE);
2422 }
2423 
2424 
2425 /*
2426  * Callback function that's invoked in the master process after a step has
2427  * been parallel dumped.
2428  *
2429  * We don't need to do anything except check for worker failure.
2430  */
2431 static void
2433  TocEntry *te,
2434  int status,
2435  void *callback_data)
2436 {
2437  ahlog(AH, 1, "finished item %d %s %s\n",
2438  te->dumpId, te->desc, te->tag);
2439 
2440  if (status != 0)
2441  exit_horribly(modulename, "worker process failed: exit code %d\n",
2442  status);
2443 }
2444 
2445 
2446 void
2448 {
2449  StartDataPtr startPtr;
2450  EndDataPtr endPtr;
2451 
2452  AH->currToc = te;
2453 
2454  if (strcmp(te->desc, "BLOBS") == 0)
2455  {
2456  startPtr = AH->StartBlobsPtr;
2457  endPtr = AH->EndBlobsPtr;
2458  }
2459  else
2460  {
2461  startPtr = AH->StartDataPtr;
2462  endPtr = AH->EndDataPtr;
2463  }
2464 
2465  if (startPtr != NULL)
2466  (*startPtr) (AH, te);
2467 
2468  /*
2469  * The user-provided DataDumper routine needs to call AH->WriteData
2470  */
2471  (*te->dataDumper) ((Archive *) AH, te->dataDumperArg);
2472 
2473  if (endPtr != NULL)
2474  (*endPtr) (AH, te);
2475 
2476  AH->currToc = NULL;
2477 }
2478 
2479 void
2481 {
2482  TocEntry *te;
2483  char workbuf[32];
2484  int tocCount;
2485  int i;
2486 
2487  /* count entries that will actually be dumped */
2488  tocCount = 0;
2489  for (te = AH->toc->next; te != AH->toc; te = te->next)
2490  {
2491  if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) != 0)
2492  tocCount++;
2493  }
2494 
2495  /* printf("%d TOC Entries to save\n", tocCount); */
2496 
2497  WriteInt(AH, tocCount);
2498 
2499  for (te = AH->toc->next; te != AH->toc; te = te->next)
2500  {
2501  if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) == 0)
2502  continue;
2503 
2504  WriteInt(AH, te->dumpId);
2505  WriteInt(AH, te->dataDumper ? 1 : 0);
2506 
2507  /* OID is recorded as a string for historical reasons */
2508  sprintf(workbuf, "%u", te->catalogId.tableoid);
2509  WriteStr(AH, workbuf);
2510  sprintf(workbuf, "%u", te->catalogId.oid);
2511  WriteStr(AH, workbuf);
2512 
2513  WriteStr(AH, te->tag);
2514  WriteStr(AH, te->desc);
2515  WriteInt(AH, te->section);
2516  WriteStr(AH, te->defn);
2517  WriteStr(AH, te->dropStmt);
2518  WriteStr(AH, te->copyStmt);
2519  WriteStr(AH, te->namespace);
2520  WriteStr(AH, te->tablespace);
2521  WriteStr(AH, te->owner);
2522  WriteStr(AH, te->withOids ? "true" : "false");
2523 
2524  /* Dump list of dependencies */
2525  for (i = 0; i < te->nDeps; i++)
2526  {
2527  sprintf(workbuf, "%d", te->dependencies[i]);
2528  WriteStr(AH, workbuf);
2529  }
2530  WriteStr(AH, NULL); /* Terminate List */
2531 
2532  if (AH->WriteExtraTocPtr)
2533  (*AH->WriteExtraTocPtr) (AH, te);
2534  }
2535 }
2536 
2537 void
2539 {
2540  int i;
2541  char *tmp;
2542  DumpId *deps;
2543  int depIdx;
2544  int depSize;
2545  TocEntry *te;
2546 
2547  AH->tocCount = ReadInt(AH);
2548  AH->maxDumpId = 0;
2549 
2550  for (i = 0; i < AH->tocCount; i++)
2551  {
2552  te = (TocEntry *) pg_malloc0(sizeof(TocEntry));
2553  te->dumpId = ReadInt(AH);
2554 
2555  if (te->dumpId > AH->maxDumpId)
2556  AH->maxDumpId = te->dumpId;
2557 
2558  /* Sanity check */
2559  if (te->dumpId <= 0)
2561  "entry ID %d out of range -- perhaps a corrupt TOC\n",
2562  te->dumpId);
2563 
2564  te->hadDumper = ReadInt(AH);
2565 
2566  if (AH->version >= K_VERS_1_8)
2567  {
2568  tmp = ReadStr(AH);
2569  sscanf(tmp, "%u", &te->catalogId.tableoid);
2570  free(tmp);
2571  }
2572  else
2574  tmp = ReadStr(AH);
2575  sscanf(tmp, "%u", &te->catalogId.oid);
2576  free(tmp);
2577 
2578  te->tag = ReadStr(AH);
2579  te->desc = ReadStr(AH);
2580 
2581  if (AH->version >= K_VERS_1_11)
2582  {
2583  te->section = ReadInt(AH);
2584  }
2585  else
2586  {
2587  /*
2588  * Rules for pre-8.4 archives wherein pg_dump hasn't classified
2589  * the entries into sections. This list need not cover entry
2590  * types added later than 8.4.
2591  */
2592  if (strcmp(te->desc, "COMMENT") == 0 ||
2593  strcmp(te->desc, "ACL") == 0 ||
2594  strcmp(te->desc, "ACL LANGUAGE") == 0)
2595  te->section = SECTION_NONE;
2596  else if (strcmp(te->desc, "TABLE DATA") == 0 ||
2597  strcmp(te->desc, "BLOBS") == 0 ||
2598  strcmp(te->desc, "BLOB COMMENTS") == 0)
2599  te->section = SECTION_DATA;
2600  else if (strcmp(te->desc, "CONSTRAINT") == 0 ||
2601  strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
2602  strcmp(te->desc, "FK CONSTRAINT") == 0 ||
2603  strcmp(te->desc, "INDEX") == 0 ||
2604  strcmp(te->desc, "RULE") == 0 ||
2605  strcmp(te->desc, "TRIGGER") == 0)
2606  te->section = SECTION_POST_DATA;
2607  else
2608  te->section = SECTION_PRE_DATA;
2609  }
2610 
2611  te->defn = ReadStr(AH);
2612  te->dropStmt = ReadStr(AH);
2613 
2614  if (AH->version >= K_VERS_1_3)
2615  te->copyStmt = ReadStr(AH);
2616 
2617  if (AH->version >= K_VERS_1_6)
2618  te->namespace = ReadStr(AH);
2619 
2620  if (AH->version >= K_VERS_1_10)
2621  te->tablespace = ReadStr(AH);
2622 
2623  te->owner = ReadStr(AH);
2624  if (AH->version >= K_VERS_1_9)
2625  {
2626  if (strcmp(ReadStr(AH), "true") == 0)
2627  te->withOids = true;
2628  else
2629  te->withOids = false;
2630  }
2631  else
2632  te->withOids = true;
2633 
2634  /* Read TOC entry dependencies */
2635  if (AH->version >= K_VERS_1_5)
2636  {
2637  depSize = 100;
2638  deps = (DumpId *) pg_malloc(sizeof(DumpId) * depSize);
2639  depIdx = 0;
2640  for (;;)
2641  {
2642  tmp = ReadStr(AH);
2643  if (!tmp)
2644  break; /* end of list */
2645  if (depIdx >= depSize)
2646  {
2647  depSize *= 2;
2648  deps = (DumpId *) pg_realloc(deps, sizeof(DumpId) * depSize);
2649  }
2650  sscanf(tmp, "%d", &deps[depIdx]);
2651  free(tmp);
2652  depIdx++;
2653  }
2654 
2655  if (depIdx > 0) /* We have a non-null entry */
2656  {
2657  deps = (DumpId *) pg_realloc(deps, sizeof(DumpId) * depIdx);
2658  te->dependencies = deps;
2659  te->nDeps = depIdx;
2660  }
2661  else
2662  {
2663  free(deps);
2664  te->dependencies = NULL;
2665  te->nDeps = 0;
2666  }
2667  }
2668  else
2669  {
2670  te->dependencies = NULL;
2671  te->nDeps = 0;
2672  }
2673 
2674  if (AH->ReadExtraTocPtr)
2675  (*AH->ReadExtraTocPtr) (AH, te);
2676 
2677  ahlog(AH, 3, "read TOC entry %d (ID %d) for %s %s\n",
2678  i, te->dumpId, te->desc, te->tag);
2679 
2680  /* link completed entry into TOC circular list */
2681  te->prev = AH->toc->prev;
2682  AH->toc->prev->next = te;
2683  AH->toc->prev = te;
2684  te->next = AH->toc;
2685 
2686  /* special processing immediately upon read for some items */
2687  if (strcmp(te->desc, "ENCODING") == 0)
2688  processEncodingEntry(AH, te);
2689  else if (strcmp(te->desc, "STDSTRINGS") == 0)
2690  processStdStringsEntry(AH, te);
2691  }
2692 }
2693 
2694 static void
2696 {
2697  /* te->defn should have the form SET client_encoding = 'foo'; */
2698  char *defn = pg_strdup(te->defn);
2699  char *ptr1;
2700  char *ptr2 = NULL;
2701  int encoding;
2702 
2703  ptr1 = strchr(defn, '\'');
2704  if (ptr1)
2705  ptr2 = strchr(++ptr1, '\'');
2706  if (ptr2)
2707  {
2708  *ptr2 = '\0';
2709  encoding = pg_char_to_encoding(ptr1);
2710  if (encoding < 0)
2711  exit_horribly(modulename, "unrecognized encoding \"%s\"\n",
2712  ptr1);
2713  AH->public.encoding = encoding;
2714  }
2715  else
2716  exit_horribly(modulename, "invalid ENCODING item: %s\n",
2717  te->defn);
2718 
2719  free(defn);
2720 }
2721 
2722 static void
2724 {
2725  /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2726  char *ptr1;
2727 
2728  ptr1 = strchr(te->defn, '\'');
2729  if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
2730  AH->public.std_strings = true;
2731  else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
2732  AH->public.std_strings = false;
2733  else
2734  exit_horribly(modulename, "invalid STDSTRINGS item: %s\n",
2735  te->defn);
2736 }
2737 
2738 static void
2740 {
2741  const char *missing_name;
2742 
2743  Assert(ropt->strict_names);
2744 
2745  if (ropt->schemaNames.head != NULL)
2746  {
2747  missing_name = simple_string_list_not_touched(&ropt->schemaNames);
2748  if (missing_name != NULL)
2749  exit_horribly(modulename, "schema \"%s\" not found\n", missing_name);
2750  }
2751 
2752  if (ropt->tableNames.head != NULL)
2753  {
2754  missing_name = simple_string_list_not_touched(&ropt->tableNames);
2755  if (missing_name != NULL)
2756  exit_horribly(modulename, "table \"%s\" not found\n", missing_name);
2757  }
2758 
2759  if (ropt->indexNames.head != NULL)
2760  {
2761  missing_name = simple_string_list_not_touched(&ropt->indexNames);
2762  if (missing_name != NULL)
2763  exit_horribly(modulename, "index \"%s\" not found\n", missing_name);
2764  }
2765 
2766  if (ropt->functionNames.head != NULL)
2767  {
2768  missing_name = simple_string_list_not_touched(&ropt->functionNames);
2769  if (missing_name != NULL)
2770  exit_horribly(modulename, "function \"%s\" not found\n", missing_name);
2771  }
2772 
2773  if (ropt->triggerNames.head != NULL)
2774  {
2775  missing_name = simple_string_list_not_touched(&ropt->triggerNames);
2776  if (missing_name != NULL)
2777  exit_horribly(modulename, "trigger \"%s\" not found\n", missing_name);
2778  }
2779 }
2780 
2781 static teReqs
2783 {
2784  teReqs res = REQ_SCHEMA | REQ_DATA;
2785 
2786  /* ENCODING and STDSTRINGS items are treated specially */
2787  if (strcmp(te->desc, "ENCODING") == 0 ||
2788  strcmp(te->desc, "STDSTRINGS") == 0)
2789  return REQ_SPECIAL;
2790 
2791  /* If it's an ACL, maybe ignore it */
2792  if (ropt->aclsSkip && _tocEntryIsACL(te))
2793  return 0;
2794 
2795  /* If it's security labels, maybe ignore it */
2796  if (ropt->no_security_labels && strcmp(te->desc, "SECURITY LABEL") == 0)
2797  return 0;
2798 
2799  /* Ignore it if section is not to be dumped/restored */
2800  switch (curSection)
2801  {
2802  case SECTION_PRE_DATA:
2803  if (!(ropt->dumpSections & DUMP_PRE_DATA))
2804  return 0;
2805  break;
2806  case SECTION_DATA:
2807  if (!(ropt->dumpSections & DUMP_DATA))
2808  return 0;
2809  break;
2810  case SECTION_POST_DATA:
2811  if (!(ropt->dumpSections & DUMP_POST_DATA))
2812  return 0;
2813  break;
2814  default:
2815  /* shouldn't get here, really, but ignore it */
2816  return 0;
2817  }
2818 
2819  /* Check options for selective dump/restore */
2820  if (ropt->schemaNames.head != NULL)
2821  {
2822  /* If no namespace is specified, it means all. */
2823  if (!te->namespace)
2824  return 0;
2825  if (!(simple_string_list_member(&ropt->schemaNames, te->namespace)))
2826  return 0;
2827  }
2828 
2829  if (ropt->schemaExcludeNames.head != NULL &&
2830  te->namespace &&
2831  simple_string_list_member(&ropt->schemaExcludeNames, te->namespace))
2832  return 0;
2833 
2834  if (ropt->selTypes)
2835  {
2836  if (strcmp(te->desc, "TABLE") == 0 ||
2837  strcmp(te->desc, "TABLE DATA") == 0 ||
2838  strcmp(te->desc, "VIEW") == 0 ||
2839  strcmp(te->desc, "FOREIGN TABLE") == 0 ||
2840  strcmp(te->desc, "MATERIALIZED VIEW") == 0 ||
2841  strcmp(te->desc, "MATERIALIZED VIEW DATA") == 0 ||
2842  strcmp(te->desc, "SEQUENCE") == 0 ||
2843  strcmp(te->desc, "SEQUENCE SET") == 0)
2844  {
2845  if (!ropt->selTable)
2846  return 0;
2847  if (ropt->tableNames.head != NULL && (!(simple_string_list_member(&ropt->tableNames, te->tag))))
2848  return 0;
2849  }
2850  else if (strcmp(te->desc, "INDEX") == 0)
2851  {
2852  if (!ropt->selIndex)
2853  return 0;
2854  if (ropt->indexNames.head != NULL && (!(simple_string_list_member(&ropt->indexNames, te->tag))))
2855  return 0;
2856  }
2857  else if (strcmp(te->desc, "FUNCTION") == 0)
2858  {
2859  if (!ropt->selFunction)
2860  return 0;
2861  if (ropt->functionNames.head != NULL && (!(simple_string_list_member(&ropt->functionNames, te->tag))))
2862  return 0;
2863  }
2864  else if (strcmp(te->desc, "TRIGGER") == 0)
2865  {
2866  if (!ropt->selTrigger)
2867  return 0;
2868  if (ropt->triggerNames.head != NULL && (!(simple_string_list_member(&ropt->triggerNames, te->tag))))
2869  return 0;
2870  }
2871  else
2872  return 0;
2873  }
2874 
2875  /*
2876  * Check if we had a dataDumper. Indicates if the entry is schema or data
2877  */
2878  if (!te->hadDumper)
2879  {
2880  /*
2881  * Special Case: If 'SEQUENCE SET' or anything to do with BLOBs, then
2882  * it is considered a data entry. We don't need to check for the
2883  * BLOBS entry or old-style BLOB COMMENTS, because they will have
2884  * hadDumper = true ... but we do need to check new-style BLOB
2885  * comments.
2886  */
2887  if (strcmp(te->desc, "SEQUENCE SET") == 0 ||
2888  strcmp(te->desc, "BLOB") == 0 ||
2889  (strcmp(te->desc, "ACL") == 0 &&
2890  strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
2891  (strcmp(te->desc, "COMMENT") == 0 &&
2892  strncmp(te->tag, "LARGE OBJECT ", 13) == 0) ||
2893  (strcmp(te->desc, "SECURITY LABEL") == 0 &&
2894  strncmp(te->tag, "LARGE OBJECT ", 13) == 0))
2895  res = res & REQ_DATA;
2896  else
2897  res = res & ~REQ_DATA;
2898  }
2899 
2900  /*
2901  * Special case: <Init> type with <Max OID> tag; this is obsolete and we
2902  * always ignore it.
2903  */
2904  if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))
2905  return 0;
2906 
2907  /* Mask it if we only want schema */
2908  if (ropt->schemaOnly)
2909  {
2910  /*
2911  * In binary-upgrade mode, even with schema-only set, we do not mask
2912  * out large objects. Only large object definitions, comments and
2913  * other information should be generated in binary-upgrade mode (not
2914  * the actual data).
2915  */
2916  if (!(ropt->sequence_data && strcmp(te->desc, "SEQUENCE SET") == 0) &&
2917  !(ropt->binary_upgrade && strcmp(te->desc, "BLOB") == 0) &&
2918  !(ropt->binary_upgrade && strncmp(te->tag, "LARGE OBJECT ", 13) == 0))
2919  res = res & REQ_SCHEMA;
2920  }
2921 
2922  /* Mask it if we only want data */
2923  if (ropt->dataOnly)
2924  res = res & REQ_DATA;
2925 
2926  /* Mask it if we don't have a schema contribution */
2927  if (!te->defn || strlen(te->defn) == 0)
2928  res = res & ~REQ_SCHEMA;
2929 
2930  /* Finally, if there's a per-ID filter, limit based on that as well */
2931  if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1])
2932  return 0;
2933 
2934  return res;
2935 }
2936 
2937 /*
2938  * Identify TOC entries that are ACLs.
2939  */
2940 static bool
2942 {
2943  /* "ACL LANGUAGE" was a crock emitted only in PG 7.4 */
2944  if (strcmp(te->desc, "ACL") == 0 ||
2945  strcmp(te->desc, "ACL LANGUAGE") == 0 ||
2946  strcmp(te->desc, "DEFAULT ACL") == 0)
2947  return true;
2948  return false;
2949 }
2950 
2951 /*
2952  * Issue SET commands for parameters that we want to have set the same way
2953  * at all times during execution of a restore script.
2954  */
2955 static void
2957 {
2958  RestoreOptions *ropt = AH->public.ropt;
2959 
2960  /*
2961  * Disable timeouts to allow for slow commands, idle parallel workers, etc
2962  */
2963  ahprintf(AH, "SET statement_timeout = 0;\n");
2964  ahprintf(AH, "SET lock_timeout = 0;\n");
2965  ahprintf(AH, "SET idle_in_transaction_session_timeout = 0;\n");
2966 
2967  /* Select the correct character set encoding */
2968  ahprintf(AH, "SET client_encoding = '%s';\n",
2970 
2971  /* Select the correct string literal syntax */
2972  ahprintf(AH, "SET standard_conforming_strings = %s;\n",
2973  AH->public.std_strings ? "on" : "off");
2974 
2975  /* Select the role to be used during restore */
2976  if (ropt && ropt->use_role)
2977  ahprintf(AH, "SET ROLE %s;\n", fmtId(ropt->use_role));
2978 
2979  /* Make sure function checking is disabled */
2980  ahprintf(AH, "SET check_function_bodies = false;\n");
2981 
2982  /* Avoid annoying notices etc */
2983  ahprintf(AH, "SET client_min_messages = warning;\n");
2984  if (!AH->public.std_strings)
2985  ahprintf(AH, "SET escape_string_warning = off;\n");
2986 
2987  /* Adjust row-security state */
2988  if (ropt && ropt->enable_row_security)
2989  ahprintf(AH, "SET row_security = on;\n");
2990  else
2991  ahprintf(AH, "SET row_security = off;\n");
2992 
2993  ahprintf(AH, "\n");
2994 }
2995 
2996 /*
2997  * Issue a SET SESSION AUTHORIZATION command. Caller is responsible
2998  * for updating state if appropriate. If user is NULL or an empty string,
2999  * the specification DEFAULT will be used.
3000  */
3001 static void
3003 {
3005 
3006  appendPQExpBufferStr(cmd, "SET SESSION AUTHORIZATION ");
3007 
3008  /*
3009  * SQL requires a string literal here. Might as well be correct.
3010  */
3011  if (user && *user)
3012  appendStringLiteralAHX(cmd, user, AH);
3013  else
3014  appendPQExpBufferStr(cmd, "DEFAULT");
3015  appendPQExpBufferChar(cmd, ';');
3016 
3017  if (RestoringToDB(AH))
3018  {
3019  PGresult *res;
3020 
3021  res = PQexec(AH->connection, cmd->data);
3022 
3023  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3024  /* NOT warn_or_exit_horribly... use -O instead to skip this. */
3025  exit_horribly(modulename, "could not set session user to \"%s\": %s",
3026  user, PQerrorMessage(AH->connection));
3027 
3028  PQclear(res);
3029  }
3030  else
3031  ahprintf(AH, "%s\n\n", cmd->data);
3032 
3033  destroyPQExpBuffer(cmd);
3034 }
3035 
3036 
3037 /*
3038  * Issue a SET default_with_oids command. Caller is responsible
3039  * for updating state if appropriate.
3040  */
3041 static void
3042 _doSetWithOids(ArchiveHandle *AH, const bool withOids)
3043 {
3045 
3046  appendPQExpBuffer(cmd, "SET default_with_oids = %s;", withOids ?
3047  "true" : "false");
3048 
3049  if (RestoringToDB(AH))
3050  {
3051  PGresult *res;
3052 
3053  res = PQexec(AH->connection, cmd->data);
3054 
3055  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3057  "could not set default_with_oids: %s",
3058  PQerrorMessage(AH->connection));
3059 
3060  PQclear(res);
3061  }
3062  else
3063  ahprintf(AH, "%s\n\n", cmd->data);
3064 
3065  destroyPQExpBuffer(cmd);
3066 }
3067 
3068 
3069 /*
3070  * Issue the commands to connect to the specified database.
3071  *
3072  * If we're currently restoring right into a database, this will
3073  * actually establish a connection. Otherwise it puts a \connect into
3074  * the script output.
3075  *
3076  * NULL dbname implies reconnecting to the current DB (pretty useless).
3077  */
3078 static void
3080 {
3081  if (RestoringToDB(AH))
3082  ReconnectToServer(AH, dbname, NULL);
3083  else
3084  {
3085  if (dbname)
3086  {
3087  PQExpBufferData connectbuf;
3088 
3089  initPQExpBuffer(&connectbuf);
3090  appendPsqlMetaConnect(&connectbuf, dbname);
3091  ahprintf(AH, "%s\n", connectbuf.data);
3092  termPQExpBuffer(&connectbuf);
3093  }
3094  else
3095  ahprintf(AH, "%s\n", "\\connect -\n");
3096  }
3097 
3098  /*
3099  * NOTE: currUser keeps track of what the imaginary session user in our
3100  * script is. It's now effectively reset to the original userID.
3101  */
3102  if (AH->currUser)
3103  free(AH->currUser);
3104  AH->currUser = NULL;
3105 
3106  /* don't assume we still know the output schema, tablespace, etc either */
3107  if (AH->currSchema)
3108  free(AH->currSchema);
3109  AH->currSchema = NULL;
3110  if (AH->currTablespace)
3111  free(AH->currTablespace);
3112  AH->currTablespace = NULL;
3113  AH->currWithOids = -1;
3114 
3115  /* re-establish fixed state */
3117 }
3118 
3119 /*
3120  * Become the specified user, and update state to avoid redundant commands
3121  *
3122  * NULL or empty argument is taken to mean restoring the session default
3123  */
3124 static void
3125 _becomeUser(ArchiveHandle *AH, const char *user)
3126 {
3127  if (!user)
3128  user = ""; /* avoid null pointers */
3129 
3130  if (AH->currUser && strcmp(AH->currUser, user) == 0)
3131  return; /* no need to do anything */
3132 
3133  _doSetSessionAuth(AH, user);
3134 
3135  /*
3136  * NOTE: currUser keeps track of what the imaginary session user in our
3137  * script is
3138  */
3139  if (AH->currUser)
3140  free(AH->currUser);
3141  AH->currUser = pg_strdup(user);
3142 }
3143 
3144 /*
3145  * Become the owner of the given TOC entry object. If
3146  * changes in ownership are not allowed, this doesn't do anything.
3147  */
3148 static void
3150 {
3151  RestoreOptions *ropt = AH->public.ropt;
3152 
3153  if (ropt && (ropt->noOwner || !ropt->use_setsessauth))
3154  return;
3155 
3156  _becomeUser(AH, te->owner);
3157 }
3158 
3159 
3160 /*
3161  * Set the proper default_with_oids value for the table.
3162  */
3163 static void
3165 {
3166  if (AH->currWithOids != te->withOids)
3167  {
3168  _doSetWithOids(AH, te->withOids);
3169  AH->currWithOids = te->withOids;
3170  }
3171 }
3172 
3173 
3174 /*
3175  * Issue the commands to select the specified schema as the current schema
3176  * in the target database.
3177  */
3178 static void
3179 _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
3180 {
3181  PQExpBuffer qry;
3182 
3183  if (!schemaName || *schemaName == '\0' ||
3184  (AH->currSchema && strcmp(AH->currSchema, schemaName) == 0))
3185  return; /* no need to do anything */
3186 
3187  qry = createPQExpBuffer();
3188 
3189  appendPQExpBuffer(qry, "SET search_path = %s",
3190  fmtId(schemaName));
3191  if (strcmp(schemaName, "pg_catalog") != 0)
3192  appendPQExpBufferStr(qry, ", pg_catalog");
3193 
3194  if (RestoringToDB(AH))
3195  {
3196  PGresult *res;
3197 
3198  res = PQexec(AH->connection, qry->data);
3199 
3200  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3202  "could not set search_path to \"%s\": %s",
3203  schemaName, PQerrorMessage(AH->connection));
3204 
3205  PQclear(res);
3206  }
3207  else
3208  ahprintf(AH, "%s;\n\n", qry->data);
3209 
3210  if (AH->currSchema)
3211  free(AH->currSchema);
3212  AH->currSchema = pg_strdup(schemaName);
3213 
3214  destroyPQExpBuffer(qry);
3215 }
3216 
3217 /*
3218  * Issue the commands to select the specified tablespace as the current one
3219  * in the target database.
3220  */
3221 static void
3223 {
3224  RestoreOptions *ropt = AH->public.ropt;
3225  PQExpBuffer qry;
3226  const char *want,
3227  *have;
3228 
3229  /* do nothing in --no-tablespaces mode */
3230  if (ropt->noTablespace)
3231  return;
3232 
3233  have = AH->currTablespace;
3234  want = tablespace;
3235 
3236  /* no need to do anything for non-tablespace object */
3237  if (!want)
3238  return;
3239 
3240  if (have && strcmp(want, have) == 0)
3241  return; /* no need to do anything */
3242 
3243  qry = createPQExpBuffer();
3244 
3245  if (strcmp(want, "") == 0)
3246  {
3247  /* We want the tablespace to be the database's default */
3248  appendPQExpBufferStr(qry, "SET default_tablespace = ''");
3249  }
3250  else
3251  {
3252  /* We want an explicit tablespace */
3253  appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want));
3254  }
3255 
3256  if (RestoringToDB(AH))
3257  {
3258  PGresult *res;
3259 
3260  res = PQexec(AH->connection, qry->data);
3261 
3262  if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
3264  "could not set default_tablespace to %s: %s",
3265  fmtId(want), PQerrorMessage(AH->connection));
3266 
3267  PQclear(res);
3268  }
3269  else
3270  ahprintf(AH, "%s;\n\n", qry->data);
3271 
3272  if (AH->currTablespace)
3273  free(AH->currTablespace);
3274  AH->currTablespace = pg_strdup(want);
3275 
3276  destroyPQExpBuffer(qry);
3277 }
3278 
3279 /*
3280  * Extract an object description for a TOC entry, and append it to buf.
3281  *
3282  * This is used for ALTER ... OWNER TO.
3283  */
3284 static void
3286 {
3287  const char *type = te->desc;
3288 
3289  /* Use ALTER TABLE for views and sequences */
3290  if (strcmp(type, "VIEW") == 0 || strcmp(type, "SEQUENCE") == 0 ||
3291  strcmp(type, "MATERIALIZED VIEW") == 0)
3292  type = "TABLE";
3293 
3294  /* objects that don't require special decoration */
3295  if (strcmp(type, "COLLATION") == 0 ||
3296  strcmp(type, "CONVERSION") == 0 ||
3297  strcmp(type, "DOMAIN") == 0 ||
3298  strcmp(type, "TABLE") == 0 ||
3299  strcmp(type, "TYPE") == 0 ||
3300  strcmp(type, "FOREIGN TABLE") == 0 ||
3301  strcmp(type, "TEXT SEARCH DICTIONARY") == 0 ||
3302  strcmp(type, "TEXT SEARCH CONFIGURATION") == 0 ||
3303  /* non-schema-specified objects */
3304  strcmp(type, "DATABASE") == 0 ||
3305  strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
3306  strcmp(type, "SCHEMA") == 0 ||
3307  strcmp(type, "FOREIGN DATA WRAPPER") == 0 ||
3308  strcmp(type, "SERVER") == 0 ||
3309  strcmp(type, "PUBLICATION") == 0 ||
3310  strcmp(type, "SUBSCRIPTION") == 0 ||
3311  strcmp(type, "USER MAPPING") == 0)
3312  {
3313  /* We already know that search_path was set properly */
3314  appendPQExpBuffer(buf, "%s %s", type, fmtId(te->tag));
3315  return;
3316  }
3317 
3318  /* BLOBs just have a name, but it's numeric so must not use fmtId */
3319  if (strcmp(type, "BLOB") == 0)
3320  {
3321  appendPQExpBuffer(buf, "LARGE OBJECT %s", te->tag);
3322  return;
3323  }
3324 
3325  /*
3326  * These object types require additional decoration. Fortunately, the
3327  * information needed is exactly what's in the DROP command.
3328  */
3329  if (strcmp(type, "AGGREGATE") == 0 ||
3330  strcmp(type, "FUNCTION") == 0 ||
3331  strcmp(type, "OPERATOR") == 0 ||
3332  strcmp(type, "OPERATOR CLASS") == 0 ||
3333  strcmp(type, "OPERATOR FAMILY") == 0)
3334  {
3335  /* Chop "DROP " off the front and make a modifiable copy */
3336  char *first = pg_strdup(te->dropStmt + 5);
3337  char *last;
3338 
3339  /* point to last character in string */
3340  last = first + strlen(first) - 1;
3341 
3342  /* Strip off any ';' or '\n' at the end */
3343  while (last >= first && (*last == '\n' || *last == ';'))
3344  last--;
3345  *(last + 1) = '\0';
3346 
3347  appendPQExpBufferStr(buf, first);
3348 
3349  free(first);
3350  return;
3351  }
3352 
3353  write_msg(modulename, "WARNING: don't know how to set owner for object type %s\n",
3354  type);
3355 }
3356 
3357 static void
3358 _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData, bool acl_pass)
3359 {
3360  RestoreOptions *ropt = AH->public.ropt;
3361 
3362  /* ACLs are dumped only during acl pass */
3363  if (acl_pass)
3364  {
3365  if (!_tocEntryIsACL(te))
3366  return;
3367  }
3368  else
3369  {
3370  if (_tocEntryIsACL(te))
3371  return;
3372  }
3373 
3374  /*
3375  * Avoid dumping the public schema, as it will already be created ...
3376  * unless we are using --clean mode (and *not* --create mode), in which
3377  * case we've previously issued a DROP for it so we'd better recreate it.
3378  *
3379  * Likewise for its comment, if any. (We could try issuing the COMMENT
3380  * command anyway; but it'd fail if the restore is done as non-super-user,
3381  * so let's not.)
3382  *
3383  * XXX it looks pretty ugly to hard-wire the public schema like this, but
3384  * it sits in a sort of no-mans-land between being a system object and a
3385  * user object, so it really is special in a way.
3386  */
3387  if (!(ropt->dropSchema && !ropt->createDB))
3388  {
3389  if (strcmp(te->desc, "SCHEMA") == 0 &&
3390  strcmp(te->tag, "public") == 0)
3391  return;
3392  if (strcmp(te->desc, "COMMENT") == 0 &&
3393  strcmp(te->tag, "SCHEMA public") == 0)
3394  return;
3395  }
3396 
3397  /* Select owner, schema, and tablespace as necessary */
3398  _becomeOwner(AH, te);
3399  _selectOutputSchema(AH, te->namespace);
3400  _selectTablespace(AH, te->tablespace);
3401 
3402  /* Set up OID mode too */
3403  if (strcmp(te->desc, "TABLE") == 0)
3404  _setWithOids(AH, te);
3405 
3406  /* Emit header comment for item */
3407  if (!AH->noTocComments)
3408  {
3409  const char *pfx;
3410  char *sanitized_name;
3411  char *sanitized_schema;
3412  char *sanitized_owner;
3413 
3414  if (isData)
3415  pfx = "Data for ";
3416  else
3417  pfx = "";
3418 
3419  ahprintf(AH, "--\n");
3420  if (AH->public.verbose)
3421  {
3422  ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
3423  te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
3424  if (te->nDeps > 0)
3425  {
3426  int i;
3427 
3428  ahprintf(AH, "-- Dependencies:");
3429  for (i = 0; i < te->nDeps; i++)
3430  ahprintf(AH, " %d", te->dependencies[i]);
3431  ahprintf(AH, "\n");
3432  }
3433  }
3434 
3435  /*
3436  * Zap any line endings embedded in user-supplied fields, to prevent
3437  * corruption of the dump (which could, in the worst case, present an
3438  * SQL injection vulnerability if someone were to incautiously load a
3439  * dump containing objects with maliciously crafted names).
3440  */
3441  sanitized_name = replace_line_endings(te->tag);
3442  if (te->namespace)
3443  sanitized_schema = replace_line_endings(te->namespace);
3444  else
3445  sanitized_schema = pg_strdup("-");
3446  if (!ropt->noOwner)
3447  sanitized_owner = replace_line_endings(te->owner);
3448  else
3449  sanitized_owner = pg_strdup("-");
3450 
3451  ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
3452  pfx, sanitized_name, te->desc, sanitized_schema,
3453  sanitized_owner);
3454 
3455  free(sanitized_name);
3456  free(sanitized_schema);
3457  free(sanitized_owner);
3458 
3459  if (te->tablespace && strlen(te->tablespace) > 0 && !ropt->noTablespace)
3460  {
3461  char *sanitized_tablespace;
3462 
3463  sanitized_tablespace = replace_line_endings(te->tablespace);
3464  ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
3465  free(sanitized_tablespace);
3466  }
3467  ahprintf(AH, "\n");
3468 
3469  if (AH->PrintExtraTocPtr !=NULL)
3470  (*AH->PrintExtraTocPtr) (AH, te);
3471  ahprintf(AH, "--\n\n");
3472  }
3473 
3474  /*
3475  * Actually print the definition.
3476  *
3477  * Really crude hack for suppressing AUTHORIZATION clause that old pg_dump
3478  * versions put into CREATE SCHEMA. We have to do this when --no-owner
3479  * mode is selected. This is ugly, but I see no other good way ...
3480  */
3481  if (ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0)
3482  {
3483  ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
3484  }
3485  else
3486  {
3487  if (strlen(te->defn) > 0)
3488  ahprintf(AH, "%s\n\n", te->defn);
3489  }
3490 
3491  /*
3492  * If we aren't using SET SESSION AUTH to determine ownership, we must
3493  * instead issue an ALTER OWNER command. We assume that anything without
3494  * a DROP command is not a separately ownable object. All the categories
3495  * with DROP commands must appear in one list or the other.
3496  */
3497  if (!ropt->noOwner && !ropt->use_setsessauth &&
3498  strlen(te->owner) > 0 && strlen(te->dropStmt) > 0)
3499  {
3500  if (strcmp(te->desc, "AGGREGATE") == 0 ||
3501  strcmp(te->desc, "BLOB") == 0 ||
3502  strcmp(te->desc, "COLLATION") == 0 ||
3503  strcmp(te->desc, "CONVERSION") == 0 ||
3504  strcmp(te->desc, "DATABASE") == 0 ||
3505  strcmp(te->desc, "DOMAIN") == 0 ||
3506  strcmp(te->desc, "FUNCTION") == 0 ||
3507  strcmp(te->desc, "OPERATOR") == 0 ||
3508  strcmp(te->desc, "OPERATOR CLASS") == 0 ||
3509  strcmp(te->desc, "OPERATOR FAMILY") == 0 ||
3510  strcmp(te->desc, "PROCEDURAL LANGUAGE") == 0 ||
3511  strcmp(te->desc, "SCHEMA") == 0 ||
3512  strcmp(te->desc, "TABLE") == 0 ||
3513  strcmp(te->desc, "TYPE") == 0 ||
3514  strcmp(te->desc, "VIEW") == 0 ||
3515  strcmp(te->desc, "MATERIALIZED VIEW") == 0 ||
3516  strcmp(te->desc, "SEQUENCE") == 0 ||
3517  strcmp(te->desc, "FOREIGN TABLE") == 0 ||
3518  strcmp(te->desc, "TEXT SEARCH DICTIONARY") == 0 ||
3519  strcmp(te->desc, "TEXT SEARCH CONFIGURATION") == 0 ||
3520  strcmp(te->desc, "FOREIGN DATA WRAPPER") == 0 ||
3521  strcmp(te->desc, "SERVER") == 0 ||
3522  strcmp(te->desc, "PUBLICATION") == 0 ||
3523  strcmp(te->desc, "SUBSCRIPTION") == 0)
3524  {
3525  PQExpBuffer temp = createPQExpBuffer();
3526 
3527  appendPQExpBufferStr(temp, "ALTER ");
3528  _getObjectDescription(temp, te, AH);
3529  appendPQExpBuffer(temp, " OWNER TO %s;", fmtId(te->owner));
3530  ahprintf(AH, "%s\n\n", temp->data);
3531  destroyPQExpBuffer(temp);
3532  }
3533  else if (strcmp(te->desc, "CAST") == 0 ||
3534  strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
3535  strcmp(te->desc, "CONSTRAINT") == 0 ||
3536  strcmp(te->desc, "DEFAULT") == 0 ||
3537  strcmp(te->desc, "FK CONSTRAINT") == 0 ||
3538  strcmp(te->desc, "INDEX") == 0 ||
3539  strcmp(te->desc, "RULE") == 0 ||
3540  strcmp(te->desc, "TRIGGER") == 0 ||
3541  strcmp(te->desc, "ROW SECURITY") == 0 ||
3542  strcmp(te->desc, "POLICY") == 0 ||
3543  strcmp(te->desc, "USER MAPPING") == 0 ||
3544  strcmp(te->desc, "STATISTICS") == 0)
3545  {
3546  /* these object types don't have separate owners */
3547  }
3548  else
3549  {
3550  write_msg(modulename, "WARNING: don't know how to set owner for object type %s\n",
3551  te->desc);
3552  }
3553  }
3554 
3555  /*
3556  * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
3557  * commands, so we can no longer assume we know the current auth setting.
3558  */
3559  if (acl_pass)
3560  {
3561  if (AH->currUser)
3562  free(AH->currUser);
3563  AH->currUser = NULL;
3564  }
3565 }
3566 
3567 /*
3568  * Sanitize a string to be included in an SQL comment or TOC listing,
3569  * by replacing any newlines with spaces.
3570  * The result is a freshly malloc'd string.
3571  */
3572 static char *
3573 replace_line_endings(const char *str)
3574 {
3575  char *result;
3576  char *s;
3577 
3578  result = pg_strdup(str);
3579 
3580  for (s = result; *s != '\0'; s++)
3581  {
3582  if (*s == '\n' || *s == '\r')
3583  *s = ' ';
3584  }
3585 
3586  return result;
3587 }
3588 
3589 void
3591 {
3592  struct tm crtm;
3593 
3594  (*AH->WriteBufPtr) (AH, "PGDMP", 5); /* Magic code */
3595  (*AH->WriteBytePtr) (AH, ARCHIVE_MAJOR(AH->version));
3596  (*AH->WriteBytePtr) (AH, ARCHIVE_MINOR(AH->version));
3597  (*AH->WriteBytePtr) (AH, ARCHIVE_REV(AH->version));
3598  (*AH->WriteBytePtr) (AH, AH->intSize);
3599  (*AH->WriteBytePtr) (AH, AH->offSize);
3600  (*AH->WriteBytePtr) (AH, AH->format);
3601  WriteInt(AH, AH->compression);
3602  crtm = *localtime(&AH->createDate);
3603  WriteInt(AH, crtm.tm_sec);
3604  WriteInt(AH, crtm.tm_min);
3605  WriteInt(AH, crtm.tm_hour);
3606  WriteInt(AH, crtm.tm_mday);
3607  WriteInt(AH, crtm.tm_mon);
3608  WriteInt(AH, crtm.tm_year);
3609  WriteInt(AH, crtm.tm_isdst);
3610  WriteStr(AH, PQdb(AH->connection));
3611  WriteStr(AH, AH->public.remoteVersionStr);
3612  WriteStr(AH, PG_VERSION);
3613 }
3614 
3615 void
3617 {
3618  char tmpMag[7];
3619  int fmt;
3620  struct tm crtm;
3621 
3622  /*
3623  * If we haven't already read the header, do so.
3624  *
3625  * NB: this code must agree with _discoverArchiveFormat(). Maybe find a
3626  * way to unify the cases?
3627  */
3628  if (!AH->readHeader)
3629  {
3630  char vmaj,
3631  vmin,
3632  vrev;
3633 
3634  (*AH->ReadBufPtr) (AH, tmpMag, 5);
3635 
3636  if (strncmp(tmpMag, "PGDMP", 5) != 0)
3637  exit_horribly(modulename, "did not find magic string in file header\n");
3638 
3639  vmaj = (*AH->ReadBytePtr) (AH);
3640  vmin = (*AH->ReadBytePtr) (AH);
3641 
3642  if (vmaj > 1 || (vmaj == 1 && vmin > 0)) /* Version > 1.0 */
3643  vrev = (*AH->ReadBytePtr) (AH);
3644  else
3645  vrev = 0;
3646 
3647  AH->version = MAKE_ARCHIVE_VERSION(vmaj, vmin, vrev);
3648 
3649  if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
3650  exit_horribly(modulename, "unsupported version (%d.%d) in file header\n",
3651  vmaj, vmin);
3652 
3653  AH->intSize = (*AH->ReadBytePtr) (AH);
3654  if (AH->intSize > 32)
3655  exit_horribly(modulename, "sanity check on integer size (%lu) failed\n",
3656  (unsigned long) AH->intSize);
3657 
3658  if (AH->intSize > sizeof(int))
3659  write_msg(modulename, "WARNING: archive was made on a machine with larger integers, some operations might fail\n");
3660 
3661  if (AH->version >= K_VERS_1_7)
3662  AH->offSize = (*AH->ReadBytePtr) (AH);
3663  else
3664  AH->offSize = AH->intSize;
3665 
3666  fmt = (*AH->ReadBytePtr) (AH);
3667 
3668  if (AH->format != fmt)
3669  exit_horribly(modulename, "expected format (%d) differs from format found in file (%d)\n",
3670  AH->format, fmt);
3671  }
3672 
3673  if (AH->version >= K_VERS_1_2)
3674  {
3675  if (AH->version < K_VERS_1_4)
3676  AH->compression = (*AH->ReadBytePtr) (AH);
3677  else
3678  AH->compression = ReadInt(AH);
3679  }
3680  else
3682 
3683 #ifndef HAVE_LIBZ
3684  if (AH->compression != 0)
3685  write_msg(modulename, "WARNING: archive is compressed, but this installation does not support compression -- no data will be available\n");
3686 #endif
3687 
3688  if (AH->version >= K_VERS_1_4)
3689  {
3690  crtm.tm_sec = ReadInt(AH);
3691  crtm.tm_min = ReadInt(AH);
3692  crtm.tm_hour = ReadInt(AH);
3693  crtm.tm_mday = ReadInt(AH);
3694  crtm.tm_mon = ReadInt(AH);
3695  crtm.tm_year = ReadInt(AH);
3696  crtm.tm_isdst = ReadInt(AH);
3697 
3698  AH->archdbname = ReadStr(AH);
3699 
3700  AH->createDate = mktime(&crtm);
3701 
3702  if (AH->createDate == (time_t) -1)
3703  write_msg(modulename, "WARNING: invalid creation date in header\n");
3704  }
3705 
3706  if (AH->version >= K_VERS_1_10)
3707  {
3708  AH->archiveRemoteVersion = ReadStr(AH);
3709  AH->archiveDumpVersion = ReadStr(AH);
3710  }
3711 }
3712 
3713 
3714 /*
3715  * checkSeek
3716  * check to see if ftell/fseek can be performed.
3717  */
3718 bool
3719 checkSeek(FILE *fp)
3720 {
3721  pgoff_t tpos;
3722 
3723  /*
3724  * If pgoff_t is wider than long, we must have "real" fseeko and not an
3725  * emulation using fseek. Otherwise report no seek capability.
3726  */
3727 #ifndef HAVE_FSEEKO
3728  if (sizeof(pgoff_t) > sizeof(long))
3729  return false;
3730 #endif
3731 
3732  /* Check that ftello works on this file */
3733  tpos = ftello(fp);
3734  if (tpos < 0)
3735  return false;
3736 
3737  /*
3738  * Check that fseeko(SEEK_SET) works, too. NB: we used to try to test
3739  * this with fseeko(fp, 0, SEEK_CUR). But some platforms treat that as a
3740  * successful no-op even on files that are otherwise unseekable.
3741  */
3742  if (fseeko(fp, tpos, SEEK_SET) != 0)
3743  return false;
3744 
3745  return true;
3746 }
3747 
3748 
3749 /*
3750  * dumpTimestamp
3751  */
3752 static void
3753 dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim)
3754 {
3755  char buf[64];
3756 
3757  if (strftime(buf, sizeof(buf), PGDUMP_STRFTIME_FMT, localtime(&tim)) != 0)
3758  ahprintf(AH, "-- %s %s\n\n", msg, buf);
3759 }
3760 
3761 /*
3762  * Main engine for parallel restore.
3763  *
3764  * Work is done in three phases.
3765  * First we process all SECTION_PRE_DATA tocEntries, in a single connection,
3766  * just as for a standard restore. Second we process the remaining non-ACL
3767  * steps in parallel worker children (threads on Windows, processes on Unix),
3768  * each of which connects separately to the database. Finally we process all
3769  * the ACL entries in a single connection (that happens back in
3770  * RestoreArchive).
3771  */
3772 static void
3774 {
3775  bool skipped_some;
3776  TocEntry *next_work_item;
3777 
3778  ahlog(AH, 2, "entering restore_toc_entries_prefork\n");
3779 
3780  /* Adjust dependency information */
3781  fix_dependencies(AH);
3782 
3783  /*
3784  * Do all the early stuff in a single connection in the parent. There's no
3785  * great point in running it in parallel, in fact it will actually run
3786  * faster in a single connection because we avoid all the connection and
3787  * setup overhead. Also, pre-9.2 pg_dump versions were not very good
3788  * about showing all the dependencies of SECTION_PRE_DATA items, so we do
3789  * not risk trying to process them out-of-order.
3790  *
3791  * Note: as of 9.2, it should be guaranteed that all PRE_DATA items appear
3792  * before DATA items, and all DATA items before POST_DATA items. That is
3793  * not certain to be true in older archives, though, so this loop is coded
3794  * to not assume it.
3795  */
3796  skipped_some = false;
3797  for (next_work_item = AH->toc->next; next_work_item != AH->toc; next_work_item = next_work_item->next)
3798  {
3799  /* NB: process-or-continue logic must be the inverse of loop below */
3800  if (next_work_item->section != SECTION_PRE_DATA)
3801  {
3802  /* DATA and POST_DATA items are just ignored for now */
3803  if (next_work_item->section == SECTION_DATA ||
3804  next_work_item->section == SECTION_POST_DATA)
3805  {
3806  skipped_some = true;
3807  continue;
3808  }
3809  else
3810  {
3811  /*
3812  * SECTION_NONE items, such as comments, can be processed now
3813  * if we are still in the PRE_DATA part of the archive. Once
3814  * we've skipped any items, we have to consider whether the
3815  * comment's dependencies are satisfied, so skip it for now.
3816  */
3817  if (skipped_some)
3818  continue;
3819  }
3820  }
3821 
3822  ahlog(AH, 1, "processing item %d %s %s\n",
3823  next_work_item->dumpId,
3824  next_work_item->desc, next_work_item->tag);
3825 
3826  (void) restore_toc_entry(AH, next_work_item, false);
3827 
3828  /* there should be no touch of ready_list here, so pass NULL */
3829  reduce_dependencies(AH, next_work_item, NULL);
3830  }
3831 
3832  /*
3833  * Now close parent connection in prep for parallel steps. We do this
3834  * mainly to ensure that we don't exceed the specified number of parallel
3835  * connections.
3836  */
3837  DisconnectDatabase(&AH->public);
3838 
3839  /* blow away any transient state from the old connection */
3840  if (AH->currUser)
3841  free(AH->currUser);
3842  AH->currUser = NULL;
3843  if (AH->currSchema)
3844  free(AH->currSchema);
3845  AH->currSchema = NULL;
3846  if (AH->currTablespace)
3847  free(AH->currTablespace);
3848  AH->currTablespace = NULL;
3849  AH->currWithOids = -1;
3850 }
3851 
3852 /*
3853  * Main engine for parallel restore.
3854  *
3855  * Work is done in three phases.
3856  * First we process all SECTION_PRE_DATA tocEntries, in a single connection,
3857  * just as for a standard restore. This is done in restore_toc_entries_prefork().
3858  * Second we process the remaining non-ACL steps in parallel worker children
3859  * (threads on Windows, processes on Unix), these fork off and set up their
3860  * connections before we call restore_toc_entries_parallel_forked.
3861  * Finally we process all the ACL entries in a single connection (that happens
3862  * back in RestoreArchive).
3863  */
3864 static void
3866  TocEntry *pending_list)
3867 {
3868  bool skipped_some;
3869  TocEntry ready_list;
3870  TocEntry *next_work_item;
3871 
3872  ahlog(AH, 2, "entering restore_toc_entries_parallel\n");
3873 
3874  /*
3875  * Initialize the lists of ready items, the list for pending items has
3876  * already been initialized in the caller. After this setup, the pending
3877  * list is everything that needs to be done but is blocked by one or more
3878  * dependencies, while the ready list contains items that have no
3879  * remaining dependencies. Note: we don't yet filter out entries that
3880  * aren't going to be restored. They might participate in dependency
3881  * chains connecting entries that should be restored, so we treat them as
3882  * live until we actually process them.
3883  */
3884  par_list_header_init(&ready_list);
3885  skipped_some = false;
3886  for (next_work_item = AH->toc->next; next_work_item != AH->toc; next_work_item = next_work_item->next)
3887  {
3888  /* NB: process-or-continue logic must be the inverse of loop above */
3889  if (next_work_item->section == SECTION_PRE_DATA)
3890  {
3891  /* All PRE_DATA items were dealt with above */
3892  continue;
3893  }
3894  if (next_work_item->section == SECTION_DATA ||
3895  next_work_item->section == SECTION_POST_DATA)
3896  {
3897  /* set this flag at same point that previous loop did */
3898  skipped_some = true;
3899  }
3900  else
3901  {
3902  /* SECTION_NONE items must be processed if previous loop didn't */
3903  if (!skipped_some)
3904  continue;
3905  }
3906 
3907  if (next_work_item->depCount > 0)
3908  par_list_append(pending_list, next_work_item);
3909  else
3910  par_list_append(&ready_list, next_work_item);
3911  }
3912 
3913  /*
3914  * main parent loop
3915  *
3916  * Keep going until there is no worker still running AND there is no work
3917  * left to be done.
3918  */
3919 
3920  ahlog(AH, 1, "entering main parallel loop\n");
3921 
3922  while ((next_work_item = get_next_work_item(AH, &ready_list, pstate)) != NULL ||
3923  !IsEveryWorkerIdle(pstate))
3924  {
3925  if (next_work_item != NULL)
3926  {
3927  /* If not to be restored, don't waste time launching a worker */
3928  if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA)) == 0 ||
3929  _tocEntryIsACL(next_work_item))
3930  {
3931  ahlog(AH, 1, "skipping item %d %s %s\n",
3932  next_work_item->dumpId,
3933  next_work_item->desc, next_work_item->tag);
3934 
3935  par_list_remove(next_work_item);
3936  reduce_dependencies(AH, next_work_item, &ready_list);
3937 
3938  continue;
3939  }
3940 
3941  ahlog(AH, 1, "launching item %d %s %s\n",
3942  next_work_item->dumpId,
3943  next_work_item->desc, next_work_item->tag);
3944 
3945  par_list_remove(next_work_item);
3946 
3947  DispatchJobForTocEntry(AH, pstate, next_work_item, ACT_RESTORE,
3948  mark_restore_job_done, &ready_list);
3949  }
3950  else
3951  {
3952  /* at least one child is working and we have nothing ready. */
3953  }
3954 
3955  /*
3956  * Before dispatching another job, check to see if anything has
3957  * finished. We should check every time through the loop so as to
3958  * reduce dependencies as soon as possible. If we were unable to
3959  * dispatch any job this time through, wait until some worker finishes
3960  * (and, hopefully, unblocks some pending item). If we did dispatch
3961  * something, continue as soon as there's at least one idle worker.
3962  * Note that in either case, there's guaranteed to be at least one
3963  * idle worker when we return to the top of the loop. This ensures we
3964  * won't block inside DispatchJobForTocEntry, which would be
3965  * undesirable: we'd rather postpone dispatching until we see what's
3966  * been unblocked by finished jobs.
3967  */
3968  WaitForWorkers(AH, pstate,
3969  next_work_item ? WFW_ONE_IDLE : WFW_GOT_STATUS);
3970  }
3971 
3972  ahlog(AH, 1, "finished main parallel loop\n");
3973 }
3974 
3975 static void
3977 {
3978  RestoreOptions *ropt = AH->public.ropt;
3979  TocEntry *te;
3980 
3981  ahlog(AH, 2, "entering restore_toc_entries_postfork\n");
3982 
3983  /*
3984  * Now reconnect the single parent connection.
3985  */
3986  ConnectDatabase((Archive *) AH, ropt->dbname,
3987  ropt->pghost, ropt->pgport, ropt->username,
3988  ropt->promptPassword);
3989 
3990  /* re-establish fixed state */
3992 
3993  /*
3994  * Make sure there is no non-ACL work left due to, say, circular
3995  * dependencies, or some other pathological condition. If so, do it in the
3996  * single parent connection.
3997  */
3998  for (te = pending_list->par_next; te != pending_list; te = te->par_next)
3999  {
4000  ahlog(AH, 1, "processing missed item %d %s %s\n",
4001  te->dumpId, te->desc, te->tag);
4002  (void) restore_toc_entry(AH, te, false);
4003  }
4004 
4005  /* The ACLs will be handled back in RestoreArchive. */
4006 }
4007 
4008 /*
4009  * Check if te1 has an exclusive lock requirement for an item that te2 also
4010  * requires, whether or not te2's requirement is for an exclusive lock.
4011  */
4012 static bool
4014 {
4015  int j,
4016  k;
4017 
4018  for (j = 0; j < te1->nLockDeps; j++)
4019  {
4020  for (k = 0; k < te2->nDeps; k++)
4021  {
4022  if (te1->lockDeps[j] == te2->dependencies[k])
4023  return true;
4024  }
4025  }
4026  return false;
4027 }
4028 
4029 
4030 /*
4031  * Initialize the header of a parallel-processing list.
4032  *
4033  * These are circular lists with a dummy TocEntry as header, just like the
4034  * main TOC list; but we use separate list links so that an entry can be in
4035  * the main TOC list as well as in a parallel-processing list.
4036  */
4037 static void
4039 {
4040  l->par_prev = l->par_next = l;
4041 }
4042 
4043 /* Append te to the end of the parallel-processing list headed by l */
4044 static void
4046 {
4047  te->par_prev = l->par_prev;
4048  l->par_prev->par_next = te;
4049  l->par_prev = te;
4050  te->par_next = l;
4051 }
4052 
4053 /* Remove te from whatever parallel-processing list it's in */
4054 static void
4056 {
4057  te->par_prev->par_next = te->par_next;
4058  te->par_next->par_prev = te->par_prev;
4059  te->par_prev = NULL;
4060  te->par_next = NULL;
4061 }
4062 
4063 
4064 /*
4065  * Find the next work item (if any) that is capable of being run now.
4066  *
4067  * To qualify, the item must have no remaining dependencies
4068  * and no requirements for locks that are incompatible with
4069  * items currently running. Items in the ready_list are known to have
4070  * no remaining dependencies, but we have to check for lock conflicts.
4071  *
4072  * Note that the returned item has *not* been removed from ready_list.
4073  * The caller must do that after successfully dispatching the item.
4074  *
4075  * pref_non_data is for an alternative selection algorithm that gives
4076  * preference to non-data items if there is already a data load running.
4077  * It is currently disabled.
4078  */
4079 static TocEntry *
4081  ParallelState *pstate)
4082 {
4083  bool pref_non_data = false; /* or get from AH->ropt */
4084  TocEntry *data_te = NULL;
4085  TocEntry *te;
4086  int i,
4087  k;
4088 
4089  /*
4090  * Bogus heuristics for pref_non_data
4091  */
4092  if (pref_non_data)
4093  {
4094  int count = 0;
4095 
4096  for (k = 0; k < pstate->numWorkers; k++)
4097  {
4098  TocEntry *running_te = pstate->te[k];
4099 
4100  if (running_te != NULL &&
4101  running_te->section == SECTION_DATA)
4102  count++;
4103  }
4104  if (pstate->numWorkers == 0 || count * 4 < pstate->numWorkers)
4105  pref_non_data = false;
4106  }
4107 
4108  /*
4109  * Search the ready_list until we find a suitable item.
4110  */
4111  for (te = ready_list->par_next; te != ready_list; te = te->par_next)
4112  {
4113  bool conflicts = false;
4114 
4115  /*
4116  * Check to see if the item would need exclusive lock on something
4117  * that a currently running item also needs lock on, or vice versa. If
4118  * so, we don't want to schedule them together.
4119  */
4120  for (i = 0; i < pstate->numWorkers; i++)
4121  {
4122  TocEntry *running_te = pstate->te[i];
4123 
4124  if (running_te == NULL)
4125  continue;
4126  if (has_lock_conflicts(te, running_te) ||
4127  has_lock_conflicts(running_te, te))
4128  {
4129  conflicts = true;
4130  break;
4131  }
4132  }
4133 
4134  if (conflicts)
4135  continue;
4136 
4137  if (pref_non_data && te->section == SECTION_DATA)
4138  {
4139  if (data_te == NULL)
4140  data_te = te;
4141  continue;
4142  }
4143 
4144  /* passed all tests, so this item can run */
4145  return te;
4146  }
4147 
4148  if (data_te != NULL)
4149  return data_te;
4150 
4151  ahlog(AH, 2, "no item ready\n");
4152  return NULL;
4153 }
4154 
4155 
4156 /*
4157  * Restore a single TOC item in parallel with others
4158  *
4159  * this is run in the worker, i.e. in a thread (Windows) or a separate process
4160  * (everything else). A worker process executes several such work items during
4161  * a parallel backup or restore. Once we terminate here and report back that
4162  * our work is finished, the master process will assign us a new work item.
4163  */
4164 int
4166 {
4167  int status;
4168 
4169  Assert(AH->connection != NULL);
4170 
4171  /* Count only errors associated with this TOC entry */
4172  AH->public.n_errors = 0;
4173 
4174  /* Restore the TOC item */
4175  status = restore_toc_entry(AH, te, true);
4176 
4177  return status;
4178 }
4179 
4180 
4181 /*
4182  * Callback function that's invoked in the master process after a step has
4183  * been parallel restored.
4184  *
4185  * Update status and reduce the dependency count of any dependent items.
4186  */
4187 static void
4189  TocEntry *te,
4190  int status,
4191  void *callback_data)
4192 {
4193  TocEntry *ready_list = (TocEntry *) callback_data;
4194 
4195  ahlog(AH, 1, "finished item %d %s %s\n",
4196  te->dumpId, te->desc, te->tag);
4197 
4198  if (status == WORKER_CREATE_DONE)
4199  mark_create_done(AH, te);
4200  else if (status == WORKER_INHIBIT_DATA)
4201  {
4203  AH->public.n_errors++;
4204  }
4205  else if (status == WORKER_IGNORED_ERRORS)
4206  AH->public.n_errors++;
4207  else if (status != 0)
4208  exit_horribly(modulename, "worker process failed: exit code %d\n",
4209  status);
4210 
4211  reduce_dependencies(AH, te, ready_list);
4212 }
4213 
4214 
4215 /*
4216  * Process the dependency information into a form useful for parallel restore.
4217  *
4218  * This function takes care of fixing up some missing or badly designed
4219  * dependencies, and then prepares subsidiary data structures that will be
4220  * used in the main parallel-restore logic, including:
4221  * 1. We build the revDeps[] arrays of incoming dependency dumpIds.
4222  * 2. We set up depCount fields that are the number of as-yet-unprocessed
4223  * dependencies for each TOC entry.
4224  *
4225  * We also identify locking dependencies so that we can avoid trying to
4226  * schedule conflicting items at the same time.
4227  */
4228 static void
4230 {
4231  TocEntry *te;
4232  int i;
4233 
4234  /*
4235  * Initialize the depCount/revDeps/nRevDeps fields, and make sure the TOC
4236  * items are marked as not being in any parallel-processing list.
4237  */
4238  for (te = AH->toc->next; te != AH->toc; te = te->next)
4239  {
4240  te->depCount = te->nDeps;
4241  te->revDeps = NULL;
4242  te->nRevDeps = 0;
4243  te->par_prev = NULL;
4244  te->par_next = NULL;
4245  }
4246 
4247  /*
4248  * POST_DATA items that are shown as depending on a table need to be
4249  * re-pointed to depend on that table's data, instead. This ensures they
4250  * won't get scheduled until the data has been loaded.
4251  */
4253 
4254  /*
4255  * Pre-8.4 versions of pg_dump neglected to set up a dependency from BLOB
4256  * COMMENTS to BLOBS. Cope. (We assume there's only one BLOBS and only
4257  * one BLOB COMMENTS in such files.)
4258  */
4259  if (AH->version < K_VERS_1_11)
4260  {
4261  for (te = AH->toc->next; te != AH->toc; te = te->next)
4262  {
4263  if (strcmp(te->desc, "BLOB COMMENTS") == 0 && te->nDeps == 0)
4264  {
4265  TocEntry *te2;
4266 
4267  for (te2 = AH->toc->next; te2 != AH->toc; te2 = te2->next)
4268  {
4269  if (strcmp(te2->desc, "BLOBS") == 0)
4270  {
4271  te->dependencies = (DumpId *) pg_malloc(sizeof(DumpId));
4272  te->dependencies[0] = te2->dumpId;
4273  te->nDeps++;
4274  te->depCount++;
4275  break;
4276  }
4277  }
4278  break;
4279  }
4280  }
4281  }
4282 
4283  /*
4284  * At this point we start to build the revDeps reverse-dependency arrays,
4285  * so all changes of dependencies must be complete.
4286  */
4287 
4288  /*
4289  * Count the incoming dependencies for each item. Also, it is possible
4290  * that the dependencies list items that are not in the archive at all
4291  * (that should not happen in 9.2 and later, but is highly likely in older
4292  * archives). Subtract such items from the depCounts.
4293  */
4294  for (te = AH->toc->next; te != AH->toc; te = te->next)
4295  {
4296  for (i = 0; i < te->nDeps; i++)
4297  {
4298  DumpId depid = te->dependencies[i];
4299 
4300  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4301  AH->tocsByDumpId[depid]->nRevDeps++;
4302  else
4303  te->depCount--;
4304  }
4305  }
4306 
4307  /*
4308  * Allocate space for revDeps[] arrays, and reset nRevDeps so we can use
4309  * it as a counter below.
4310  */
4311  for (te = AH->toc->next; te != AH->toc; te = te->next)
4312  {
4313  if (te->nRevDeps > 0)
4314  te->revDeps = (DumpId *) pg_malloc(te->nRevDeps * sizeof(DumpId));
4315  te->nRevDeps = 0;
4316  }
4317 
4318  /*
4319  * Build the revDeps[] arrays of incoming-dependency dumpIds. This had
4320  * better agree with the loops above.
4321  */
4322  for (te = AH->toc->next; te != AH->toc; te = te->next)
4323  {
4324  for (i = 0; i < te->nDeps; i++)
4325  {
4326  DumpId depid = te->dependencies[i];
4327 
4328  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL)
4329  {
4330  TocEntry *otherte = AH->tocsByDumpId[depid];
4331 
4332  otherte->revDeps[otherte->nRevDeps++] = te->dumpId;
4333  }
4334  }
4335  }
4336 
4337  /*
4338  * Lastly, work out the locking dependencies.
4339  */
4340  for (te = AH->toc->next; te != AH->toc; te = te->next)
4341  {
4342  te->lockDeps = NULL;
4343  te->nLockDeps = 0;
4345  }
4346 }
4347 
4348 /*
4349  * Change dependencies on table items to depend on table data items instead,
4350  * but only in POST_DATA items.
4351  */
4352 static void
4354 {
4355  TocEntry *te;
4356  int i;
4357  DumpId olddep;
4358 
4359  for (te = AH->toc->next; te != AH->toc; te = te->next)
4360  {
4361  if (te->section != SECTION_POST_DATA)
4362  continue;
4363  for (i = 0; i < te->nDeps; i++)
4364  {
4365  olddep = te->dependencies[i];
4366  if (olddep <= AH->maxDumpId &&
4367  AH->tableDataId[olddep] != 0)
4368  {
4369  te->dependencies[i] = AH->tableDataId[olddep];
4370  ahlog(AH, 2, "transferring dependency %d -> %d to %d\n",
4371  te->dumpId, olddep, AH->tableDataId[olddep]);
4372  }
4373  }
4374  }
4375 }
4376 
4377 /*
4378  * Identify which objects we'll need exclusive lock on in order to restore
4379  * the given TOC entry (*other* than the one identified by the TOC entry
4380  * itself). Record their dump IDs in the entry's lockDeps[] array.
4381  */
4382 static void
4384 {
4385  DumpId *lockids;
4386  int nlockids;
4387  int i;
4388 
4389  /* Quick exit if no dependencies at all */
4390  if (te->nDeps == 0)
4391  return;
4392 
4393  /* Exit if this entry doesn't need exclusive lock on other objects */
4394  if (!(strcmp(te->desc, "CONSTRAINT") == 0 ||
4395  strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
4396  strcmp(te->desc, "FK CONSTRAINT") == 0 ||
4397  strcmp(te->desc, "RULE") == 0 ||
4398  strcmp(te->desc, "TRIGGER") == 0))
4399  return;
4400 
4401  /*
4402  * We assume the entry requires exclusive lock on each TABLE or TABLE DATA
4403  * item listed among its dependencies. Originally all of these would have
4404  * been TABLE items, but repoint_table_dependencies would have repointed
4405  * them to the TABLE DATA items if those are present (which they might not
4406  * be, eg in a schema-only dump). Note that all of the entries we are
4407  * processing here are POST_DATA; otherwise there might be a significant
4408  * difference between a dependency on a table and a dependency on its
4409  * data, so that closer analysis would be needed here.
4410  */
4411  lockids = (DumpId *) pg_malloc(te->nDeps * sizeof(DumpId));
4412  nlockids = 0;
4413  for (i = 0; i < te->nDeps; i++)
4414  {
4415  DumpId depid = te->dependencies[i];
4416 
4417  if (depid <= AH->maxDumpId && AH->tocsByDumpId[depid] != NULL &&
4418  ((strcmp(AH->tocsByDumpId[depid]->desc, "TABLE DATA") == 0) ||
4419  strcmp(AH->tocsByDumpId[depid]->desc, "TABLE") == 0))
4420  lockids[nlockids++] = depid;
4421  }
4422 
4423  if (nlockids == 0)
4424  {
4425  free(lockids);
4426  return;
4427  }
4428 
4429  te->lockDeps = pg_realloc(lockids, nlockids * sizeof(DumpId));
4430  te->nLockDeps = nlockids;
4431 }
4432 
4433 /*
4434  * Remove the specified TOC entry from the depCounts of items that depend on
4435  * it, thereby possibly making them ready-to-run. Any pending item that
4436  * becomes ready should be moved to the ready list.
4437  */
4438 static void
4440 {
4441  int i;
4442 
4443  ahlog(AH, 2, "reducing dependencies for %d\n", te->dumpId);
4444 
4445  for (i = 0; i < te->nRevDeps; i++)
4446  {
4447  TocEntry *otherte = AH->tocsByDumpId[te->revDeps[i]];
4448 
4449  otherte->depCount--;
4450  if (otherte->depCount == 0 && otherte->par_prev != NULL)
4451  {
4452  /* It must be in the pending list, so remove it ... */
4453  par_list_remove(otherte);
4454  /* ... and add to ready_list */
4455  par_list_append(ready_list, otherte);
4456  }
4457  }
4458 }
4459 
4460 /*
4461  * Set the created flag on the DATA member corresponding to the given
4462  * TABLE member
4463  */
4464 static void
4466 {
4467  if (AH->tableDataId[te->dumpId] != 0)
4468  {
4469  TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4470 
4471  ted->created = true;
4472  }
4473 }
4474 
4475 /*
4476  * Mark the DATA member corresponding to the given TABLE member
4477  * as not wanted
4478  */
4479 static void
4481 {
4482  ahlog(AH, 1, "table \"%s\" could not be created, will not restore its data\n",
4483  te->tag);
4484 
4485  if (AH->tableDataId[te->dumpId] != 0)
4486  {
4487  TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]];
4488 
4489  ted->reqs = 0;
4490  }
4491 }
4492 
4493 /*
4494  * Clone and de-clone routines used in parallel restoration.
4495  *
4496  * Enough of the structure is cloned to ensure that there is no
4497  * conflict between different threads each with their own clone.
4498  */
4499 ArchiveHandle *
4501 {
4502  ArchiveHandle *clone;
4503 
4504  /* Make a "flat" copy */
4505  clone = (ArchiveHandle *) pg_malloc(sizeof(ArchiveHandle));
4506  memcpy(clone, AH, sizeof(ArchiveHandle));
4507 
4508  /* Handle format-independent fields */
4509  memset(&(clone->sqlparse), 0, sizeof(clone->sqlparse));
4510 
4511  /* The clone will have its own connection, so disregard connection state */
4512  clone->connection = NULL;
4513  clone->connCancel = NULL;
4514  clone->currUser = NULL;
4515  clone->currSchema = NULL;
4516  clone->currTablespace = NULL;
4517  clone->currWithOids = -1;
4518 
4519  /* savedPassword must be local in case we change it while connecting */
4520  if (clone->savedPassword)
4521  clone->savedPassword = pg_strdup(clone->savedPassword);
4522 
4523  /* clone has its own error count, too */
4524  clone->public.n_errors = 0;
4525 
4526  /*
4527  * Connect our new clone object to the database: In parallel restore the
4528  * parent is already disconnected, because we can connect the worker
4529  * processes independently to the database (no snapshot sync required). In
4530  * parallel backup we clone the parent's existing connection.
4531  */
4532  if (AH->mode == archModeRead)
4533  {
4534  RestoreOptions *ropt = AH->public.ropt;
4535 
4536  Assert(AH->connection == NULL);
4537 
4538  /* this also sets clone->connection */
4539  ConnectDatabase((Archive *) clone, ropt->dbname,
4540  ropt->pghost, ropt->pgport, ropt->username,
4541  ropt->promptPassword);
4542 
4543  /* re-establish fixed state */
4544  _doSetFixedOutputState(clone);
4545  }
4546  else
4547  {
4549  char *pghost;
4550  char *pgport;
4551  char *username;
4552 
4553  Assert(AH->connection != NULL);
4554 
4555  /*
4556  * Even though we are technically accessing the parent's database
4557  * object here, these functions are fine to be called like that
4558  * because all just return a pointer and do not actually send/receive
4559  * any data to/from the database.
4560  */
4561  initPQExpBuffer(&connstr);
4562  appendPQExpBuffer(&connstr, "dbname=");
4563  appendConnStrVal(&connstr, PQdb(AH->connection));
4564  pghost = PQhost(AH->connection);
4565  pgport = PQport(AH->connection);
4566  username = PQuser(AH->connection);
4567 
4568  /* this also sets clone->connection */
4569  ConnectDatabase((Archive *) clone, connstr.data,
4570  pghost, pgport, username, TRI_NO);
4571 
4572  termPQExpBuffer(&connstr);
4573  /* setupDumpWorker will fix up connection state */
4574  }
4575 
4576  /* Let the format-specific code have a chance too */
4577  (clone->ClonePtr) (clone);
4578 
4579  Assert(clone->connection != NULL);
4580  return clone;
4581 }
4582 
4583 /*
4584  * Release clone-local storage.
4585  *
4586  * Note: we assume any clone-local connection was already closed.
4587  */
4588 void
4590 {
4591  /* Should not have an open database connection */
4592  Assert(AH->connection == NULL);
4593 
4594  /* Clear format-specific state */
4595  (AH->DeClonePtr) (AH);
4596 
4597  /* Clear state allocated by CloneArchive */
4598  if (AH->sqlparse.curCmd)
4600 
4601  /* Clear any connection-local state */
4602  if (AH->currUser)
4603  free(AH->currUser);
4604  if (AH->currSchema)
4605  free(AH->currSchema);
4606  if (AH->currTablespace)
4607  free(AH->currTablespace);
4608  if (AH->savedPassword)
4609  free(AH->savedPassword);
4610 
4611  free(AH);
4612 }
int remaining
Definition: informix.c:692
struct _tocEntry * next
static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te)
static int RestoringToDB(ArchiveHandle *AH)
void ReadToc(ArchiveHandle *AH)
int column_inserts
Definition: pg_backup.h:146
PQExpBuffer curCmd
#define appendByteaLiteralAHX(buf, str, len, AH)
StartBlobsPtr StartBlobsPtr
int disable_triggers
Definition: pg_backup.h:153
int DumpId
Definition: pg_backup.h:229
int parallel_restore(ArchiveHandle *AH, TocEntry *te)
void EndDBCopyMode(Archive *AHX, const char *tocEntryTag)
Definition: pg_backup_db.c:629
void ReadHead(ArchiveHandle *AH)
#define K_VERS_SELF
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:6011
int noDataForFailedTables
Definition: pg_backup.h:111
#define Z_DEFAULT_COMPRESSION
struct _tocEntry * currentTE
static void dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim)
#define K_VERS_1_0
static void mark_restore_job_done(ArchiveHandle *AH, TocEntry *te, int status, void *callback_data)
int pg_char_to_encoding(const char *name)
Definition: encnames.c:551
int ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *newUser)
Definition: pg_backup_db.c:88
void DispatchJobForTocEntry(ArchiveHandle *AH, ParallelState *pstate, TocEntry *te, T_Action act, ParallelCompletionPtr callback, void *callback_data)
Definition: parallel.c:1227
int disable_dollar_quoting
Definition: pg_backup.h:73
bool simple_string_list_member(SimpleStringList *list, const char *val)
Definition: simple_list.c:87
int archprintf(Archive *AH, const char *fmt,...)
int ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen)
Definition: pg_backup_db.c:574
Oid tableoid
Definition: pg_backup.h:225
int EndBlob(Archive *AHX, Oid oid)
static ArchiveHandle * _allocAH(const char *FileSpec, const ArchiveFormat fmt, const int compression, bool dosync, ArchiveMode mode, SetupWorkerPtr setupWorkerPtr)
SimpleStringList triggerNames
Definition: pg_backup.h:103
void DropBlobIfExists(ArchiveHandle *AH, Oid oid)
Definition: pg_backup_db.c:674
void PrintTOCSummary(Archive *AHX)
bool IsEveryWorkerIdle(ParallelState *pstate)
Definition: parallel.c:1290
static void setupRestoreWorker(Archive *AHX)
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
RestoreOptions * ropt
Definition: pg_backup.h:180
static void _becomeUser(ArchiveHandle *AH, const char *user)
const char * fmtId(const char *rawid)
Definition: string_utils.c:66
bool schemaOnly
Definition: pg_backup.h:137
static void restore_toc_entries_postfork(ArchiveHandle *AH, TocEntry *pending_list)
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:128
CatalogId catalogId
const char * simple_string_list_not_touched(SimpleStringList *list)
Definition: simple_list.c:106
PrintTocDataPtr PrintTocDataPtr
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:385
void * dataDumperArg
char * username
Definition: pg_backup.h:110
static void SetOutput(ArchiveHandle *AH, const char *filename, int compression)
int(* DataDumperPtr)(Archive *AH, void *userArg)
Definition: pg_backup.h:231
void WriteDataChunks(ArchiveHandle *AH, ParallelState *pstate)
void ProcessArchiveRestoreOptions(Archive *AHX)
#define TEXT_DUMP_HEADER
static void restore_toc_entries_parallel(ArchiveHandle *AH, ParallelState *pstate, TocEntry *pending_list)
#define gettext_noop(x)
Definition: c.h:139
WriteBufPtr WriteBufPtr
void appendConnStrVal(PQExpBuffer buf, const char *str)
Definition: string_utils.c:536
WriteExtraTocPtr WriteExtraTocPtr
#define K_VERS_1_9
static bool dosync
Definition: pg_dump.c:92
char * PQport(const PGconn *conn)
Definition: fe-connect.c:5932
#define PG_BINARY_W
Definition: c.h:1041
#define WORKER_CREATE_DONE
void WriteToc(ArchiveHandle *AH)
void InitArchiveFmt_Tar(ArchiveHandle *AH)
return result
Definition: formatting.c:1618
DumpOptions * NewDumpOptions(void)
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
static void restore_toc_entries_prefork(ArchiveHandle *AH)
DataDumperPtr dataDumper
int ReadInt(ArchiveHandle *AH)
char * use_role
Definition: pg_backup.h:71
SimpleStringList schemaNames
Definition: pg_backup.h:101
SetupWorkerPtr SetupWorkerPtr
int n_errors
Definition: pg_backup.h:201
PGcancel *volatile connCancel
int sequence_data
Definition: pg_backup.h:170
unsigned int Oid
Definition: postgres_ext.h:31
int PQserverVersion(const PGconn *conn)
Definition: fe-connect.c:6001
#define fseeko(stream, offset, origin)
Definition: win32.h:247
int include_subscriptions
Definition: pg_backup.h:157
bool isValidTarHeader(char *header)
static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te)
#define PG_BINARY_R
Definition: c.h:1040
DumpId * lockDeps
int encoding
Definition: pg_backup.h:195
#define K_VERS_1_4
void CloseArchive(Archive *AHX)
void StartRestoreBlobs(ArchiveHandle *AH)
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:2596
struct _tocEntry * currToc
int maxRemoteVersion
Definition: pg_backup.h:188
#define WORKER_IGNORED_ERRORS
static bool _tocEntryIsACL(TocEntry *te)
teSection section
char * PQuser(const PGconn *conn)
Definition: fe-connect.c:5887
static struct pg_tm tm
Definition: localtime.c:103
void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname)
Definition: string_utils.c:581
#define K_VERS_1_12
#define K_VERS_1_7
void DeCloneArchive(ArchiveHandle *AH)
#define K_VERS_1_5
const char * lockWaitTimeout
Definition: pg_backup.h:86
void warn_or_exit_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...)
int use_setsessauth
Definition: pg_backup.h:155
const char * filename
Definition: pg_backup.h:80
void destroyPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:113
int lo_close(PGconn *conn, int fd)
Definition: fe-lobj.c:100
void(* EndDataPtr)(ArchiveHandle *AH, TocEntry *te)
int disable_dollar_quoting
Definition: pg_backup.h:144
size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args)
Definition: psprintf.c:104
bool * idWanted
Definition: pg_backup.h:119
static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te, bool is_parallel)
RestoreOptions * NewRestoreOptions(void)
void * pg_malloc0(size_t size)
Definition: fe_memutils.c:53
DumpOptions * dopt
Definition: pg_backup.h:179
#define MAXPGPATH
PrintExtraTocPtr PrintExtraTocPtr
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:262
int column_inserts
Definition: pg_backup.h:75
#define MAKE_ARCHIVE_VERSION(major, minor, rev)
void StartRestoreBlob(ArchiveHandle *AH, Oid oid, bool drop)
static char * replace_line_endings(const char *str)
const char * lockWaitTimeout
Definition: pg_backup.h:141
#define K_VERS_1_2
char sign
Definition: informix.c:693
bool dataOnly
Definition: pg_backup.h:138
WriteBytePtr WriteBytePtr
bool include_everything
Definition: pg_backup.h:161
SimpleStringList tableNames
Definition: pg_backup.h:104
char * c
struct _tocEntry * toc
static char * buf
Definition: pg_test_fsync.c:65
TocEntry * getTocEntryByDumpId(ArchiveHandle *AH, DumpId id)
DumpId * dependencies
#define K_VERS_1_8
static void _setWithOids(ArchiveHandle *AH, TocEntry *te)
ArchiveHandle * CloneArchive(ArchiveHandle *AH)
#define K_VERS_1_10
char * tablespace
Definition: pgbench.c:146
char * outputSuperuser
Definition: pg_backup.h:168
static void par_list_header_init(TocEntry *l)
static void dump_lo_buf(ArchiveHandle *AH)
SimpleStringList functionNames
Definition: pg_backup.h:100
void ArchiveEntry(Archive *AHX, CatalogId catalogId, DumpId dumpId, const char *tag, const char *namespace, const char *tablespace, const char *owner, bool withOids, const char *desc, teSection section, const char *defn, const char *dropStmt, const char *copyStmt, const DumpId *deps, int nDeps, DataDumperPtr dumpFn, void *dumpArg)
#define ARCHIVE_REV(version)
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
static void _doSetFixedOutputState(ArchiveHandle *AH)
ArchiveEntryPtr ArchiveEntryPtr
Archive * CreateArchive(const char *FileSpec, const ArchiveFormat fmt, const int compression, bool dosync, ArchiveMode mode, SetupWorkerPtr setupDumpWorker)
ReadBytePtr ReadBytePtr
void SetArchiveOptions(Archive *AH, DumpOptions *dopt, RestoreOptions *ropt)
struct _tocEntry * par_prev
int StartBlob(Archive *AHX, Oid oid)
int include_everything
Definition: pg_backup.h:87
DumpOptions * dumpOptionsFromRestoreOptions(RestoreOptions *ropt)
Archive * OpenArchive(const char *FileSpec, const ArchiveFormat fmt)
int no_security_labels
Definition: pg_backup.h:77
static void buildTocEntryArrays(ArchiveHandle *AH)
#define K_OFFSET_NO_DATA
void * pg_realloc(void *ptr, size_t size)
Definition: fe_memutils.c:65
static void _becomeOwner(ArchiveHandle *AH, TocEntry *te)
int dumpSections
Definition: pg_backup.h:139
sqlparseInfo sqlparse
int enable_row_security
Definition: pg_backup.h:120
int dump_inserts
Definition: pg_backup.h:145
void WriteData(Archive *AHX, const void *data, size_t dLen)
int outputNoOwner
Definition: pg_backup.h:167
#define K_VERS_1_3
static void inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te)
int lo_open(PGconn *conn, Oid lobjId, int mode)
Definition: fe-lobj.c:58
void archputs(const char *s, Archive *AH)
int lo_write(int fd, const char *buf, int len)
Definition: be-fsstubs.c:189
void DisconnectDatabase(Archive *AHX)
Definition: pg_backup_db.c:345
int no_security_labels
Definition: pg_backup.h:148
int ahprintf(ArchiveHandle *AH, const char *fmt,...)
ParallelState * ParallelBackupStart(ArchiveHandle *AH)
Definition: parallel.c:909
size_t WriteOffset(ArchiveHandle *AH, pgoff_t o, int wasSet)
#define WORKER_INHIBIT_DATA
#define ARCHIVE_MINOR(version)
void SortTocFromFile(Archive *AHX)
static void mark_create_done(ArchiveHandle *AH, TocEntry *te)
char * pghost
Definition: pgbench.c:180
#define GZWRITE(p, s, n, fh)
struct _tocEntry * par_next
void ParallelBackupEnd(ArchiveHandle *AH, ParallelState *pstate)
Definition: parallel.c:1079
void EndRestoreBlobs(ArchiveHandle *AH)
char * superuser
Definition: pg_backup.h:70
static void _reconnectToDB(ArchiveHandle *AH, const char *dbname)
struct _tocEntry * prev
#define pgoff_t
Definition: win32.h:241
#define ngettext(s, p, n)
Definition: c.h:127
#define exit_nicely(code)
Definition: pg_dumpall.c:89
ArchiveFormat format
ArchiverStage stage
int ReadOffset(ArchiveHandle *AH, pgoff_t *o)
#define TEXT_DUMPALL_HEADER
CustomOutPtr CustomOutPtr
static void fix_dependencies(ArchiveHandle *AH)
bool aclsSkip
Definition: pg_backup.h:140
PQExpBuffer createPQExpBuffer(void)
Definition: pqexpbuffer.c:71
int use_setsessauth
Definition: pg_backup.h:68
int verbose
Definition: pg_backup.h:182
static void StrictNamesCheck(RestoreOptions *ropt)
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:396
static int _discoverArchiveFormat(ArchiveHandle *AH)
#define ARCHIVE_MAJOR(version)
static int sig
Definition: pg_ctl.c:76
static OutputContext SaveOutput(ArchiveHandle *AH)
void WaitForWorkers(ArchiveHandle *AH, ParallelState *pstate, WFW_WaitOption mode)
Definition: parallel.c:1475
int enable_row_security
Definition: pg_backup.h:156
static char * username
Definition: initdb.c:131
#define InvalidOid
Definition: postgres_ext.h:36
void InitArchiveFmt_Directory(ArchiveHandle *AH)
enum _archiveFormat ArchiveFormat
#define K_VERS_MAX
char * PQhost(const PGconn *conn)
Definition: fe-connect.c:5912
void PQclear(PGresult *res)
Definition: fe-exec.c:650
static void reduce_dependencies(ArchiveHandle *AH, TocEntry *te, TocEntry *ready_list)
void InitArchiveFmt_Null(ArchiveHandle *AH)
static void * fn(void *arg)
static char * encoding
Definition: initdb.c:122
static void StartTransaction(void)
Definition: xact.c:1802
#define free(a)
Definition: header.h:65
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:607
enum _teSection teSection
Oid lo_create(PGconn *conn, Oid lobjId)
Definition: fe-lobj.c:505
char * PQdb(const PGconn *conn)
Definition: fe-connect.c:5879
void InitArchiveFmt_Custom(ArchiveHandle *AH)
void write_msg(const char *modulename, const char *fmt,...)
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
char * ReadStr(ArchiveHandle *AH)
TocEntry ** te
Definition: parallel.h:44
teReqs TocIDRequired(ArchiveHandle *AH, DumpId id)
#define PG_BINARY_A
Definition: c.h:1039
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
#define ftello(stream)
Definition: win32.h:250
SimpleStringListCell * head
Definition: simple_list.h:42
int outputCreateDB
Definition: pg_backup.h:164
ArchiveMode
Definition: xlog.h:115
int outputClean
Definition: pg_backup.h:163
char * dbname
Definition: streamutil.c:38
WriteDataPtr WriteDataPtr
static void _moveBefore(ArchiveHandle *AH, TocEntry *pos, TocEntry *te)
size_t WriteInt(ArchiveHandle *AH, int i)
static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
DumpId * revDeps
void(* StartDataPtr)(ArchiveHandle *AH, TocEntry *te)
#define PGDUMP_STRFTIME_FMT
Definition: dumputils.h:33
int numWorkers
Definition: pg_backup.h:190
#define GZCLOSE(fh)
void pg_free(void *ptr)
Definition: fe_memutils.c:105
static void par_list_append(TocEntry *l, TocEntry *te)
ArchiverOutput outputKind
static void RestoreOutput(ArchiveHandle *AH, OutputContext savedContext)
#define WORKER_OK
#define INV_WRITE
Definition: libpq-fs.h:21
struct _outputContext OutputContext
void(* SetupWorkerPtr)(Archive *AH)
Definition: pg_backup.h:233
#define appendStringLiteralAHX(buf, str, AH)
void WriteHead(ArchiveHandle *AH)
struct _tocEntry ** tocsByDumpId
int include_subscriptions
Definition: pg_backup.h:122
#define WRITE_ERROR_EXIT
void WriteDataChunksForTocEntry(ArchiveHandle *AH, TocEntry *te)
void exit_horribly(const char *modulename, const char *fmt,...)
StartDataPtr StartDataPtr
static teReqs _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt)
SimpleStringList indexNames
Definition: pg_backup.h:99
int outputNoTablespaces
Definition: pg_backup.h:154
EndBlobsPtr EndBlobsPtr
static void identify_locking_dependencies(ArchiveHandle *AH, TocEntry *te)
static char * filename
Definition: pg_dumpall.c:87
char * remoteVersionStr
Definition: pg_backup.h:183
static char * user
Definition: pg_regress.c:92
#define K_VERS_1_6
static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te)
void ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
void EndRestoreBlob(ArchiveHandle *AH, Oid oid)
#define K_OFFSET_POS_SET
bool exit_on_error
Definition: pg_backup.h:200
int i
const char * strerror(int errnum)
Definition: strerror.c:19
size_t WriteStr(ArchiveHandle *AH, const char *c)
ArchiverStage lastErrorStage
#define READ_ERROR_EXIT(fd)
static void CommitTransaction(void)
Definition: xact.c:1940
static void par_list_remove(TocEntry *te)
#define K_VERS_1_11
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:1846
static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData, bool acl_pass)
void ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
bool checkSeek(FILE *fp)
int suppressDumpWarnings
Definition: pg_backup.h:115
void RestoreArchive(Archive *AHX)
static TocEntry * get_next_work_item(ArchiveHandle *AH, TocEntry *ready_list, ParallelState *pstate)
SimpleStringList schemaExcludeNames
Definition: pg_backup.h:102
static void _doSetWithOids(ArchiveHandle *AH, const bool withOids)
struct _tocEntry * lastErrorTE
static void _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
static void mark_dump_job_done(ArchiveHandle *AH, TocEntry *te, int status, void *callback_data)
void InitDumpOptions(DumpOptions *opts)
static bool has_lock_conflicts(TocEntry *te1, TocEntry *te2)
static const char * modulename
static void repoint_table_dependencies(ArchiveHandle *AH)
ReadExtraTocPtr ReadExtraTocPtr
static void setupDumpWorker(Archive *AHX)
Definition: pg_dump.c:1146
char * pgport
Definition: pgbench.c:181
char * tocFile
Definition: pg_backup.h:90
void vwrite_msg(const char *modulename, const char *fmt, va_list ap)
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:89
int numWorkers
Definition: parallel.h:42
static void _selectTablespace(ArchiveHandle *AH, const char *tablespace)
bool std_strings
Definition: pg_backup.h:196
int disable_triggers
Definition: pg_backup.h:66
#define K_OFFSET_POS_NOT_SET
void ConnectDatabase(Archive *AH, const char *dbname, const char *pghost, const char *pgport, const char *username, trivalue prompt_password)
Definition: pg_backup_db.c:248
static char * connstr
Definition: pg_dumpall.c:64
trivalue promptPassword
Definition: pg_backup.h:112
StartBlobPtr StartBlobPtr
int minRemoteVersion
Definition: pg_backup.h:187
static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te)