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