]> granicus.if.org Git - postgresql/blob - src/bin/pg_dump/pg_backup_archiver.c
Remove a couple of debugging messages that have been #ifdef'd out for ages.
[postgresql] / src / bin / pg_dump / pg_backup_archiver.c
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  *              $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.171 2009/06/04 19:16:48 tgl Exp $
19  *
20  *-------------------------------------------------------------------------
21  */
22
23 #include "pg_backup_db.h"
24 #include "dumputils.h"
25
26 #include <ctype.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/wait.h>
30
31 #ifdef WIN32
32 #include <io.h>
33 #endif
34
35 #include "libpq/libpq-fs.h"
36
37 /*
38  * Special exit values from worker children.  We reserve 0 for normal
39  * success; 1 and other small values should be interpreted as crashes.
40  */
41 #define WORKER_CREATE_DONE              10
42 #define WORKER_INHIBIT_DATA             11
43 #define WORKER_IGNORED_ERRORS   12
44
45 /*
46  * Unix uses exit to return result from worker child, so function is void.
47  * Windows thread result comes via function return.
48  */
49 #ifndef WIN32
50 #define parallel_restore_result void
51 #else
52 #define parallel_restore_result DWORD
53 #endif
54
55 /* IDs for worker children are either PIDs or thread handles */
56 #ifndef WIN32
57 #define thandle pid_t
58 #else
59 #define thandle HANDLE
60 #endif
61
62 typedef struct _restore_args
63 {
64         ArchiveHandle *AH;
65         TocEntry      *te;
66 } RestoreArgs;
67
68 typedef struct _parallel_slot
69 {
70         thandle         child_id;
71         RestoreArgs *args;
72 } ParallelSlot;
73
74 #define NO_SLOT (-1)
75
76 const char *progname;
77
78 static const char *modulename = gettext_noop("archiver");
79
80
81 static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
82                  const int compression, ArchiveMode mode);
83 static void _getObjectDescription(PQExpBuffer buf, TocEntry *te,
84                                           ArchiveHandle *AH);
85 static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData, bool acl_pass);
86
87
88 static void _doSetFixedOutputState(ArchiveHandle *AH);
89 static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
90 static void _doSetWithOids(ArchiveHandle *AH, const bool withOids);
91 static void _reconnectToDB(ArchiveHandle *AH, const char *dbname);
92 static void _becomeUser(ArchiveHandle *AH, const char *user);
93 static void _becomeOwner(ArchiveHandle *AH, TocEntry *te);
94 static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName);
95 static void _selectTablespace(ArchiveHandle *AH, const char *tablespace);
96 static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te);
97 static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te);
98 static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls);
99 static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
100 static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
101 static TocEntry *getTocEntryByDumpId(ArchiveHandle *AH, DumpId id);
102 static void _moveAfter(ArchiveHandle *AH, TocEntry *pos, TocEntry *te);
103 static int      _discoverArchiveFormat(ArchiveHandle *AH);
104
105 static void dump_lo_buf(ArchiveHandle *AH);
106 static void _write_msg(const char *modulename, const char *fmt, va_list ap);
107 static void _die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt, va_list ap);
108
109 static void dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim);
110 static OutputContext SetOutput(ArchiveHandle *AH, char *filename, int compression);
111 static void ResetOutput(ArchiveHandle *AH, OutputContext savedContext);
112
113 static int restore_toc_entry(ArchiveHandle *AH, TocEntry *te,
114                                                          RestoreOptions *ropt, bool is_parallel);
115 static void restore_toc_entries_parallel(ArchiveHandle *AH);
116 static thandle spawn_restore(RestoreArgs *args);
117 static thandle reap_child(ParallelSlot *slots, int n_slots, int *work_status);
118 static bool work_in_progress(ParallelSlot *slots, int n_slots);
119 static int get_next_slot(ParallelSlot *slots, int n_slots);
120 static TocEntry *get_next_work_item(ArchiveHandle *AH,
121                                                                         TocEntry **first_unprocessed,
122                                                                         ParallelSlot *slots, int n_slots);
123 static parallel_restore_result parallel_restore(RestoreArgs *args);
124 static void mark_work_done(ArchiveHandle *AH, thandle worker, int status,
125                                                    ParallelSlot *slots, int n_slots);
126 static void fix_dependencies(ArchiveHandle *AH);
127 static bool has_lock_conflicts(TocEntry *te1, TocEntry *te2);
128 static void repoint_table_dependencies(ArchiveHandle *AH,
129                                                                            DumpId tableId, DumpId tableDataId);
130 static void identify_locking_dependencies(TocEntry *te,
131                                                                                   TocEntry **tocsByDumpId);
132 static void reduce_dependencies(ArchiveHandle *AH, TocEntry *te);
133 static void mark_create_done(ArchiveHandle *AH, TocEntry *te);
134 static void inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te);
135 static ArchiveHandle *CloneArchive(ArchiveHandle *AH);
136 static void DeCloneArchive(ArchiveHandle *AH);
137
138
139 /*
140  *      Wrapper functions.
141  *
142  *      The objective it to make writing new formats and dumpers as simple
143  *      as possible, if necessary at the expense of extra function calls etc.
144  *
145  */
146
147
148 /* Create a new archive */
149 /* Public */
150 Archive *
151 CreateArchive(const char *FileSpec, const ArchiveFormat fmt,
152                           const int compression, ArchiveMode mode)
153
154 {
155         ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression, mode);
156
157         return (Archive *) AH;
158 }
159
160 /* Open an existing archive */
161 /* Public */
162 Archive *
163 OpenArchive(const char *FileSpec, const ArchiveFormat fmt)
164 {
165         ArchiveHandle *AH = _allocAH(FileSpec, fmt, 0, archModeRead);
166
167         return (Archive *) AH;
168 }
169
170 /* Public */
171 void
172 CloseArchive(Archive *AHX)
173 {
174         int                     res = 0;
175         ArchiveHandle *AH = (ArchiveHandle *) AHX;
176
177         (*AH->ClosePtr) (AH);
178
179         /* Close the output */
180         if (AH->gzOut)
181                 res = GZCLOSE(AH->OF);
182         else if (AH->OF != stdout)
183                 res = fclose(AH->OF);
184
185         if (res != 0)
186                 die_horribly(AH, modulename, "could not close output file: %s\n",
187                                          strerror(errno));
188 }
189
190 /* Public */
191 void
192 RestoreArchive(Archive *AHX, RestoreOptions *ropt)
193 {
194         ArchiveHandle *AH = (ArchiveHandle *) AHX;
195         TocEntry   *te;
196         teReqs          reqs;
197         OutputContext sav;
198
199         AH->ropt = ropt;
200         AH->stage = STAGE_INITIALIZING;
201
202         /*
203          * Check for nonsensical option combinations.
204          *
205          * NB: create+dropSchema is useless because if you're creating the DB,
206          * there's no need to drop individual items in it.  Moreover, if we tried
207          * to do that then we'd issue the drops in the database initially
208          * connected to, not the one we will create, which is very bad...
209          */
210         if (ropt->create && ropt->dropSchema)
211                 die_horribly(AH, modulename, "-C and -c are incompatible options\n");
212
213         /*
214          * -1 is not compatible with -C, because we can't create a database
215          *  inside a transaction block.
216          */
217         if (ropt->create && ropt->single_txn)
218                 die_horribly(AH, modulename, "-C and -1 are incompatible options\n");
219
220         /*
221          * Make sure we won't need (de)compression we haven't got
222          */
223 #ifndef HAVE_LIBZ
224         if (AH->compression != 0 && AH->PrintTocDataPtr != NULL)
225         {
226                 for (te = AH->toc->next; te != AH->toc; te = te->next)
227                 {
228                         reqs = _tocEntryRequired(te, ropt, false);
229                         if (te->hadDumper && (reqs & REQ_DATA) != 0)
230                                 die_horribly(AH, modulename, "cannot restore from compressed archive (compression not supported in this installation)\n");
231                 }
232         }
233 #endif
234
235         /*
236          * If we're using a DB connection, then connect it.
237          */
238         if (ropt->useDB)
239         {
240                 ahlog(AH, 1, "connecting to database for restore\n");
241                 if (AH->version < K_VERS_1_3)
242                         die_horribly(AH, modulename, "direct database connections are not supported in pre-1.3 archives\n");
243
244                 /* XXX Should get this from the archive */
245                 AHX->minRemoteVersion = 070100;
246                 AHX->maxRemoteVersion = 999999;
247
248                 ConnectDatabase(AHX, ropt->dbname,
249                                                 ropt->pghost, ropt->pgport, ropt->username,
250                                                 ropt->promptPassword);
251
252                 /*
253                  * If we're talking to the DB directly, don't send comments since they
254                  * obscure SQL when displaying errors
255                  */
256                 AH->noTocComments = 1;
257         }
258
259         /*
260          * Work out if we have an implied data-only restore. This can happen if
261          * the dump was data only or if the user has used a toc list to exclude
262          * all of the schema data. All we do is look for schema entries - if none
263          * are found then we set the dataOnly flag.
264          *
265          * We could scan for wanted TABLE entries, but that is not the same as
266          * dataOnly. At this stage, it seems unnecessary (6-Mar-2001).
267          */
268         if (!ropt->dataOnly)
269         {
270                 int                     impliedDataOnly = 1;
271
272                 for (te = AH->toc->next; te != AH->toc; te = te->next)
273                 {
274                         reqs = _tocEntryRequired(te, ropt, true);
275                         if ((reqs & REQ_SCHEMA) != 0)
276                         {                                       /* It's schema, and it's wanted */
277                                 impliedDataOnly = 0;
278                                 break;
279                         }
280                 }
281                 if (impliedDataOnly)
282                 {
283                         ropt->dataOnly = impliedDataOnly;
284                         ahlog(AH, 1, "implied data-only restore\n");
285                 }
286         }
287
288         /*
289          * Setup the output file if necessary.
290          */
291         if (ropt->filename || ropt->compression)
292                 sav = SetOutput(AH, ropt->filename, ropt->compression);
293
294         ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n");
295
296         if (AH->public.verbose)
297                 dumpTimestamp(AH, "Started on", AH->createDate);
298
299         if (ropt->single_txn)
300         {
301                 if (AH->connection)
302                         StartTransaction(AH);
303                 else
304                         ahprintf(AH, "BEGIN;\n\n");
305         }
306
307         /*
308          * Establish important parameter values right away.
309          */
310         _doSetFixedOutputState(AH);
311
312         AH->stage = STAGE_PROCESSING;
313
314         /*
315          * Drop the items at the start, in reverse order
316          */
317         if (ropt->dropSchema)
318         {
319                 for (te = AH->toc->prev; te != AH->toc; te = te->prev)
320                 {
321                         AH->currentTE = te;
322
323                         reqs = _tocEntryRequired(te, ropt, false /* needn't drop ACLs */ );
324                         if (((reqs & REQ_SCHEMA) != 0) && te->dropStmt)
325                         {
326                                 /* We want the schema */
327                                 ahlog(AH, 1, "dropping %s %s\n", te->desc, te->tag);
328                                 /* Select owner and schema as necessary */
329                                 _becomeOwner(AH, te);
330                                 _selectOutputSchema(AH, te->namespace);
331                                 /* Drop it */
332                                 ahprintf(AH, "%s", te->dropStmt);
333                         }
334                 }
335
336                 /*
337                  * _selectOutputSchema may have set currSchema to reflect the effect
338                  * of a "SET search_path" command it emitted.  However, by now we may
339                  * have dropped that schema; or it might not have existed in the first
340                  * place.  In either case the effective value of search_path will not
341                  * be what we think.  Forcibly reset currSchema so that we will
342                  * re-establish the search_path setting when needed (after creating
343                  * the schema).
344                  *
345                  * If we treated users as pg_dump'able objects then we'd need to reset
346                  * currUser here too.
347                  */
348                 if (AH->currSchema)
349                         free(AH->currSchema);
350                 AH->currSchema = NULL;
351         }
352
353         /*
354          * In serial mode, we now process each non-ACL TOC entry.
355          *
356          * In parallel mode, turn control over to the parallel-restore logic.
357          */
358         if (ropt->number_of_jobs > 1 && ropt->useDB)
359                 restore_toc_entries_parallel(AH);
360         else
361         {
362                 for (te = AH->toc->next; te != AH->toc; te = te->next)
363                         (void) restore_toc_entry(AH, te, ropt, false);
364         }
365
366         /*
367          * Scan TOC again to output ownership commands and ACLs
368          */
369         for (te = AH->toc->next; te != AH->toc; te = te->next)
370         {
371                 AH->currentTE = te;
372
373                 /* Work out what, if anything, we want from this entry */
374                 reqs = _tocEntryRequired(te, ropt, true);
375
376                 if ((reqs & REQ_SCHEMA) != 0)   /* We want the schema */
377                 {
378                         ahlog(AH, 1, "setting owner and privileges for %s %s\n",
379                                   te->desc, te->tag);
380                         _printTocEntry(AH, te, ropt, false, true);
381                 }
382         }
383
384         if (ropt->single_txn)
385         {
386                 if (AH->connection)
387                         CommitTransaction(AH);
388                 else
389                         ahprintf(AH, "COMMIT;\n\n");
390         }
391
392         if (AH->public.verbose)
393                 dumpTimestamp(AH, "Completed on", time(NULL));
394
395         ahprintf(AH, "--\n-- PostgreSQL database dump complete\n--\n\n");
396
397         /*
398          * Clean up & we're done.
399          */
400         AH->stage = STAGE_FINALIZING;
401
402         if (ropt->filename || ropt->compression)
403                 ResetOutput(AH, sav);
404
405         if (ropt->useDB)
406         {
407                 PQfinish(AH->connection);
408                 AH->connection = NULL;
409         }
410 }
411
412 /*
413  * Restore a single TOC item.  Used in both parallel and non-parallel restore;
414  * is_parallel is true if we are in a worker child process.
415  *
416  * Returns 0 normally, but WORKER_CREATE_DONE or WORKER_INHIBIT_DATA if
417  * the parallel parent has to make the corresponding status update.
418  */
419 static int
420 restore_toc_entry(ArchiveHandle *AH, TocEntry *te,
421                                   RestoreOptions *ropt, bool is_parallel)
422 {
423         int         retval = 0;
424         teReqs          reqs;
425         bool            defnDumped;
426
427         AH->currentTE = te;
428
429         /* Work out what, if anything, we want from this entry */
430         reqs = _tocEntryRequired(te, ropt, false);
431
432         /* Dump any relevant dump warnings to stderr */
433         if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0)
434         {
435                 if (!ropt->dataOnly && te->defn != NULL && strlen(te->defn) != 0)
436                         write_msg(modulename, "warning from original dump file: %s\n", te->defn);
437                 else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0)
438                         write_msg(modulename, "warning from original dump file: %s\n", te->copyStmt);
439         }
440
441         defnDumped = false;
442
443         if ((reqs & REQ_SCHEMA) != 0)   /* We want the schema */
444         {
445                 ahlog(AH, 1, "creating %s %s\n", te->desc, te->tag);
446
447                 _printTocEntry(AH, te, ropt, false, false);
448                 defnDumped = true;
449
450                 if (strcmp(te->desc, "TABLE") == 0)
451                 {
452                         if (AH->lastErrorTE == te)
453                         {
454                                 /*
455                                  * We failed to create the table.
456                                  * If --no-data-for-failed-tables was given,
457                                  * mark the corresponding TABLE DATA to be ignored.
458                                  *
459                                  * In the parallel case this must be done in the parent,
460                                  * so we just set the return value.
461                                  */
462                                 if (ropt->noDataForFailedTables)
463                                 {
464                                         if (is_parallel)
465                                                 retval = WORKER_INHIBIT_DATA;
466                                         else
467                                                 inhibit_data_for_failed_table(AH, te);
468                                 }
469                         }
470                         else
471                         {
472                                 /*
473                                  * We created the table successfully.  Mark the
474                                  * corresponding TABLE DATA for possible truncation.
475                                  *
476                                  * In the parallel case this must be done in the parent,
477                                  * so we just set the return value.
478                                  */
479                                 if (is_parallel)
480                                         retval = WORKER_CREATE_DONE;
481                                 else
482                                         mark_create_done(AH, te);
483                         }
484                 }
485
486                 /* If we created a DB, connect to it... */
487                 if (strcmp(te->desc, "DATABASE") == 0)
488                 {
489                         ahlog(AH, 1, "connecting to new database \"%s\"\n", te->tag);
490                         _reconnectToDB(AH, te->tag);
491                         ropt->dbname = strdup(te->tag);
492                 }
493         }
494
495         /*
496          * If we have a data component, then process it
497          */
498         if ((reqs & REQ_DATA) != 0)
499         {
500                 /*
501                  * hadDumper will be set if there is genuine data component for
502                  * this node. Otherwise, we need to check the defn field for
503                  * statements that need to be executed in data-only restores.
504                  */
505                 if (te->hadDumper)
506                 {
507                         /*
508                          * If we can output the data, then restore it.
509                          */
510                         if (AH->PrintTocDataPtr != NULL && (reqs & REQ_DATA) != 0)
511                         {
512                                 _printTocEntry(AH, te, ropt, true, false);
513
514                                 if (strcmp(te->desc, "BLOBS") == 0 ||
515                                         strcmp(te->desc, "BLOB COMMENTS") == 0)
516                                 {
517                                         ahlog(AH, 1, "restoring %s\n", te->desc);
518
519                                         _selectOutputSchema(AH, "pg_catalog");
520
521                                         (*AH->PrintTocDataPtr) (AH, te, ropt);
522                                 }
523                                 else
524                                 {
525                                         _disableTriggersIfNecessary(AH, te, ropt);
526
527                                         /* Select owner and schema as necessary */
528                                         _becomeOwner(AH, te);
529                                         _selectOutputSchema(AH, te->namespace);
530
531                                         ahlog(AH, 1, "restoring data for table \"%s\"\n",
532                                                   te->tag);
533
534                                         /*
535                                          * In parallel restore, if we created the table earlier
536                                          * in the run then we wrap the COPY in a transaction and
537                                          * precede it with a TRUNCATE.  If archiving is not on
538                                          * this prevents WAL-logging the COPY.  This obtains a
539                                          * speedup similar to that from using single_txn mode
540                                          * in non-parallel restores.
541                                          */
542                                         if (is_parallel && te->created)
543                                         {
544                                                 /*
545                                                  * Parallel restore is always talking directly to a
546                                                  * server, so no need to see if we should issue BEGIN.
547                                                  */
548                                                 StartTransaction(AH);
549
550                                                 /*
551                                                  * If the server version is >= 8.4, make sure we issue
552                                                  * TRUNCATE with ONLY so that child tables are not
553                                                  * wiped.
554                                                  */
555                                                 ahprintf(AH, "TRUNCATE TABLE %s%s;\n\n",
556                                                                  (PQserverVersion(AH->connection) >= 80400 ?
557                                                                   "ONLY " : ""),
558                                                                  fmtId(te->tag));
559                                         }
560
561                                         /*
562                                          * If we have a copy statement, use it. As of V1.3,
563                                          * these are separate to allow easy import from
564                                          * withing a database connection. Pre 1.3 archives can
565                                          * not use DB connections and are sent to output only.
566                                          *
567                                          * For V1.3+, the table data MUST have a copy
568                                          * statement so that we can go into appropriate mode
569                                          * with libpq.
570                                          */
571                                         if (te->copyStmt && strlen(te->copyStmt) > 0)
572                                         {
573                                                 ahprintf(AH, "%s", te->copyStmt);
574                                                 AH->writingCopyData = true;
575                                         }
576
577                                         (*AH->PrintTocDataPtr) (AH, te, ropt);
578
579                                         AH->writingCopyData = false;
580
581                                         /* close out the transaction started above */
582                                         if (is_parallel && te->created)
583                                                 CommitTransaction(AH);
584
585                                         _enableTriggersIfNecessary(AH, te, ropt);
586                                 }
587                         }
588                 }
589                 else if (!defnDumped)
590                 {
591                         /* If we haven't already dumped the defn part, do so now */
592                         ahlog(AH, 1, "executing %s %s\n", te->desc, te->tag);
593                         _printTocEntry(AH, te, ropt, false, false);
594                 }
595         }
596
597         return retval;
598 }
599
600 /*
601  * Allocate a new RestoreOptions block.
602  * This is mainly so we can initialize it, but also for future expansion,
603  */
604 RestoreOptions *
605 NewRestoreOptions(void)
606 {
607         RestoreOptions *opts;
608
609         opts = (RestoreOptions *) calloc(1, sizeof(RestoreOptions));
610
611         /* set any fields that shouldn't default to zeroes */
612         opts->format = archUnknown;
613         opts->promptPassword = TRI_DEFAULT;
614
615         return opts;
616 }
617
618 static void
619 _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
620 {
621         /* This hack is only needed in a data-only restore */
622         if (!ropt->dataOnly || !ropt->disable_triggers)
623                 return;
624
625         ahlog(AH, 1, "disabling triggers for %s\n", te->tag);
626
627         /*
628          * Become superuser if possible, since they are the only ones who can
629          * disable constraint triggers.  If -S was not given, assume the initial
630          * user identity is a superuser.  (XXX would it be better to become the
631          * table owner?)
632          */
633         _becomeUser(AH, ropt->superuser);
634
635         /*
636          * Disable them.
637          */
638         _selectOutputSchema(AH, te->namespace);
639
640         ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n",
641                          fmtId(te->tag));
642 }
643
644 static void
645 _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
646 {
647         /* This hack is only needed in a data-only restore */
648         if (!ropt->dataOnly || !ropt->disable_triggers)
649                 return;
650
651         ahlog(AH, 1, "enabling triggers for %s\n", te->tag);
652
653         /*
654          * Become superuser if possible, since they are the only ones who can
655          * disable constraint triggers.  If -S was not given, assume the initial
656          * user identity is a superuser.  (XXX would it be better to become the
657          * table owner?)
658          */
659         _becomeUser(AH, ropt->superuser);
660
661         /*
662          * Enable them.
663          */
664         _selectOutputSchema(AH, te->namespace);
665
666         ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n",
667                          fmtId(te->tag));
668 }
669
670 /*
671  * This is a routine that is part of the dumper interface, hence the 'Archive*' parameter.
672  */
673
674 /* Public */
675 size_t
676 WriteData(Archive *AHX, const void *data, size_t dLen)
677 {
678         ArchiveHandle *AH = (ArchiveHandle *) AHX;
679
680         if (!AH->currToc)
681                 die_horribly(AH, modulename, "internal error -- WriteData cannot be called outside the context of a DataDumper routine\n");
682
683         return (*AH->WriteDataPtr) (AH, data, dLen);
684 }
685
686 /*
687  * Create a new TOC entry. The TOC was designed as a TOC, but is now the
688  * repository for all metadata. But the name has stuck.
689  */
690
691 /* Public */
692 void
693 ArchiveEntry(Archive *AHX,
694                          CatalogId catalogId, DumpId dumpId,
695                          const char *tag,
696                          const char *namespace,
697                          const char *tablespace,
698                          const char *owner, bool withOids,
699                          const char *desc, teSection section,
700                          const char *defn,
701                          const char *dropStmt, const char *copyStmt,
702                          const DumpId *deps, int nDeps,
703                          DataDumperPtr dumpFn, void *dumpArg)
704 {
705         ArchiveHandle *AH = (ArchiveHandle *) AHX;
706         TocEntry   *newToc;
707
708         newToc = (TocEntry *) calloc(1, sizeof(TocEntry));
709         if (!newToc)
710                 die_horribly(AH, modulename, "out of memory\n");
711
712         AH->tocCount++;
713         if (dumpId > AH->maxDumpId)
714                 AH->maxDumpId = dumpId;
715
716         newToc->prev = AH->toc->prev;
717         newToc->next = AH->toc;
718         AH->toc->prev->next = newToc;
719         AH->toc->prev = newToc;
720
721         newToc->catalogId = catalogId;
722         newToc->dumpId = dumpId;
723         newToc->section = section;
724
725         newToc->tag = strdup(tag);
726         newToc->namespace = namespace ? strdup(namespace) : NULL;
727         newToc->tablespace = tablespace ? strdup(tablespace) : NULL;
728         newToc->owner = strdup(owner);
729         newToc->withOids = withOids;
730         newToc->desc = strdup(desc);
731         newToc->defn = strdup(defn);
732         newToc->dropStmt = strdup(dropStmt);
733         newToc->copyStmt = copyStmt ? strdup(copyStmt) : NULL;
734
735         if (nDeps > 0)
736         {
737                 newToc->dependencies = (DumpId *) malloc(nDeps * sizeof(DumpId));
738                 memcpy(newToc->dependencies, deps, nDeps * sizeof(DumpId));
739                 newToc->nDeps = nDeps;
740         }
741         else
742         {
743                 newToc->dependencies = NULL;
744                 newToc->nDeps = 0;
745         }
746
747         newToc->dataDumper = dumpFn;
748         newToc->dataDumperArg = dumpArg;
749         newToc->hadDumper = dumpFn ? true : false;
750
751         newToc->formatData = NULL;
752
753         if (AH->ArchiveEntryPtr !=NULL)
754                 (*AH->ArchiveEntryPtr) (AH, newToc);
755 }
756
757 /* Public */
758 void
759 PrintTOCSummary(Archive *AHX, RestoreOptions *ropt)
760 {
761         ArchiveHandle *AH = (ArchiveHandle *) AHX;
762         TocEntry   *te;
763         OutputContext sav;
764         char       *fmtName;
765
766         if (ropt->filename)
767                 sav = SetOutput(AH, ropt->filename, 0 /* no compression */ );
768
769         ahprintf(AH, ";\n; Archive created at %s", ctime(&AH->createDate));
770         ahprintf(AH, ";     dbname: %s\n;     TOC Entries: %d\n;     Compression: %d\n",
771                          AH->archdbname, AH->tocCount, AH->compression);
772
773         switch (AH->format)
774         {
775                 case archFiles:
776                         fmtName = "FILES";
777                         break;
778                 case archCustom:
779                         fmtName = "CUSTOM";
780                         break;
781                 case archTar:
782                         fmtName = "TAR";
783                         break;
784                 default:
785                         fmtName = "UNKNOWN";
786         }
787
788         ahprintf(AH, ";     Dump Version: %d.%d-%d\n", AH->vmaj, AH->vmin, AH->vrev);
789         ahprintf(AH, ";     Format: %s\n", fmtName);
790         ahprintf(AH, ";     Integer: %d bytes\n", (int) AH->intSize);
791         ahprintf(AH, ";     Offset: %d bytes\n", (int) AH->offSize);
792         if (AH->archiveRemoteVersion)
793                 ahprintf(AH, ";     Dumped from database version: %s\n",
794                                  AH->archiveRemoteVersion);
795         if (AH->archiveDumpVersion)
796                 ahprintf(AH, ";     Dumped by pg_dump version: %s\n",
797                                  AH->archiveDumpVersion);
798
799         ahprintf(AH, ";\n;\n; Selected TOC Entries:\n;\n");
800
801         for (te = AH->toc->next; te != AH->toc; te = te->next)
802         {
803                 if (ropt->verbose || _tocEntryRequired(te, ropt, true) != 0)
804                         ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
805                                          te->catalogId.tableoid, te->catalogId.oid,
806                                          te->desc, te->namespace ? te->namespace : "-",
807                                          te->tag, te->owner);
808                 if (ropt->verbose && te->nDeps > 0)
809                 {
810                         int             i;
811
812                         ahprintf(AH, ";\tdepends on:");
813                         for (i = 0; i < te->nDeps; i++)
814                                 ahprintf(AH, " %d", te->dependencies[i]);
815                         ahprintf(AH, "\n");
816                 }
817         }
818
819         if (ropt->filename)
820                 ResetOutput(AH, sav);
821 }
822
823 /***********
824  * BLOB Archival
825  ***********/
826
827 /* Called by a dumper to signal start of a BLOB */
828 int
829 StartBlob(Archive *AHX, Oid oid)
830 {
831         ArchiveHandle *AH = (ArchiveHandle *) AHX;
832
833         if (!AH->StartBlobPtr)
834                 die_horribly(AH, modulename, "large-object output not supported in chosen format\n");
835
836         (*AH->StartBlobPtr) (AH, AH->currToc, oid);
837
838         return 1;
839 }
840
841 /* Called by a dumper to signal end of a BLOB */
842 int
843 EndBlob(Archive *AHX, Oid oid)
844 {
845         ArchiveHandle *AH = (ArchiveHandle *) AHX;
846
847         if (AH->EndBlobPtr)
848                 (*AH->EndBlobPtr) (AH, AH->currToc, oid);
849
850         return 1;
851 }
852
853 /**********
854  * BLOB Restoration
855  **********/
856
857 /*
858  * Called by a format handler before any blobs are restored
859  */
860 void
861 StartRestoreBlobs(ArchiveHandle *AH)
862 {
863         if (!AH->ropt->single_txn)
864         {
865                 if (AH->connection)
866                         StartTransaction(AH);
867                 else
868                         ahprintf(AH, "BEGIN;\n\n");
869         }
870
871         AH->blobCount = 0;
872 }
873
874 /*
875  * Called by a format handler after all blobs are restored
876  */
877 void
878 EndRestoreBlobs(ArchiveHandle *AH)
879 {
880         if (!AH->ropt->single_txn)
881         {
882                 if (AH->connection)
883                         CommitTransaction(AH);
884                 else
885                         ahprintf(AH, "COMMIT;\n\n");
886         }
887
888         ahlog(AH, 1, ngettext("restored %d large object\n",
889                                                   "restored %d large objects\n",
890                                                   AH->blobCount),
891                   AH->blobCount);
892 }
893
894
895 /*
896  * Called by a format handler to initiate restoration of a blob
897  */
898 void
899 StartRestoreBlob(ArchiveHandle *AH, Oid oid)
900 {
901         Oid                     loOid;
902
903         AH->blobCount++;
904
905         /* Initialize the LO Buffer */
906         AH->lo_buf_used = 0;
907
908         ahlog(AH, 2, "restoring large object with OID %u\n", oid);
909
910         if (AH->connection)
911         {
912                 loOid = lo_create(AH->connection, oid);
913                 if (loOid == 0 || loOid != oid)
914                         die_horribly(AH, modulename, "could not create large object %u\n",
915                                                  oid);
916
917                 AH->loFd = lo_open(AH->connection, oid, INV_WRITE);
918                 if (AH->loFd == -1)
919                         die_horribly(AH, modulename, "could not open large object\n");
920         }
921         else
922         {
923                 ahprintf(AH, "SELECT lo_open(lo_create(%u), %d);\n", oid, INV_WRITE);
924         }
925
926         AH->writingBlob = 1;
927 }
928
929 void
930 EndRestoreBlob(ArchiveHandle *AH, Oid oid)
931 {
932         if (AH->lo_buf_used > 0)
933         {
934                 /* Write remaining bytes from the LO buffer */
935                 dump_lo_buf(AH);
936         }
937
938         AH->writingBlob = 0;
939
940         if (AH->connection)
941         {
942                 lo_close(AH->connection, AH->loFd);
943                 AH->loFd = -1;
944         }
945         else
946         {
947                 ahprintf(AH, "SELECT lo_close(0);\n\n");
948         }
949 }
950
951 /***********
952  * Sorting and Reordering
953  ***********/
954
955 void
956 SortTocFromFile(Archive *AHX, RestoreOptions *ropt)
957 {
958         ArchiveHandle *AH = (ArchiveHandle *) AHX;
959         FILE       *fh;
960         char            buf[1024];
961         char       *cmnt;
962         char       *endptr;
963         DumpId          id;
964         TocEntry   *te;
965         TocEntry   *tePrev;
966
967         /* Allocate space for the 'wanted' array, and init it */
968         ropt->idWanted = (bool *) malloc(sizeof(bool) * AH->maxDumpId);
969         memset(ropt->idWanted, 0, sizeof(bool) * AH->maxDumpId);
970
971         /* Set prev entry as head of list */
972         tePrev = AH->toc;
973
974         /* Setup the file */
975         fh = fopen(ropt->tocFile, PG_BINARY_R);
976         if (!fh)
977                 die_horribly(AH, modulename, "could not open TOC file \"%s\": %s\n",
978                                          ropt->tocFile, strerror(errno));
979
980         while (fgets(buf, sizeof(buf), fh) != NULL)
981         {
982                 /* Truncate line at comment, if any */
983                 cmnt = strchr(buf, ';');
984                 if (cmnt != NULL)
985                         cmnt[0] = '\0';
986
987                 /* Ignore if all blank */
988                 if (strspn(buf, " \t\r") == strlen(buf))
989                         continue;
990
991                 /* Get an ID, check it's valid and not already seen */
992                 id = strtol(buf, &endptr, 10);
993                 if (endptr == buf || id <= 0 || id > AH->maxDumpId ||
994                         ropt->idWanted[id - 1])
995                 {
996                         write_msg(modulename, "WARNING: line ignored: %s\n", buf);
997                         continue;
998                 }
999
1000                 /* Find TOC entry */
1001                 te = getTocEntryByDumpId(AH, id);
1002                 if (!te)
1003                         die_horribly(AH, modulename, "could not find entry for ID %d\n",
1004                                                  id);
1005
1006                 ropt->idWanted[id - 1] = true;
1007
1008                 _moveAfter(AH, tePrev, te);
1009                 tePrev = te;
1010         }
1011
1012         if (fclose(fh) != 0)
1013                 die_horribly(AH, modulename, "could not close TOC file: %s\n",
1014                                          strerror(errno));
1015 }
1016
1017 /*
1018  * Set up a dummy ID filter that selects all dump IDs
1019  */
1020 void
1021 InitDummyWantedList(Archive *AHX, RestoreOptions *ropt)
1022 {
1023         ArchiveHandle *AH = (ArchiveHandle *) AHX;
1024
1025         /* Allocate space for the 'wanted' array, and init it to 1's */
1026         ropt->idWanted = (bool *) malloc(sizeof(bool) * AH->maxDumpId);
1027         memset(ropt->idWanted, 1, sizeof(bool) * AH->maxDumpId);
1028 }
1029
1030 /**********************
1031  * 'Convenience functions that look like standard IO functions
1032  * for writing data when in dump mode.
1033  **********************/
1034
1035 /* Public */
1036 int
1037 archputs(const char *s, Archive *AH)
1038 {
1039         return WriteData(AH, s, strlen(s));
1040 }
1041
1042 /* Public */
1043 int
1044 archprintf(Archive *AH, const char *fmt,...)
1045 {
1046         char       *p = NULL;
1047         va_list         ap;
1048         int                     bSize = strlen(fmt) + 256;
1049         int                     cnt = -1;
1050
1051         /*
1052          * This is paranoid: deal with the possibility that vsnprintf is willing
1053          * to ignore trailing null or returns > 0 even if string does not fit. It
1054          * may be the case that it returns cnt = bufsize
1055          */
1056         while (cnt < 0 || cnt >= (bSize - 1))
1057         {
1058                 if (p != NULL)
1059                         free(p);
1060                 bSize *= 2;
1061                 p = (char *) malloc(bSize);
1062                 if (p == NULL)
1063                         exit_horribly(AH, modulename, "out of memory\n");
1064                 va_start(ap, fmt);
1065                 cnt = vsnprintf(p, bSize, fmt, ap);
1066                 va_end(ap);
1067         }
1068         WriteData(AH, p, cnt);
1069         free(p);
1070         return cnt;
1071 }
1072
1073
1074 /*******************************
1075  * Stuff below here should be 'private' to the archiver routines
1076  *******************************/
1077
1078 static OutputContext
1079 SetOutput(ArchiveHandle *AH, char *filename, int compression)
1080 {
1081         OutputContext sav;
1082         int                     fn;
1083
1084         /* Replace the AH output file handle */
1085         sav.OF = AH->OF;
1086         sav.gzOut = AH->gzOut;
1087
1088         if (filename)
1089                 fn = -1;
1090         else if (AH->FH)
1091                 fn = fileno(AH->FH);
1092         else if (AH->fSpec)
1093         {
1094                 fn = -1;
1095                 filename = AH->fSpec;
1096         }
1097         else
1098                 fn = fileno(stdout);
1099
1100         /* If compression explicitly requested, use gzopen */
1101 #ifdef HAVE_LIBZ
1102         if (compression != 0)
1103         {
1104                 char            fmode[10];
1105
1106                 /* Don't use PG_BINARY_x since this is zlib */
1107                 sprintf(fmode, "wb%d", compression);
1108                 if (fn >= 0)
1109                         AH->OF = gzdopen(dup(fn), fmode);
1110                 else
1111                         AH->OF = gzopen(filename, fmode);
1112                 AH->gzOut = 1;
1113         }
1114         else
1115 #endif
1116         {                                                       /* Use fopen */
1117                 if (AH->mode == archModeAppend)
1118                 {
1119                         if (fn >= 0)
1120                                 AH->OF = fdopen(dup(fn), PG_BINARY_A);
1121                         else
1122                                 AH->OF = fopen(filename, PG_BINARY_A);
1123                 }
1124                 else
1125                 {
1126                         if (fn >= 0)
1127                                 AH->OF = fdopen(dup(fn), PG_BINARY_W);
1128                         else
1129                                 AH->OF = fopen(filename, PG_BINARY_W);
1130                 }
1131                 AH->gzOut = 0;
1132         }
1133
1134         if (!AH->OF)
1135         {
1136                 if (filename)
1137                         die_horribly(AH, modulename, "could not open output file \"%s\": %s\n",
1138                                                  filename, strerror(errno));
1139                 else
1140                         die_horribly(AH, modulename, "could not open output file: %s\n",
1141                                                  strerror(errno));
1142         }
1143
1144         return sav;
1145 }
1146
1147 static void
1148 ResetOutput(ArchiveHandle *AH, OutputContext sav)
1149 {
1150         int                     res;
1151
1152         if (AH->gzOut)
1153                 res = GZCLOSE(AH->OF);
1154         else
1155                 res = fclose(AH->OF);
1156
1157         if (res != 0)
1158                 die_horribly(AH, modulename, "could not close output file: %s\n",
1159                                          strerror(errno));
1160
1161         AH->gzOut = sav.gzOut;
1162         AH->OF = sav.OF;
1163 }
1164
1165
1166
1167 /*
1168  *      Print formatted text to the output file (usually stdout).
1169  */
1170 int
1171 ahprintf(ArchiveHandle *AH, const char *fmt,...)
1172 {
1173         char       *p = NULL;
1174         va_list         ap;
1175         int                     bSize = strlen(fmt) + 256;              /* Should be enough */
1176         int                     cnt = -1;
1177
1178         /*
1179          * This is paranoid: deal with the possibility that vsnprintf is willing
1180          * to ignore trailing null
1181          */
1182
1183         /*
1184          * or returns > 0 even if string does not fit. It may be the case that it
1185          * returns cnt = bufsize
1186          */
1187         while (cnt < 0 || cnt >= (bSize - 1))
1188         {
1189                 if (p != NULL)
1190                         free(p);
1191                 bSize *= 2;
1192                 p = (char *) malloc(bSize);
1193                 if (p == NULL)
1194                         die_horribly(AH, modulename, "out of memory\n");
1195                 va_start(ap, fmt);
1196                 cnt = vsnprintf(p, bSize, fmt, ap);
1197                 va_end(ap);
1198         }
1199         ahwrite(p, 1, cnt, AH);
1200         free(p);
1201         return cnt;
1202 }
1203
1204 void
1205 ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
1206 {
1207         va_list         ap;
1208
1209         if (AH->debugLevel < level && (!AH->public.verbose || level > 1))
1210                 return;
1211
1212         va_start(ap, fmt);
1213         _write_msg(NULL, fmt, ap);
1214         va_end(ap);
1215 }
1216
1217 /*
1218  * Single place for logic which says 'We are restoring to a direct DB connection'.
1219  */
1220 static int
1221 RestoringToDB(ArchiveHandle *AH)
1222 {
1223         return (AH->ropt && AH->ropt->useDB && AH->connection);
1224 }
1225
1226 /*
1227  * Dump the current contents of the LO data buffer while writing a BLOB
1228  */
1229 static void
1230 dump_lo_buf(ArchiveHandle *AH)
1231 {
1232         if (AH->connection)
1233         {
1234                 size_t          res;
1235
1236                 res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
1237                 ahlog(AH, 5, ngettext("wrote %lu byte of large object data (result = %lu)\n",
1238                                                           "wrote %lu bytes of large object data (result = %lu)\n",
1239                                                           AH->lo_buf_used),
1240                           (unsigned long) AH->lo_buf_used, (unsigned long) res);
1241                 if (res != AH->lo_buf_used)
1242                         die_horribly(AH, modulename,
1243                         "could not write to large object (result: %lu, expected: %lu)\n",
1244                                            (unsigned long) res, (unsigned long) AH->lo_buf_used);
1245         }
1246         else
1247         {
1248                 unsigned char *str;
1249                 size_t          len;
1250
1251                 str = PQescapeBytea((const unsigned char *) AH->lo_buf,
1252                                                         AH->lo_buf_used, &len);
1253                 if (!str)
1254                         die_horribly(AH, modulename, "out of memory\n");
1255
1256                 /* Hack: turn off writingBlob so ahwrite doesn't recurse to here */
1257                 AH->writingBlob = 0;
1258                 ahprintf(AH, "SELECT lowrite(0, '%s');\n", str);
1259                 AH->writingBlob = 1;
1260
1261                 free(str);
1262         }
1263         AH->lo_buf_used = 0;
1264 }
1265
1266
1267 /*
1268  *      Write buffer to the output file (usually stdout). This is user for
1269  *      outputting 'restore' scripts etc. It is even possible for an archive
1270  *      format to create a custom output routine to 'fake' a restore if it
1271  *      wants to generate a script (see TAR output).
1272  */
1273 int
1274 ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
1275 {
1276         size_t          res;
1277
1278         if (AH->writingBlob)
1279         {
1280                 size_t          remaining = size * nmemb;
1281
1282                 while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1283                 {
1284                         size_t          avail = AH->lo_buf_size - AH->lo_buf_used;
1285
1286                         memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
1287                         ptr = (const void *) ((const char *) ptr + avail);
1288                         remaining -= avail;
1289                         AH->lo_buf_used += avail;
1290                         dump_lo_buf(AH);
1291                 }
1292
1293                 memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1294                 AH->lo_buf_used += remaining;
1295
1296                 return size * nmemb;
1297         }
1298         else if (AH->gzOut)
1299         {
1300                 res = GZWRITE((void *) ptr, size, nmemb, AH->OF);
1301                 if (res != (nmemb * size))
1302                         die_horribly(AH, modulename, "could not write to output file: %s\n", strerror(errno));
1303                 return res;
1304         }
1305         else if (AH->CustomOutPtr)
1306         {
1307                 res = AH->CustomOutPtr (AH, ptr, size * nmemb);
1308
1309                 if (res != (nmemb * size))
1310                         die_horribly(AH, modulename, "could not write to custom output routine\n");
1311                 return res;
1312         }
1313         else
1314         {
1315                 /*
1316                  * If we're doing a restore, and it's direct to DB, and we're
1317                  * connected then send it to the DB.
1318                  */
1319                 if (RestoringToDB(AH))
1320                         return ExecuteSqlCommandBuf(AH, (void *) ptr, size * nmemb);            /* Always 1, currently */
1321                 else
1322                 {
1323                         res = fwrite((void *) ptr, size, nmemb, AH->OF);
1324                         if (res != nmemb)
1325                                 die_horribly(AH, modulename, "could not write to output file: %s\n",
1326                                                          strerror(errno));
1327                         return res;
1328                 }
1329         }
1330 }
1331
1332 /* Common exit code */
1333 static void
1334 _write_msg(const char *modulename, const char *fmt, va_list ap)
1335 {
1336         if (modulename)
1337                 fprintf(stderr, "%s: [%s] ", progname, _(modulename));
1338         else
1339                 fprintf(stderr, "%s: ", progname);
1340         vfprintf(stderr, _(fmt), ap);
1341 }
1342
1343 void
1344 write_msg(const char *modulename, const char *fmt,...)
1345 {
1346         va_list         ap;
1347
1348         va_start(ap, fmt);
1349         _write_msg(modulename, fmt, ap);
1350         va_end(ap);
1351 }
1352
1353
1354 static void
1355 _die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt, va_list ap)
1356 {
1357         _write_msg(modulename, fmt, ap);
1358
1359         if (AH)
1360         {
1361                 if (AH->public.verbose)
1362                         write_msg(NULL, "*** aborted because of error\n");
1363                 if (AH->connection)
1364                         PQfinish(AH->connection);
1365         }
1366
1367         exit(1);
1368 }
1369
1370 /* External use */
1371 void
1372 exit_horribly(Archive *AH, const char *modulename, const char *fmt,...)
1373 {
1374         va_list         ap;
1375
1376         va_start(ap, fmt);
1377         _die_horribly((ArchiveHandle *) AH, modulename, fmt, ap);
1378         va_end(ap);
1379 }
1380
1381 /* Archiver use (just different arg declaration) */
1382 void
1383 die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...)
1384 {
1385         va_list         ap;
1386
1387         va_start(ap, fmt);
1388         _die_horribly(AH, modulename, fmt, ap);
1389         va_end(ap);
1390 }
1391
1392 /* on some error, we may decide to go on... */
1393 void
1394 warn_or_die_horribly(ArchiveHandle *AH,
1395                                          const char *modulename, const char *fmt,...)
1396 {
1397         va_list         ap;
1398
1399         switch (AH->stage)
1400         {
1401
1402                 case STAGE_NONE:
1403                         /* Do nothing special */
1404                         break;
1405
1406                 case STAGE_INITIALIZING:
1407                         if (AH->stage != AH->lastErrorStage)
1408                                 write_msg(modulename, "Error while INITIALIZING:\n");
1409                         break;
1410
1411                 case STAGE_PROCESSING:
1412                         if (AH->stage != AH->lastErrorStage)
1413                                 write_msg(modulename, "Error while PROCESSING TOC:\n");
1414                         break;
1415
1416                 case STAGE_FINALIZING:
1417                         if (AH->stage != AH->lastErrorStage)
1418                                 write_msg(modulename, "Error while FINALIZING:\n");
1419                         break;
1420         }
1421         if (AH->currentTE != NULL && AH->currentTE != AH->lastErrorTE)
1422         {
1423                 write_msg(modulename, "Error from TOC entry %d; %u %u %s %s %s\n",
1424                                   AH->currentTE->dumpId,
1425                          AH->currentTE->catalogId.tableoid, AH->currentTE->catalogId.oid,
1426                           AH->currentTE->desc, AH->currentTE->tag, AH->currentTE->owner);
1427         }
1428         AH->lastErrorStage = AH->stage;
1429         AH->lastErrorTE = AH->currentTE;
1430
1431         va_start(ap, fmt);
1432         if (AH->public.exit_on_error)
1433                 _die_horribly(AH, modulename, fmt, ap);
1434         else
1435         {
1436                 _write_msg(modulename, fmt, ap);
1437                 AH->public.n_errors++;
1438         }
1439         va_end(ap);
1440 }
1441
1442 static void
1443 _moveAfter(ArchiveHandle *AH, TocEntry *pos, TocEntry *te)
1444 {
1445         te->prev->next = te->next;
1446         te->next->prev = te->prev;
1447
1448         te->prev = pos;
1449         te->next = pos->next;
1450
1451         pos->next->prev = te;
1452         pos->next = te;
1453 }
1454
1455 #ifdef NOT_USED
1456
1457 static void
1458 _moveBefore(ArchiveHandle *AH, TocEntry *pos, TocEntry *te)
1459 {
1460         te->prev->next = te->next;
1461         te->next->prev = te->prev;
1462
1463         te->prev = pos->prev;
1464         te->next = pos;
1465         pos->prev->next = te;
1466         pos->prev = te;
1467 }
1468 #endif
1469
1470 static TocEntry *
1471 getTocEntryByDumpId(ArchiveHandle *AH, DumpId id)
1472 {
1473         TocEntry   *te;
1474
1475         for (te = AH->toc->next; te != AH->toc; te = te->next)
1476         {
1477                 if (te->dumpId == id)
1478                         return te;
1479         }
1480         return NULL;
1481 }
1482
1483 teReqs
1484 TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt)
1485 {
1486         TocEntry   *te = getTocEntryByDumpId(AH, id);
1487
1488         if (!te)
1489                 return 0;
1490
1491         return _tocEntryRequired(te, ropt, true);
1492 }
1493
1494 size_t
1495 WriteOffset(ArchiveHandle *AH, pgoff_t o, int wasSet)
1496 {
1497         int                     off;
1498
1499         /* Save the flag */
1500         (*AH->WriteBytePtr) (AH, wasSet);
1501
1502         /* Write out pgoff_t smallest byte first, prevents endian mismatch */
1503         for (off = 0; off < sizeof(pgoff_t); off++)
1504         {
1505                 (*AH->WriteBytePtr) (AH, o & 0xFF);
1506                 o >>= 8;
1507         }
1508         return sizeof(pgoff_t) + 1;
1509 }
1510
1511 int
1512 ReadOffset(ArchiveHandle *AH, pgoff_t * o)
1513 {
1514         int                     i;
1515         int                     off;
1516         int                     offsetFlg;
1517
1518         /* Initialize to zero */
1519         *o = 0;
1520
1521         /* Check for old version */
1522         if (AH->version < K_VERS_1_7)
1523         {
1524                 /* Prior versions wrote offsets using WriteInt */
1525                 i = ReadInt(AH);
1526                 /* -1 means not set */
1527                 if (i < 0)
1528                         return K_OFFSET_POS_NOT_SET;
1529                 else if (i == 0)
1530                         return K_OFFSET_NO_DATA;
1531
1532                 /* Cast to pgoff_t because it was written as an int. */
1533                 *o = (pgoff_t) i;
1534                 return K_OFFSET_POS_SET;
1535         }
1536
1537         /*
1538          * Read the flag indicating the state of the data pointer. Check if valid
1539          * and die if not.
1540          *
1541          * This used to be handled by a negative or zero pointer, now we use an
1542          * extra byte specifically for the state.
1543          */
1544         offsetFlg = (*AH->ReadBytePtr) (AH) & 0xFF;
1545
1546         switch (offsetFlg)
1547         {
1548                 case K_OFFSET_POS_NOT_SET:
1549                 case K_OFFSET_NO_DATA:
1550                 case K_OFFSET_POS_SET:
1551
1552                         break;
1553
1554                 default:
1555                         die_horribly(AH, modulename, "unexpected data offset flag %d\n", offsetFlg);
1556         }
1557
1558         /*
1559          * Read the bytes
1560          */
1561         for (off = 0; off < AH->offSize; off++)
1562         {
1563                 if (off < sizeof(pgoff_t))
1564                         *o |= ((pgoff_t) ((*AH->ReadBytePtr) (AH))) << (off * 8);
1565                 else
1566                 {
1567                         if ((*AH->ReadBytePtr) (AH) != 0)
1568                                 die_horribly(AH, modulename, "file offset in dump file is too large\n");
1569                 }
1570         }
1571
1572         return offsetFlg;
1573 }
1574
1575 size_t
1576 WriteInt(ArchiveHandle *AH, int i)
1577 {
1578         int                     b;
1579
1580         /*
1581          * This is a bit yucky, but I don't want to make the binary format very
1582          * dependent on representation, and not knowing much about it, I write out
1583          * a sign byte. If you change this, don't forget to change the file
1584          * version #, and modify readInt to read the new format AS WELL AS the old
1585          * formats.
1586          */
1587
1588         /* SIGN byte */
1589         if (i < 0)
1590         {
1591                 (*AH->WriteBytePtr) (AH, 1);
1592                 i = -i;
1593         }
1594         else
1595                 (*AH->WriteBytePtr) (AH, 0);
1596
1597         for (b = 0; b < AH->intSize; b++)
1598         {
1599                 (*AH->WriteBytePtr) (AH, i & 0xFF);
1600                 i >>= 8;
1601         }
1602
1603         return AH->intSize + 1;
1604 }
1605
1606 int
1607 ReadInt(ArchiveHandle *AH)
1608 {
1609         int                     res = 0;
1610         int                     bv,
1611                                 b;
1612         int                     sign = 0;               /* Default positive */
1613         int                     bitShift = 0;
1614
1615         if (AH->version > K_VERS_1_0)
1616                 /* Read a sign byte */
1617                 sign = (*AH->ReadBytePtr) (AH);
1618
1619         for (b = 0; b < AH->intSize; b++)
1620         {
1621                 bv = (*AH->ReadBytePtr) (AH) & 0xFF;
1622                 if (bv != 0)
1623                         res = res + (bv << bitShift);
1624                 bitShift += 8;
1625         }
1626
1627         if (sign)
1628                 res = -res;
1629
1630         return res;
1631 }
1632
1633 size_t
1634 WriteStr(ArchiveHandle *AH, const char *c)
1635 {
1636         size_t          res;
1637
1638         if (c)
1639         {
1640                 res = WriteInt(AH, strlen(c));
1641                 res += (*AH->WriteBufPtr) (AH, c, strlen(c));
1642         }
1643         else
1644                 res = WriteInt(AH, -1);
1645
1646         return res;
1647 }
1648
1649 char *
1650 ReadStr(ArchiveHandle *AH)
1651 {
1652         char       *buf;
1653         int                     l;
1654
1655         l = ReadInt(AH);
1656         if (l < 0)
1657                 buf = NULL;
1658         else
1659         {
1660                 buf = (char *) malloc(l + 1);
1661                 if (!buf)
1662                         die_horribly(AH, modulename, "out of memory\n");
1663
1664                 if ((*AH->ReadBufPtr) (AH, (void *) buf, l) != l)
1665                         die_horribly(AH, modulename, "unexpected end of file\n");
1666
1667                 buf[l] = '\0';
1668         }
1669
1670         return buf;
1671 }
1672
1673 static int
1674 _discoverArchiveFormat(ArchiveHandle *AH)
1675 {
1676         FILE       *fh;
1677         char            sig[6];                 /* More than enough */
1678         size_t          cnt;
1679         int                     wantClose = 0;
1680
1681 #if 0
1682         write_msg(modulename, "attempting to ascertain archive format\n");
1683 #endif
1684
1685         if (AH->lookahead)
1686                 free(AH->lookahead);
1687
1688         AH->lookaheadSize = 512;
1689         AH->lookahead = calloc(1, 512);
1690         AH->lookaheadLen = 0;
1691         AH->lookaheadPos = 0;
1692
1693         if (AH->fSpec)
1694         {
1695                 wantClose = 1;
1696                 fh = fopen(AH->fSpec, PG_BINARY_R);
1697                 if (!fh)
1698                         die_horribly(AH, modulename, "could not open input file \"%s\": %s\n",
1699                                                  AH->fSpec, strerror(errno));
1700         }
1701         else
1702         {
1703                 fh = stdin;
1704                 if (!fh)
1705                         die_horribly(AH, modulename, "could not open input file: %s\n",
1706                                                  strerror(errno));
1707         }
1708
1709         cnt = fread(sig, 1, 5, fh);
1710
1711         if (cnt != 5)
1712         {
1713                 if (ferror(fh))
1714                         die_horribly(AH, modulename, "could not read input file: %s\n", strerror(errno));
1715                 else
1716                         die_horribly(AH, modulename, "input file is too short (read %lu, expected 5)\n",
1717                                                  (unsigned long) cnt);
1718         }
1719
1720         /* Save it, just in case we need it later */
1721         strncpy(&AH->lookahead[0], sig, 5);
1722         AH->lookaheadLen = 5;
1723
1724         if (strncmp(sig, "PGDMP", 5) == 0)
1725         {
1726                 AH->vmaj = fgetc(fh);
1727                 AH->vmin = fgetc(fh);
1728
1729                 /* Save these too... */
1730                 AH->lookahead[AH->lookaheadLen++] = AH->vmaj;
1731                 AH->lookahead[AH->lookaheadLen++] = AH->vmin;
1732
1733                 /* Check header version; varies from V1.0 */
1734                 if (AH->vmaj > 1 || ((AH->vmaj == 1) && (AH->vmin > 0)))                /* Version > 1.0 */
1735                 {
1736                         AH->vrev = fgetc(fh);
1737                         AH->lookahead[AH->lookaheadLen++] = AH->vrev;
1738                 }
1739                 else
1740                         AH->vrev = 0;
1741
1742                 /* Make a convenient integer <maj><min><rev>00 */
1743                 AH->version = ((AH->vmaj * 256 + AH->vmin) * 256 + AH->vrev) * 256 + 0;
1744
1745                 AH->intSize = fgetc(fh);
1746                 AH->lookahead[AH->lookaheadLen++] = AH->intSize;
1747
1748                 if (AH->version >= K_VERS_1_7)
1749                 {
1750                         AH->offSize = fgetc(fh);
1751                         AH->lookahead[AH->lookaheadLen++] = AH->offSize;
1752                 }
1753                 else
1754                         AH->offSize = AH->intSize;
1755
1756                 AH->format = fgetc(fh);
1757                 AH->lookahead[AH->lookaheadLen++] = AH->format;
1758         }
1759         else
1760         {
1761                 /*
1762                  * *Maybe* we have a tar archive format file... So, read first 512
1763                  * byte header...
1764                  */
1765                 cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh);
1766                 AH->lookaheadLen += cnt;
1767
1768                 if (AH->lookaheadLen != 512)
1769                         die_horribly(AH, modulename, "input file does not appear to be a valid archive (too short?)\n");
1770
1771                 if (!isValidTarHeader(AH->lookahead))
1772                         die_horribly(AH, modulename, "input file does not appear to be a valid archive\n");
1773
1774                 AH->format = archTar;
1775         }
1776
1777         /* If we can't seek, then mark the header as read */
1778         if (fseeko(fh, 0, SEEK_SET) != 0)
1779         {
1780                 /*
1781                  * NOTE: Formats that use the lookahead buffer can unset this in their
1782                  * Init routine.
1783                  */
1784                 AH->readHeader = 1;
1785         }
1786         else
1787                 AH->lookaheadLen = 0;   /* Don't bother since we've reset the file */
1788
1789         /* Close the file */
1790         if (wantClose)
1791                 if (fclose(fh) != 0)
1792                         die_horribly(AH, modulename, "could not close input file: %s\n",
1793                                                  strerror(errno));
1794
1795         return AH->format;
1796 }
1797
1798
1799 /*
1800  * Allocate an archive handle
1801  */
1802 static ArchiveHandle *
1803 _allocAH(const char *FileSpec, const ArchiveFormat fmt,
1804                  const int compression, ArchiveMode mode)
1805 {
1806         ArchiveHandle *AH;
1807
1808 #if 0
1809         write_msg(modulename, "allocating AH for %s, format %d\n", FileSpec, fmt);
1810 #endif
1811
1812         AH = (ArchiveHandle *) calloc(1, sizeof(ArchiveHandle));
1813         if (!AH)
1814                 die_horribly(AH, modulename, "out of memory\n");
1815
1816         /* AH->debugLevel = 100; */
1817
1818         AH->vmaj = K_VERS_MAJOR;
1819         AH->vmin = K_VERS_MINOR;
1820         AH->vrev = K_VERS_REV;
1821
1822         /* initialize for backwards compatible string processing */
1823         AH->public.encoding = 0;        /* PG_SQL_ASCII */
1824         AH->public.std_strings = false;
1825
1826         /* sql error handling */
1827         AH->public.exit_on_error = true;
1828         AH->public.n_errors = 0;
1829
1830         AH->createDate = time(NULL);
1831
1832         AH->intSize = sizeof(int);
1833         AH->offSize = sizeof(pgoff_t);
1834         if (FileSpec)
1835         {
1836                 AH->fSpec = strdup(FileSpec);
1837
1838                 /*
1839                  * Not used; maybe later....
1840                  *
1841                  * AH->workDir = strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
1842                  * i--) if (AH->workDir[i-1] == '/')
1843                  */
1844         }
1845         else
1846                 AH->fSpec = NULL;
1847
1848         AH->currUser = NULL;            /* unknown */
1849         AH->currSchema = NULL;          /* ditto */
1850         AH->currTablespace = NULL;      /* ditto */
1851         AH->currWithOids = -1;          /* force SET */
1852
1853         AH->toc = (TocEntry *) calloc(1, sizeof(TocEntry));
1854         if (!AH->toc)
1855                 die_horribly(AH, modulename, "out of memory\n");
1856
1857         AH->toc->next = AH->toc;
1858         AH->toc->prev = AH->toc;
1859
1860         AH->mode = mode;
1861         AH->compression = compression;
1862
1863         AH->pgCopyBuf = createPQExpBuffer();
1864         AH->sqlBuf = createPQExpBuffer();
1865
1866         /* Open stdout with no compression for AH output handle */
1867         AH->gzOut = 0;
1868         AH->OF = stdout;
1869
1870         /*
1871          * On Windows, we need to use binary mode to read/write non-text archive
1872          * formats.  Force stdin/stdout into binary mode if that is what we are
1873          * using.
1874          */
1875 #ifdef WIN32
1876         if (fmt != archNull &&
1877                 (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))
1878         {
1879                 if (mode == archModeWrite)
1880                         setmode(fileno(stdout), O_BINARY);
1881                 else
1882                         setmode(fileno(stdin), O_BINARY);
1883         }
1884 #endif
1885
1886         if (fmt == archUnknown)
1887                 AH->format = _discoverArchiveFormat(AH);
1888         else
1889                 AH->format = fmt;
1890
1891         AH->promptPassword = TRI_DEFAULT;
1892
1893         switch (AH->format)
1894         {
1895                 case archCustom:
1896                         InitArchiveFmt_Custom(AH);
1897                         break;
1898
1899                 case archFiles:
1900                         InitArchiveFmt_Files(AH);
1901                         break;
1902
1903                 case archNull:
1904                         InitArchiveFmt_Null(AH);
1905                         break;
1906
1907                 case archTar:
1908                         InitArchiveFmt_Tar(AH);
1909                         break;
1910
1911                 default:
1912                         die_horribly(AH, modulename, "unrecognized file format \"%d\"\n", fmt);
1913         }
1914
1915         return AH;
1916 }
1917
1918
1919 void
1920 WriteDataChunks(ArchiveHandle *AH)
1921 {
1922         TocEntry   *te;
1923         StartDataPtr startPtr;
1924         EndDataPtr      endPtr;
1925
1926         for (te = AH->toc->next; te != AH->toc; te = te->next)
1927         {
1928                 if (te->dataDumper != NULL)
1929                 {
1930                         AH->currToc = te;
1931                         /* printf("Writing data for %d (%x)\n", te->id, te); */
1932
1933                         if (strcmp(te->desc, "BLOBS") == 0)
1934                         {
1935                                 startPtr = AH->StartBlobsPtr;
1936                                 endPtr = AH->EndBlobsPtr;
1937                         }
1938                         else
1939                         {
1940                                 startPtr = AH->StartDataPtr;
1941                                 endPtr = AH->EndDataPtr;
1942                         }
1943
1944                         if (startPtr != NULL)
1945                                 (*startPtr) (AH, te);
1946
1947                         /*
1948                          * printf("Dumper arg for %d is %x\n", te->id, te->dataDumperArg);
1949                          */
1950
1951                         /*
1952                          * The user-provided DataDumper routine needs to call
1953                          * AH->WriteData
1954                          */
1955                         (*te->dataDumper) ((Archive *) AH, te->dataDumperArg);
1956
1957                         if (endPtr != NULL)
1958                                 (*endPtr) (AH, te);
1959                         AH->currToc = NULL;
1960                 }
1961         }
1962 }
1963
1964 void
1965 WriteToc(ArchiveHandle *AH)
1966 {
1967         TocEntry   *te;
1968         char            workbuf[32];
1969         int                     i;
1970
1971         /* printf("%d TOC Entries to save\n", AH->tocCount); */
1972
1973         WriteInt(AH, AH->tocCount);
1974
1975         for (te = AH->toc->next; te != AH->toc; te = te->next)
1976         {
1977                 WriteInt(AH, te->dumpId);
1978                 WriteInt(AH, te->dataDumper ? 1 : 0);
1979
1980                 /* OID is recorded as a string for historical reasons */
1981                 sprintf(workbuf, "%u", te->catalogId.tableoid);
1982                 WriteStr(AH, workbuf);
1983                 sprintf(workbuf, "%u", te->catalogId.oid);
1984                 WriteStr(AH, workbuf);
1985
1986                 WriteStr(AH, te->tag);
1987                 WriteStr(AH, te->desc);
1988                 WriteInt(AH, te->section);
1989                 WriteStr(AH, te->defn);
1990                 WriteStr(AH, te->dropStmt);
1991                 WriteStr(AH, te->copyStmt);
1992                 WriteStr(AH, te->namespace);
1993                 WriteStr(AH, te->tablespace);
1994                 WriteStr(AH, te->owner);
1995                 WriteStr(AH, te->withOids ? "true" : "false");
1996
1997                 /* Dump list of dependencies */
1998                 for (i = 0; i < te->nDeps; i++)
1999                 {
2000                         sprintf(workbuf, "%d", te->dependencies[i]);
2001                         WriteStr(AH, workbuf);
2002                 }
2003                 WriteStr(AH, NULL);             /* Terminate List */
2004
2005                 if (AH->WriteExtraTocPtr)
2006                         (*AH->WriteExtraTocPtr) (AH, te);
2007         }
2008 }
2009
2010 void
2011 ReadToc(ArchiveHandle *AH)
2012 {
2013         int                     i;
2014         char       *tmp;
2015         DumpId     *deps;
2016         int                     depIdx;
2017         int                     depSize;
2018         TocEntry   *te;
2019
2020         AH->tocCount = ReadInt(AH);
2021         AH->maxDumpId = 0;
2022
2023         for (i = 0; i < AH->tocCount; i++)
2024         {
2025                 te = (TocEntry *) calloc(1, sizeof(TocEntry));
2026                 te->dumpId = ReadInt(AH);
2027
2028                 if (te->dumpId > AH->maxDumpId)
2029                         AH->maxDumpId = te->dumpId;
2030
2031                 /* Sanity check */
2032                 if (te->dumpId <= 0)
2033                         die_horribly(AH, modulename,
2034                                            "entry ID %d out of range -- perhaps a corrupt TOC\n",
2035                                                  te->dumpId);
2036
2037                 te->hadDumper = ReadInt(AH);
2038
2039                 if (AH->version >= K_VERS_1_8)
2040                 {
2041                         tmp = ReadStr(AH);
2042                         sscanf(tmp, "%u", &te->catalogId.tableoid);
2043                         free(tmp);
2044                 }
2045                 else
2046                         te->catalogId.tableoid = InvalidOid;
2047                 tmp = ReadStr(AH);
2048                 sscanf(tmp, "%u", &te->catalogId.oid);
2049                 free(tmp);
2050
2051                 te->tag = ReadStr(AH);
2052                 te->desc = ReadStr(AH);
2053
2054                 if (AH->version >= K_VERS_1_11)
2055                 {
2056                         te->section = ReadInt(AH);
2057                 }
2058                 else
2059                 {
2060                         /*
2061                          * rules for pre-8.4 archives wherein pg_dump hasn't classified
2062                          * the entries into sections
2063                          */
2064                         if (strcmp(te->desc, "COMMENT") == 0 ||
2065                                 strcmp(te->desc, "ACL") == 0)
2066                                 te->section = SECTION_NONE;
2067                         else if (strcmp(te->desc, "TABLE DATA") == 0 ||
2068                                          strcmp(te->desc, "BLOBS") == 0 ||
2069                                          strcmp(te->desc, "BLOB COMMENTS") == 0)
2070                                 te->section = SECTION_DATA;
2071                         else if (strcmp(te->desc, "CONSTRAINT") == 0 ||
2072                                          strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
2073                                          strcmp(te->desc, "FK CONSTRAINT") == 0 ||
2074                                          strcmp(te->desc, "INDEX") == 0 ||
2075                                          strcmp(te->desc, "RULE") == 0 ||
2076                                          strcmp(te->desc, "TRIGGER") == 0)
2077                                 te->section = SECTION_POST_DATA;
2078                         else
2079                                 te->section = SECTION_PRE_DATA;
2080                 }
2081
2082                 te->defn = ReadStr(AH);
2083                 te->dropStmt = ReadStr(AH);
2084
2085                 if (AH->version >= K_VERS_1_3)
2086                         te->copyStmt = ReadStr(AH);
2087
2088                 if (AH->version >= K_VERS_1_6)
2089                         te->namespace = ReadStr(AH);
2090
2091                 if (AH->version >= K_VERS_1_10)
2092                         te->tablespace = ReadStr(AH);
2093
2094                 te->owner = ReadStr(AH);
2095                 if (AH->version >= K_VERS_1_9)
2096                 {
2097                         if (strcmp(ReadStr(AH), "true") == 0)
2098                                 te->withOids = true;
2099                         else
2100                                 te->withOids = false;
2101                 }
2102                 else
2103                         te->withOids = true;
2104
2105                 /* Read TOC entry dependencies */
2106                 if (AH->version >= K_VERS_1_5)
2107                 {
2108                         depSize = 100;
2109                         deps = (DumpId *) malloc(sizeof(DumpId) * depSize);
2110                         depIdx = 0;
2111                         for (;;)
2112                         {
2113                                 tmp = ReadStr(AH);
2114                                 if (!tmp)
2115                                         break;          /* end of list */
2116                                 if (depIdx >= depSize)
2117                                 {
2118                                         depSize *= 2;
2119                                         deps = (DumpId *) realloc(deps, sizeof(DumpId) * depSize);
2120                                 }
2121                                 sscanf(tmp, "%d", &deps[depIdx]);
2122                                 free(tmp);
2123                                 depIdx++;
2124                         }
2125
2126                         if (depIdx > 0)         /* We have a non-null entry */
2127                         {
2128                                 deps = (DumpId *) realloc(deps, sizeof(DumpId) * depIdx);
2129                                 te->dependencies = deps;
2130                                 te->nDeps = depIdx;
2131                         }
2132                         else
2133                         {
2134                                 free(deps);
2135                                 te->dependencies = NULL;
2136                                 te->nDeps = 0;
2137                         }
2138                 }
2139                 else
2140                 {
2141                         te->dependencies = NULL;
2142                         te->nDeps = 0;
2143                 }
2144
2145                 if (AH->ReadExtraTocPtr)
2146                         (*AH->ReadExtraTocPtr) (AH, te);
2147
2148                 ahlog(AH, 3, "read TOC entry %d (ID %d) for %s %s\n",
2149                           i, te->dumpId, te->desc, te->tag);
2150
2151                 /* link completed entry into TOC circular list */
2152                 te->prev = AH->toc->prev;
2153                 AH->toc->prev->next = te;
2154                 AH->toc->prev = te;
2155                 te->next = AH->toc;
2156
2157                 /* special processing immediately upon read for some items */
2158                 if (strcmp(te->desc, "ENCODING") == 0)
2159                         processEncodingEntry(AH, te);
2160                 else if (strcmp(te->desc, "STDSTRINGS") == 0)
2161                         processStdStringsEntry(AH, te);
2162         }
2163 }
2164
2165 static void
2166 processEncodingEntry(ArchiveHandle *AH, TocEntry *te)
2167 {
2168         /* te->defn should have the form SET client_encoding = 'foo'; */
2169         char       *defn = strdup(te->defn);
2170         char       *ptr1;
2171         char       *ptr2 = NULL;
2172         int                     encoding;
2173
2174         ptr1 = strchr(defn, '\'');
2175         if (ptr1)
2176                 ptr2 = strchr(++ptr1, '\'');
2177         if (ptr2)
2178         {
2179                 *ptr2 = '\0';
2180                 encoding = pg_char_to_encoding(ptr1);
2181                 if (encoding < 0)
2182                         die_horribly(AH, modulename, "unrecognized encoding \"%s\"\n",
2183                                                  ptr1);
2184                 AH->public.encoding = encoding;
2185         }
2186         else
2187                 die_horribly(AH, modulename, "invalid ENCODING item: %s\n",
2188                                          te->defn);
2189
2190         free(defn);
2191 }
2192
2193 static void
2194 processStdStringsEntry(ArchiveHandle *AH, TocEntry *te)
2195 {
2196         /* te->defn should have the form SET standard_conforming_strings = 'x'; */
2197         char       *ptr1;
2198
2199         ptr1 = strchr(te->defn, '\'');
2200         if (ptr1 && strncmp(ptr1, "'on'", 4) == 0)
2201                 AH->public.std_strings = true;
2202         else if (ptr1 && strncmp(ptr1, "'off'", 5) == 0)
2203                 AH->public.std_strings = false;
2204         else
2205                 die_horribly(AH, modulename, "invalid STDSTRINGS item: %s\n",
2206                                          te->defn);
2207 }
2208
2209 static teReqs
2210 _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
2211 {
2212         teReqs          res = REQ_ALL;
2213
2214         /* ENCODING and STDSTRINGS items are dumped specially, so always reject */
2215         if (strcmp(te->desc, "ENCODING") == 0 ||
2216                 strcmp(te->desc, "STDSTRINGS") == 0)
2217                 return 0;
2218
2219         /* If it's an ACL, maybe ignore it */
2220         if ((!include_acls || ropt->aclsSkip) && strcmp(te->desc, "ACL") == 0)
2221                 return 0;
2222
2223         if (!ropt->create && strcmp(te->desc, "DATABASE") == 0)
2224                 return 0;
2225
2226         /* Check options for selective dump/restore */
2227         if (ropt->schemaNames)
2228         {
2229                 /* If no namespace is specified, it means all. */
2230                 if (!te->namespace)
2231                         return 0;
2232                 if (strcmp(ropt->schemaNames, te->namespace) != 0)
2233                         return 0;
2234         }
2235
2236         if (ropt->selTypes)
2237         {
2238                 if (strcmp(te->desc, "TABLE") == 0 ||
2239                         strcmp(te->desc, "TABLE DATA") == 0)
2240                 {
2241                         if (!ropt->selTable)
2242                                 return 0;
2243                         if (ropt->tableNames && strcmp(ropt->tableNames, te->tag) != 0)
2244                                 return 0;
2245                 }
2246                 else if (strcmp(te->desc, "INDEX") == 0)
2247                 {
2248                         if (!ropt->selIndex)
2249                                 return 0;
2250                         if (ropt->indexNames && strcmp(ropt->indexNames, te->tag) != 0)
2251                                 return 0;
2252                 }
2253                 else if (strcmp(te->desc, "FUNCTION") == 0)
2254                 {
2255                         if (!ropt->selFunction)
2256                                 return 0;
2257                         if (ropt->functionNames && strcmp(ropt->functionNames, te->tag) != 0)
2258                                 return 0;
2259                 }
2260                 else if (strcmp(te->desc, "TRIGGER") == 0)
2261                 {
2262                         if (!ropt->selTrigger)
2263                                 return 0;
2264                         if (ropt->triggerNames && strcmp(ropt->triggerNames, te->tag) != 0)
2265                                 return 0;
2266                 }
2267                 else
2268                         return 0;
2269         }
2270
2271         /*
2272          * Check if we had a dataDumper. Indicates if the entry is schema or data
2273          */
2274         if (!te->hadDumper)
2275         {
2276                 /*
2277                  * Special Case: If 'SEQUENCE SET' then it is considered a data entry
2278                  */
2279                 if (strcmp(te->desc, "SEQUENCE SET") == 0)
2280                         res = res & REQ_DATA;
2281                 else
2282                         res = res & ~REQ_DATA;
2283         }
2284
2285         /*
2286          * Special case: <Init> type with <Max OID> tag; this is obsolete and we
2287          * always ignore it.
2288          */
2289         if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))
2290                 return 0;
2291
2292         /* Mask it if we only want schema */
2293         if (ropt->schemaOnly)
2294                 res = res & REQ_SCHEMA;
2295
2296         /* Mask it we only want data */
2297         if (ropt->dataOnly)
2298                 res = res & REQ_DATA;
2299
2300         /* Mask it if we don't have a schema contribution */
2301         if (!te->defn || strlen(te->defn) == 0)
2302                 res = res & ~REQ_SCHEMA;
2303
2304         /* Finally, if there's a per-ID filter, limit based on that as well */
2305         if (ropt->idWanted && !ropt->idWanted[te->dumpId - 1])
2306                 return 0;
2307
2308         return res;
2309 }
2310
2311 /*
2312  * Issue SET commands for parameters that we want to have set the same way
2313  * at all times during execution of a restore script.
2314  */
2315 static void
2316 _doSetFixedOutputState(ArchiveHandle *AH)
2317 {
2318         /* Disable statement_timeout in archive for pg_restore/psql      */
2319         ahprintf(AH, "SET statement_timeout = 0;\n");
2320
2321         /* Select the correct character set encoding */
2322         ahprintf(AH, "SET client_encoding = '%s';\n",
2323                          pg_encoding_to_char(AH->public.encoding));
2324
2325         /* Select the correct string literal syntax */
2326         ahprintf(AH, "SET standard_conforming_strings = %s;\n",
2327                          AH->public.std_strings ? "on" : "off");
2328
2329         /* Select the role to be used during restore */
2330         if (AH->ropt && AH->ropt->use_role)
2331                 ahprintf(AH, "SET ROLE %s;\n", fmtId(AH->ropt->use_role));
2332
2333         /* Make sure function checking is disabled */
2334         ahprintf(AH, "SET check_function_bodies = false;\n");
2335
2336         /* Avoid annoying notices etc */
2337         ahprintf(AH, "SET client_min_messages = warning;\n");
2338         if (!AH->public.std_strings)
2339                 ahprintf(AH, "SET escape_string_warning = off;\n");
2340
2341         ahprintf(AH, "\n");
2342 }
2343
2344 /*
2345  * Issue a SET SESSION AUTHORIZATION command.  Caller is responsible
2346  * for updating state if appropriate.  If user is NULL or an empty string,
2347  * the specification DEFAULT will be used.
2348  */
2349 static void
2350 _doSetSessionAuth(ArchiveHandle *AH, const char *user)
2351 {
2352         PQExpBuffer cmd = createPQExpBuffer();
2353
2354         appendPQExpBuffer(cmd, "SET SESSION AUTHORIZATION ");
2355
2356         /*
2357          * SQL requires a string literal here.  Might as well be correct.
2358          */
2359         if (user && *user)
2360                 appendStringLiteralAHX(cmd, user, AH);
2361         else
2362                 appendPQExpBuffer(cmd, "DEFAULT");
2363         appendPQExpBuffer(cmd, ";");
2364
2365         if (RestoringToDB(AH))
2366         {
2367                 PGresult   *res;
2368
2369                 res = PQexec(AH->connection, cmd->data);
2370
2371                 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2372                         /* NOT warn_or_die_horribly... use -O instead to skip this. */
2373                         die_horribly(AH, modulename, "could not set session user to \"%s\": %s",
2374                                                  user, PQerrorMessage(AH->connection));
2375
2376                 PQclear(res);
2377         }
2378         else
2379                 ahprintf(AH, "%s\n\n", cmd->data);
2380
2381         destroyPQExpBuffer(cmd);
2382 }
2383
2384
2385 /*
2386  * Issue a SET default_with_oids command.  Caller is responsible
2387  * for updating state if appropriate.
2388  */
2389 static void
2390 _doSetWithOids(ArchiveHandle *AH, const bool withOids)
2391 {
2392         PQExpBuffer cmd = createPQExpBuffer();
2393
2394         appendPQExpBuffer(cmd, "SET default_with_oids = %s;", withOids ?
2395                                           "true" : "false");
2396
2397         if (RestoringToDB(AH))
2398         {
2399                 PGresult   *res;
2400
2401                 res = PQexec(AH->connection, cmd->data);
2402
2403                 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2404                         warn_or_die_horribly(AH, modulename,
2405                                                                  "could not set default_with_oids: %s",
2406                                                                  PQerrorMessage(AH->connection));
2407
2408                 PQclear(res);
2409         }
2410         else
2411                 ahprintf(AH, "%s\n\n", cmd->data);
2412
2413         destroyPQExpBuffer(cmd);
2414 }
2415
2416
2417 /*
2418  * Issue the commands to connect to the specified database.
2419  *
2420  * If we're currently restoring right into a database, this will
2421  * actually establish a connection. Otherwise it puts a \connect into
2422  * the script output.
2423  *
2424  * NULL dbname implies reconnecting to the current DB (pretty useless).
2425  */
2426 static void
2427 _reconnectToDB(ArchiveHandle *AH, const char *dbname)
2428 {
2429         if (RestoringToDB(AH))
2430                 ReconnectToServer(AH, dbname, NULL);
2431         else
2432         {
2433                 PQExpBuffer qry = createPQExpBuffer();
2434
2435                 appendPQExpBuffer(qry, "\\connect %s\n\n",
2436                                                   dbname ? fmtId(dbname) : "-");
2437                 ahprintf(AH, "%s", qry->data);
2438                 destroyPQExpBuffer(qry);
2439         }
2440
2441         /*
2442          * NOTE: currUser keeps track of what the imaginary session user in our
2443          * script is.  It's now effectively reset to the original userID.
2444          */
2445         if (AH->currUser)
2446                 free(AH->currUser);
2447         AH->currUser = NULL;
2448
2449         /* don't assume we still know the output schema, tablespace, etc either */
2450         if (AH->currSchema)
2451                 free(AH->currSchema);
2452         AH->currSchema = NULL;
2453         if (AH->currTablespace)
2454                 free(AH->currTablespace);
2455         AH->currTablespace = NULL;
2456         AH->currWithOids = -1;
2457
2458         /* re-establish fixed state */
2459         _doSetFixedOutputState(AH);
2460 }
2461
2462 /*
2463  * Become the specified user, and update state to avoid redundant commands
2464  *
2465  * NULL or empty argument is taken to mean restoring the session default
2466  */
2467 static void
2468 _becomeUser(ArchiveHandle *AH, const char *user)
2469 {
2470         if (!user)
2471                 user = "";                              /* avoid null pointers */
2472
2473         if (AH->currUser && strcmp(AH->currUser, user) == 0)
2474                 return;                                 /* no need to do anything */
2475
2476         _doSetSessionAuth(AH, user);
2477
2478         /*
2479          * NOTE: currUser keeps track of what the imaginary session user in our
2480          * script is
2481          */
2482         if (AH->currUser)
2483                 free(AH->currUser);
2484         AH->currUser = strdup(user);
2485 }
2486
2487 /*
2488  * Become the owner of the the given TOC entry object.  If
2489  * changes in ownership are not allowed, this doesn't do anything.
2490  */
2491 static void
2492 _becomeOwner(ArchiveHandle *AH, TocEntry *te)
2493 {
2494         if (AH->ropt && (AH->ropt->noOwner || !AH->ropt->use_setsessauth))
2495                 return;
2496
2497         _becomeUser(AH, te->owner);
2498 }
2499
2500
2501 /*
2502  * Set the proper default_with_oids value for the table.
2503  */
2504 static void
2505 _setWithOids(ArchiveHandle *AH, TocEntry *te)
2506 {
2507         if (AH->currWithOids != te->withOids)
2508         {
2509                 _doSetWithOids(AH, te->withOids);
2510                 AH->currWithOids = te->withOids;
2511         }
2512 }
2513
2514
2515 /*
2516  * Issue the commands to select the specified schema as the current schema
2517  * in the target database.
2518  */
2519 static void
2520 _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
2521 {
2522         PQExpBuffer qry;
2523
2524         if (!schemaName || *schemaName == '\0' ||
2525                 (AH->currSchema && strcmp(AH->currSchema, schemaName) == 0))
2526                 return;                                 /* no need to do anything */
2527
2528         qry = createPQExpBuffer();
2529
2530         appendPQExpBuffer(qry, "SET search_path = %s",
2531                                           fmtId(schemaName));
2532         if (strcmp(schemaName, "pg_catalog") != 0)
2533                 appendPQExpBuffer(qry, ", pg_catalog");
2534
2535         if (RestoringToDB(AH))
2536         {
2537                 PGresult   *res;
2538
2539                 res = PQexec(AH->connection, qry->data);
2540
2541                 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2542                         warn_or_die_horribly(AH, modulename,
2543                                                                  "could not set search_path to \"%s\": %s",
2544                                                                  schemaName, PQerrorMessage(AH->connection));
2545
2546                 PQclear(res);
2547         }
2548         else
2549                 ahprintf(AH, "%s;\n\n", qry->data);
2550
2551         if (AH->currSchema)
2552                 free(AH->currSchema);
2553         AH->currSchema = strdup(schemaName);
2554
2555         destroyPQExpBuffer(qry);
2556 }
2557
2558 /*
2559  * Issue the commands to select the specified tablespace as the current one
2560  * in the target database.
2561  */
2562 static void
2563 _selectTablespace(ArchiveHandle *AH, const char *tablespace)
2564 {
2565         PQExpBuffer qry;
2566         const char *want,
2567                            *have;
2568
2569         /* do nothing in --no-tablespaces mode */
2570         if (AH->ropt->noTablespace)
2571                 return;
2572
2573         have = AH->currTablespace;
2574         want = tablespace;
2575
2576         /* no need to do anything for non-tablespace object */
2577         if (!want)
2578                 return;
2579
2580         if (have && strcmp(want, have) == 0)
2581                 return;                                 /* no need to do anything */
2582
2583         qry = createPQExpBuffer();
2584
2585         if (strcmp(want, "") == 0)
2586         {
2587                 /* We want the tablespace to be the database's default */
2588                 appendPQExpBuffer(qry, "SET default_tablespace = ''");
2589         }
2590         else
2591         {
2592                 /* We want an explicit tablespace */
2593                 appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want));
2594         }
2595
2596         if (RestoringToDB(AH))
2597         {
2598                 PGresult   *res;
2599
2600                 res = PQexec(AH->connection, qry->data);
2601
2602                 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2603                         warn_or_die_horribly(AH, modulename,
2604                                                                  "could not set default_tablespace to %s: %s",
2605                                                                  fmtId(want), PQerrorMessage(AH->connection));
2606
2607                 PQclear(res);
2608         }
2609         else
2610                 ahprintf(AH, "%s;\n\n", qry->data);
2611
2612         if (AH->currTablespace)
2613                 free(AH->currTablespace);
2614         AH->currTablespace = strdup(want);
2615
2616         destroyPQExpBuffer(qry);
2617 }
2618
2619 /*
2620  * Extract an object description for a TOC entry, and append it to buf.
2621  *
2622  * This is not quite as general as it may seem, since it really only
2623  * handles constructing the right thing to put into ALTER ... OWNER TO.
2624  *
2625  * The whole thing is pretty grotty, but we are kind of stuck since the
2626  * information used is all that's available in older dump files.
2627  */
2628 static void
2629 _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
2630 {
2631         const char *type = te->desc;
2632
2633         /* Use ALTER TABLE for views and sequences */
2634         if (strcmp(type, "VIEW") == 0 || strcmp(type, "SEQUENCE") == 0)
2635                 type = "TABLE";
2636
2637         /* objects named by a schema and name */
2638         if (strcmp(type, "CONVERSION") == 0 ||
2639                 strcmp(type, "DOMAIN") == 0 ||
2640                 strcmp(type, "TABLE") == 0 ||
2641                 strcmp(type, "TYPE") == 0 ||
2642                 strcmp(type, "TEXT SEARCH DICTIONARY") == 0 ||
2643                 strcmp(type, "TEXT SEARCH CONFIGURATION") == 0)
2644         {
2645                 appendPQExpBuffer(buf, "%s ", type);
2646                 if (te->namespace && te->namespace[0])  /* is null pre-7.3 */
2647                         appendPQExpBuffer(buf, "%s.", fmtId(te->namespace));
2648
2649                 /*
2650                  * Pre-7.3 pg_dump would sometimes (not always) put a fmtId'd name
2651                  * into te->tag for an index. This check is heuristic, so make its
2652                  * scope as narrow as possible.
2653                  */
2654                 if (AH->version < K_VERS_1_7 &&
2655                         te->tag[0] == '"' &&
2656                         te->tag[strlen(te->tag) - 1] == '"' &&
2657                         strcmp(type, "INDEX") == 0)
2658                         appendPQExpBuffer(buf, "%s", te->tag);
2659                 else
2660                         appendPQExpBuffer(buf, "%s", fmtId(te->tag));
2661                 return;
2662         }
2663
2664         /* objects named by just a name */
2665         if (strcmp(type, "DATABASE") == 0 ||
2666                 strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
2667                 strcmp(type, "SCHEMA") == 0 ||
2668                 strcmp(type, "FOREIGN DATA WRAPPER") == 0 ||
2669                 strcmp(type, "SERVER") == 0 ||
2670                 strcmp(type, "USER MAPPING") == 0)
2671         {
2672                 appendPQExpBuffer(buf, "%s %s", type, fmtId(te->tag));
2673                 return;
2674         }
2675
2676         /*
2677          * These object types require additional decoration.  Fortunately, the
2678          * information needed is exactly what's in the DROP command.
2679          */
2680         if (strcmp(type, "AGGREGATE") == 0 ||
2681                 strcmp(type, "FUNCTION") == 0 ||
2682                 strcmp(type, "OPERATOR") == 0 ||
2683                 strcmp(type, "OPERATOR CLASS") == 0 ||
2684                 strcmp(type, "OPERATOR FAMILY") == 0)
2685         {
2686                 /* Chop "DROP " off the front and make a modifiable copy */
2687                 char       *first = strdup(te->dropStmt + 5);
2688                 char       *last;
2689
2690                 /* point to last character in string */
2691                 last = first + strlen(first) - 1;
2692
2693                 /* Strip off any ';' or '\n' at the end */
2694                 while (last >= first && (*last == '\n' || *last == ';'))
2695                         last--;
2696                 *(last + 1) = '\0';
2697
2698                 appendPQExpBufferStr(buf, first);
2699
2700                 free(first);
2701                 return;
2702         }
2703
2704         write_msg(modulename, "WARNING: don't know how to set owner for object type %s\n",
2705                           type);
2706 }
2707
2708 static void
2709 _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData, bool acl_pass)
2710 {
2711         /* ACLs are dumped only during acl pass */
2712         if (acl_pass)
2713         {
2714                 if (strcmp(te->desc, "ACL") != 0)
2715                         return;
2716         }
2717         else
2718         {
2719                 if (strcmp(te->desc, "ACL") == 0)
2720                         return;
2721         }
2722
2723         /*
2724          * Avoid dumping the public schema, as it will already be created ...
2725          * unless we are using --clean mode, in which case it's been deleted and
2726          * we'd better recreate it.  Likewise for its comment, if any.
2727          */
2728         if (!ropt->dropSchema)
2729         {
2730                 if (strcmp(te->desc, "SCHEMA") == 0 &&
2731                         strcmp(te->tag, "public") == 0)
2732                         return;
2733                 /* The comment restore would require super-user privs, so avoid it. */
2734                 if (strcmp(te->desc, "COMMENT") == 0 &&
2735                         strcmp(te->tag, "SCHEMA public") == 0)
2736                         return;
2737         }
2738
2739         /* Select owner, schema, and tablespace as necessary */
2740         _becomeOwner(AH, te);
2741         _selectOutputSchema(AH, te->namespace);
2742         _selectTablespace(AH, te->tablespace);
2743
2744         /* Set up OID mode too */
2745         if (strcmp(te->desc, "TABLE") == 0)
2746                 _setWithOids(AH, te);
2747
2748         /* Emit header comment for item */
2749         if (!AH->noTocComments)
2750         {
2751                 const char *pfx;
2752
2753                 if (isData)
2754                         pfx = "Data for ";
2755                 else
2756                         pfx = "";
2757
2758                 ahprintf(AH, "--\n");
2759                 if (AH->public.verbose)
2760                 {
2761                         ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
2762                                          te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
2763                         if (te->nDeps > 0)
2764                         {
2765                                 int                     i;
2766
2767                                 ahprintf(AH, "-- Dependencies:");
2768                                 for (i = 0; i < te->nDeps; i++)
2769                                         ahprintf(AH, " %d", te->dependencies[i]);
2770                                 ahprintf(AH, "\n");
2771                         }
2772                 }
2773                 ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
2774                                  pfx, te->tag, te->desc,
2775                                  te->namespace ? te->namespace : "-",
2776                                  ropt->noOwner ? "-" : te->owner);
2777                 if (te->tablespace && !ropt->noTablespace)
2778                         ahprintf(AH, "; Tablespace: %s", te->tablespace);
2779                 ahprintf(AH, "\n");
2780
2781                 if (AH->PrintExtraTocPtr !=NULL)
2782                         (*AH->PrintExtraTocPtr) (AH, te);
2783                 ahprintf(AH, "--\n\n");
2784         }
2785
2786         /*
2787          * Actually print the definition.
2788          *
2789          * Really crude hack for suppressing AUTHORIZATION clause that old pg_dump
2790          * versions put into CREATE SCHEMA.  We have to do this when --no-owner
2791          * mode is selected.  This is ugly, but I see no other good way ...
2792          */
2793         if (ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0)
2794         {
2795                 ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
2796         }
2797         else
2798         {
2799                 if (strlen(te->defn) > 0)
2800                         ahprintf(AH, "%s\n\n", te->defn);
2801         }
2802
2803         /*
2804          * If we aren't using SET SESSION AUTH to determine ownership, we must
2805          * instead issue an ALTER OWNER command.  We assume that anything without
2806          * a DROP command is not a separately ownable object.  All the categories
2807          * with DROP commands must appear in one list or the other.
2808          */
2809         if (!ropt->noOwner && !ropt->use_setsessauth &&
2810                 strlen(te->owner) > 0 && strlen(te->dropStmt) > 0)
2811         {
2812                 if (strcmp(te->desc, "AGGREGATE") == 0 ||
2813                         strcmp(te->desc, "CONVERSION") == 0 ||
2814                         strcmp(te->desc, "DATABASE") == 0 ||
2815                         strcmp(te->desc, "DOMAIN") == 0 ||
2816                         strcmp(te->desc, "FUNCTION") == 0 ||
2817                         strcmp(te->desc, "OPERATOR") == 0 ||
2818                         strcmp(te->desc, "OPERATOR CLASS") == 0 ||
2819                         strcmp(te->desc, "OPERATOR FAMILY") == 0 ||
2820                         strcmp(te->desc, "PROCEDURAL LANGUAGE") == 0 ||
2821                         strcmp(te->desc, "SCHEMA") == 0 ||
2822                         strcmp(te->desc, "TABLE") == 0 ||
2823                         strcmp(te->desc, "TYPE") == 0 ||
2824                         strcmp(te->desc, "VIEW") == 0 ||
2825                         strcmp(te->desc, "SEQUENCE") == 0 ||
2826                         strcmp(te->desc, "TEXT SEARCH DICTIONARY") == 0 ||
2827                         strcmp(te->desc, "TEXT SEARCH CONFIGURATION") == 0 ||
2828                         strcmp(te->desc, "FOREIGN DATA WRAPPER") == 0 ||
2829                         strcmp(te->desc, "SERVER") == 0)
2830                 {
2831                         PQExpBuffer temp = createPQExpBuffer();
2832
2833                         appendPQExpBuffer(temp, "ALTER ");
2834                         _getObjectDescription(temp, te, AH);
2835                         appendPQExpBuffer(temp, " OWNER TO %s;", fmtId(te->owner));
2836                         ahprintf(AH, "%s\n\n", temp->data);
2837                         destroyPQExpBuffer(temp);
2838                 }
2839                 else if (strcmp(te->desc, "CAST") == 0 ||
2840                                  strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
2841                                  strcmp(te->desc, "CONSTRAINT") == 0 ||
2842                                  strcmp(te->desc, "DEFAULT") == 0 ||
2843                                  strcmp(te->desc, "FK CONSTRAINT") == 0 ||
2844                                  strcmp(te->desc, "INDEX") == 0 ||
2845                                  strcmp(te->desc, "RULE") == 0 ||
2846                                  strcmp(te->desc, "TRIGGER") == 0 ||
2847                                  strcmp(te->desc, "USER MAPPING") == 0)
2848                 {
2849                         /* these object types don't have separate owners */
2850                 }
2851                 else
2852                 {
2853                         write_msg(modulename, "WARNING: don't know how to set owner for object type %s\n",
2854                                           te->desc);
2855                 }
2856         }
2857
2858         /*
2859          * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
2860          * commands, so we can no longer assume we know the current auth setting.
2861          */
2862         if (strncmp(te->desc, "ACL", 3) == 0)
2863         {
2864                 if (AH->currUser)
2865                         free(AH->currUser);
2866                 AH->currUser = NULL;
2867         }
2868 }
2869
2870 void
2871 WriteHead(ArchiveHandle *AH)
2872 {
2873         struct tm       crtm;
2874
2875         (*AH->WriteBufPtr) (AH, "PGDMP", 5);            /* Magic code */
2876         (*AH->WriteBytePtr) (AH, AH->vmaj);
2877         (*AH->WriteBytePtr) (AH, AH->vmin);
2878         (*AH->WriteBytePtr) (AH, AH->vrev);
2879         (*AH->WriteBytePtr) (AH, AH->intSize);
2880         (*AH->WriteBytePtr) (AH, AH->offSize);
2881         (*AH->WriteBytePtr) (AH, AH->format);
2882
2883 #ifndef HAVE_LIBZ
2884         if (AH->compression != 0)
2885                 write_msg(modulename, "WARNING: requested compression not available in this "
2886                                   "installation -- archive will be uncompressed\n");
2887
2888         AH->compression = 0;
2889 #endif
2890
2891         WriteInt(AH, AH->compression);
2892
2893         crtm = *localtime(&AH->createDate);
2894         WriteInt(AH, crtm.tm_sec);
2895         WriteInt(AH, crtm.tm_min);
2896         WriteInt(AH, crtm.tm_hour);
2897         WriteInt(AH, crtm.tm_mday);
2898         WriteInt(AH, crtm.tm_mon);
2899         WriteInt(AH, crtm.tm_year);
2900         WriteInt(AH, crtm.tm_isdst);
2901         WriteStr(AH, PQdb(AH->connection));
2902         WriteStr(AH, AH->public.remoteVersionStr);
2903         WriteStr(AH, PG_VERSION);
2904 }
2905
2906 void
2907 ReadHead(ArchiveHandle *AH)
2908 {
2909         char            tmpMag[7];
2910         int                     fmt;
2911         struct tm       crtm;
2912
2913         /* If we haven't already read the header... */
2914         if (!AH->readHeader)
2915         {
2916                 if ((*AH->ReadBufPtr) (AH, tmpMag, 5) != 5)
2917                         die_horribly(AH, modulename, "unexpected end of file\n");
2918
2919                 if (strncmp(tmpMag, "PGDMP", 5) != 0)
2920                         die_horribly(AH, modulename, "did not find magic string in file header\n");
2921
2922                 AH->vmaj = (*AH->ReadBytePtr) (AH);
2923                 AH->vmin = (*AH->ReadBytePtr) (AH);
2924
2925                 if (AH->vmaj > 1 || ((AH->vmaj == 1) && (AH->vmin > 0)))                /* Version > 1.0 */
2926                         AH->vrev = (*AH->ReadBytePtr) (AH);
2927                 else
2928                         AH->vrev = 0;
2929
2930                 AH->version = ((AH->vmaj * 256 + AH->vmin) * 256 + AH->vrev) * 256 + 0;
2931
2932
2933                 if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
2934                         die_horribly(AH, modulename, "unsupported version (%d.%d) in file header\n",
2935                                                  AH->vmaj, AH->vmin);
2936
2937                 AH->intSize = (*AH->ReadBytePtr) (AH);
2938                 if (AH->intSize > 32)
2939                         die_horribly(AH, modulename, "sanity check on integer size (%lu) failed\n",
2940                                                  (unsigned long) AH->intSize);
2941
2942                 if (AH->intSize > sizeof(int))
2943                         write_msg(modulename, "WARNING: archive was made on a machine with larger integers, some operations might fail\n");
2944
2945                 if (AH->version >= K_VERS_1_7)
2946                         AH->offSize = (*AH->ReadBytePtr) (AH);
2947                 else
2948                         AH->offSize = AH->intSize;
2949
2950                 fmt = (*AH->ReadBytePtr) (AH);
2951
2952                 if (AH->format != fmt)
2953                         die_horribly(AH, modulename, "expected format (%d) differs from format found in file (%d)\n",
2954                                                  AH->format, fmt);
2955         }
2956
2957         if (AH->version >= K_VERS_1_2)
2958         {
2959                 if (AH->version < K_VERS_1_4)
2960                         AH->compression = (*AH->ReadBytePtr) (AH);
2961                 else
2962                         AH->compression = ReadInt(AH);
2963         }
2964         else
2965                 AH->compression = Z_DEFAULT_COMPRESSION;
2966
2967 #ifndef HAVE_LIBZ
2968         if (AH->compression != 0)
2969                 write_msg(modulename, "WARNING: archive is compressed, but this installation does not support compression -- no data will be available\n");
2970 #endif
2971
2972         if (AH->version >= K_VERS_1_4)
2973         {
2974                 crtm.tm_sec = ReadInt(AH);
2975                 crtm.tm_min = ReadInt(AH);
2976                 crtm.tm_hour = ReadInt(AH);
2977                 crtm.tm_mday = ReadInt(AH);
2978                 crtm.tm_mon = ReadInt(AH);
2979                 crtm.tm_year = ReadInt(AH);
2980                 crtm.tm_isdst = ReadInt(AH);
2981
2982                 AH->archdbname = ReadStr(AH);
2983
2984                 AH->createDate = mktime(&crtm);
2985
2986                 if (AH->createDate == (time_t) -1)
2987                         write_msg(modulename, "WARNING: invalid creation date in header\n");
2988         }
2989
2990         if (AH->version >= K_VERS_1_10)
2991         {
2992                 AH->archiveRemoteVersion = ReadStr(AH);
2993                 AH->archiveDumpVersion = ReadStr(AH);
2994         }
2995
2996 }
2997
2998
2999 /*
3000  * checkSeek
3001  *        check to see if fseek can be performed.
3002  */
3003 bool
3004 checkSeek(FILE *fp)
3005 {
3006         if (fseeko(fp, 0, SEEK_CUR) != 0)
3007                 return false;
3008         else if (sizeof(pgoff_t) > sizeof(long))
3009         {
3010                 /*
3011                  * At this point, pgoff_t is too large for long, so we return based on
3012                  * whether an pgoff_t version of fseek is available.
3013                  */
3014 #ifdef HAVE_FSEEKO
3015                 return true;
3016 #else
3017                 return false;
3018 #endif
3019         }
3020         else
3021                 return true;
3022 }
3023
3024
3025 /*
3026  * dumpTimestamp
3027  */
3028 static void
3029 dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim)
3030 {
3031         char            buf[256];
3032
3033         /*
3034          * We don't print the timezone on Win32, because the names are long and
3035          * localized, which means they may contain characters in various random
3036          * encodings; this has been seen to cause encoding errors when reading the
3037          * dump script.
3038          */
3039         if (strftime(buf, sizeof(buf),
3040 #ifndef WIN32
3041                                  "%Y-%m-%d %H:%M:%S %Z",
3042 #else
3043                                  "%Y-%m-%d %H:%M:%S",
3044 #endif
3045                                  localtime(&tim)) != 0)
3046                 ahprintf(AH, "-- %s %s\n\n", msg, buf);
3047 }
3048
3049
3050 /*
3051  * Main engine for parallel restore.
3052  *
3053  * Work is done in three phases.
3054  * First we process tocEntries until we come to one that is marked
3055  * SECTION_DATA or SECTION_POST_DATA, in a single connection, just as for a
3056  * standard restore.  Second we process the remaining non-ACL steps in
3057  * parallel worker children (threads on Windows, processes on Unix), each of
3058  * which connects separately to the database.  Finally we process all the ACL
3059  * entries in a single connection (that happens back in RestoreArchive).
3060  */
3061 static void
3062 restore_toc_entries_parallel(ArchiveHandle *AH)
3063 {
3064         RestoreOptions *ropt = AH->ropt;
3065         int                     n_slots = ropt->number_of_jobs;
3066         ParallelSlot *slots;
3067         int                     work_status;
3068         int                     next_slot;
3069         TocEntry   *first_unprocessed = AH->toc->next;
3070         TocEntry   *next_work_item;
3071         thandle         ret_child;
3072         TocEntry   *te;
3073
3074         ahlog(AH,2,"entering restore_toc_entries_parallel\n");
3075
3076         /* we haven't got round to making this work for all archive formats */
3077         if (AH->ClonePtr == NULL || AH->ReopenPtr == NULL)
3078                 die_horribly(AH, modulename, "parallel restore is not supported with this archive file format\n");
3079
3080         slots = (ParallelSlot *) calloc(sizeof(ParallelSlot), n_slots);
3081
3082         /* Adjust dependency information */
3083         fix_dependencies(AH);
3084
3085         /*
3086          * Do all the early stuff in a single connection in the parent.
3087          * There's no great point in running it in parallel, in fact it will
3088          * actually run faster in a single connection because we avoid all the
3089          * connection and setup overhead.
3090          */
3091         while ((next_work_item = get_next_work_item(AH, &first_unprocessed,
3092                                                                                                 NULL, 0)) != NULL)
3093         {
3094                 if (next_work_item->section == SECTION_DATA ||
3095                         next_work_item->section == SECTION_POST_DATA)
3096                         break;
3097
3098                 ahlog(AH, 1, "processing item %d %s %s\n",
3099                           next_work_item->dumpId,
3100                           next_work_item->desc, next_work_item->tag);
3101
3102                 (void) restore_toc_entry(AH, next_work_item, ropt, false);
3103
3104                 next_work_item->restored = true;
3105                 reduce_dependencies(AH, next_work_item);
3106         }
3107
3108         /*
3109          * Now close parent connection in prep for parallel steps.  We do this
3110          * mainly to ensure that we don't exceed the specified number of parallel
3111          * connections.
3112          */
3113         PQfinish(AH->connection);
3114         AH->connection = NULL;
3115
3116         /* blow away any transient state from the old connection */
3117         if (AH->currUser)
3118                 free(AH->currUser);
3119         AH->currUser = NULL;
3120         if (AH->currSchema)
3121                 free(AH->currSchema);
3122         AH->currSchema = NULL;
3123         if (AH->currTablespace)
3124                 free(AH->currTablespace);
3125         AH->currTablespace = NULL;
3126         AH->currWithOids = -1;
3127
3128         /*
3129          * main parent loop
3130          *
3131          * Keep going until there is no worker still running AND there is no work
3132          * left to be done.
3133          */
3134
3135         ahlog(AH,1,"entering main parallel loop\n");
3136
3137         while ((next_work_item = get_next_work_item(AH, &first_unprocessed,
3138                                                                                                 slots, n_slots)) != NULL ||
3139                    work_in_progress(slots, n_slots))
3140         {
3141                 if (next_work_item != NULL)
3142                 {
3143                         teReqs    reqs;
3144
3145                         /* If not to be dumped, don't waste time launching a worker */
3146                         reqs = _tocEntryRequired(next_work_item, AH->ropt, false);
3147                         if ((reqs & (REQ_SCHEMA | REQ_DATA)) == 0)
3148                         {
3149                                 ahlog(AH, 1, "skipping item %d %s %s\n",
3150                                           next_work_item->dumpId,
3151                                           next_work_item->desc, next_work_item->tag);
3152
3153                                 next_work_item->restored = true;
3154                                 reduce_dependencies(AH, next_work_item);
3155
3156                                 continue;
3157                         }
3158
3159                         if ((next_slot = get_next_slot(slots, n_slots)) != NO_SLOT)
3160                         {
3161                                 /* There is work still to do and a worker slot available */
3162                                 thandle child;
3163                                 RestoreArgs *args;
3164
3165                                 ahlog(AH, 1, "launching item %d %s %s\n",
3166                                           next_work_item->dumpId,
3167                                           next_work_item->desc, next_work_item->tag);
3168
3169                                 next_work_item->restored = true;
3170
3171                                 /* this memory is dealloced in mark_work_done() */
3172                                 args = malloc(sizeof(RestoreArgs));
3173                                 args->AH = CloneArchive(AH);
3174                                 args->te = next_work_item;
3175
3176                                 /* run the step in a worker child */
3177                                 child = spawn_restore(args);
3178
3179                                 slots[next_slot].child_id = child;
3180                                 slots[next_slot].args = args;
3181
3182                                 continue;
3183                         }
3184                 }
3185
3186                 /*
3187                  * If we get here there must be work being done.  Either there is no
3188                  * work available to schedule (and work_in_progress returned true) or
3189                  * there are no slots available.  So we wait for a worker to finish,
3190                  * and process the result.
3191                  */
3192                 ret_child = reap_child(slots, n_slots, &work_status);
3193
3194                 if (WIFEXITED(work_status))
3195                 {
3196                         mark_work_done(AH, ret_child, WEXITSTATUS(work_status),
3197                                                    slots, n_slots);
3198                 }
3199                 else
3200                 {
3201                         die_horribly(AH, modulename, "worker process crashed: status %d\n",
3202                                                  work_status);
3203                 }
3204         }
3205
3206         ahlog(AH,1,"finished main parallel loop\n");
3207
3208         /*
3209          * Now reconnect the single parent connection.
3210          */
3211         ConnectDatabase((Archive *) AH, ropt->dbname,
3212                                         ropt->pghost, ropt->pgport, ropt->username,
3213                                         ropt->promptPassword);
3214
3215         _doSetFixedOutputState(AH);
3216
3217         /*
3218          * Make sure there is no non-ACL work left due to, say,
3219          * circular dependencies, or some other pathological condition.
3220          * If so, do it in the single parent connection.
3221          */
3222         for (te = AH->toc->next; te != AH->toc; te = te->next)
3223         {
3224                 if (!te->restored)
3225                 {
3226                         ahlog(AH, 1, "processing missed item %d %s %s\n",
3227                                   te->dumpId, te->desc, te->tag);
3228                         (void) restore_toc_entry(AH, te, ropt, false);
3229                 }
3230         }
3231
3232         /* The ACLs will be handled back in RestoreArchive. */
3233 }
3234
3235 /*
3236  * create a worker child to perform a restore step in parallel
3237  */
3238 static thandle
3239 spawn_restore(RestoreArgs *args)
3240 {
3241         thandle child;
3242
3243         /* Ensure stdio state is quiesced before forking */
3244         fflush(NULL);
3245
3246 #ifndef WIN32
3247         child = fork();
3248         if (child == 0)
3249         {
3250                 /* in child process */
3251                 parallel_restore(args);
3252                 die_horribly(args->AH, modulename,
3253                                          "parallel_restore should not return\n");
3254         }
3255         else if (child < 0)
3256         {
3257                 /* fork failed */
3258                 die_horribly(args->AH, modulename,
3259                                          "could not create worker process: %s\n",
3260                                          strerror(errno));
3261         }
3262 #else
3263         child = (HANDLE) _beginthreadex(NULL, 0, (void *) parallel_restore,
3264                                                                         args, 0, NULL);
3265         if (child == 0)
3266                 die_horribly(args->AH, modulename,
3267                                          "could not create worker thread: %s\n",
3268                                          strerror(errno));
3269 #endif
3270
3271         return child;
3272 }
3273
3274 /*
3275  *  collect status from a completed worker child
3276  */
3277 static thandle
3278 reap_child(ParallelSlot *slots, int n_slots, int *work_status)
3279 {
3280 #ifndef WIN32
3281         /* Unix is so much easier ... */
3282         return wait(work_status);
3283 #else
3284         static HANDLE *handles = NULL;
3285         int hindex, snum, tnum;
3286         thandle ret_child;
3287         DWORD res;
3288
3289         /* first time around only, make space for handles to listen on */
3290         if (handles == NULL)
3291                 handles = (HANDLE *) calloc(sizeof(HANDLE),n_slots);
3292
3293         /* set up list of handles to listen to */
3294         for (snum=0, tnum=0; snum < n_slots; snum++)
3295                 if (slots[snum].child_id != 0)
3296                         handles[tnum++] = slots[snum].child_id;
3297
3298         /* wait for one to finish */
3299         hindex = WaitForMultipleObjects(tnum, handles, false, INFINITE);
3300
3301         /* get handle of finished thread */
3302         ret_child = handles[hindex - WAIT_OBJECT_0];
3303
3304         /* get the result */
3305         GetExitCodeThread(ret_child,&res);
3306         *work_status = res;
3307
3308         /* dispose of handle to stop leaks */
3309         CloseHandle(ret_child);
3310
3311         return ret_child;
3312 #endif
3313 }
3314
3315 /*
3316  * are we doing anything now?
3317  */
3318 static bool
3319 work_in_progress(ParallelSlot *slots, int n_slots)
3320 {
3321         int i;
3322
3323         for (i = 0; i < n_slots; i++)
3324         {
3325                 if (slots[i].child_id != 0)
3326                         return true;
3327         }
3328         return false;
3329 }
3330
3331 /*
3332  * find the first free parallel slot (if any).
3333  */
3334 static int
3335 get_next_slot(ParallelSlot *slots, int n_slots)
3336 {
3337         int i;
3338
3339         for (i = 0; i < n_slots; i++)
3340         {
3341                 if (slots[i].child_id == 0)
3342                         return i;
3343         }
3344         return NO_SLOT;
3345 }
3346
3347
3348 /*
3349  * Check if te1 has an exclusive lock requirement for an item that te2 also
3350  * requires, whether or not te2's requirement is for an exclusive lock.
3351  */
3352 static bool
3353 has_lock_conflicts(TocEntry *te1, TocEntry *te2)
3354 {
3355         int j,k;
3356
3357         for (j = 0; j < te1->nLockDeps; j++)
3358         {
3359                 for (k = 0; k < te2->nDeps; k++)
3360                 {
3361                         if (te1->lockDeps[j] == te2->dependencies[k])
3362                                 return true;
3363                 }
3364         }
3365         return false;
3366 }
3367
3368
3369
3370 /*
3371  * Find the next work item (if any) that is capable of being run now.
3372  *
3373  * To qualify, the item must have no remaining dependencies
3374  * and no requirement for locks that is incompatible with
3375  * items currently running.
3376  *
3377  * first_unprocessed is state data that tracks the location of the first
3378  * TocEntry that's not marked 'restored'.  This avoids O(N^2) search time
3379  * with long TOC lists.  (Even though the constant is pretty small, it'd
3380  * get us eventually.)
3381  *
3382  * pref_non_data is for an alternative selection algorithm that gives
3383  * preference to non-data items if there is already a data load running.
3384  * It is currently disabled.
3385  */
3386 static TocEntry *
3387 get_next_work_item(ArchiveHandle *AH, TocEntry **first_unprocessed,
3388                                    ParallelSlot *slots, int n_slots)
3389 {
3390         bool      pref_non_data = false; /* or get from AH->ropt */
3391         TocEntry *data_te = NULL;
3392         TocEntry *te;
3393         int       i,k;
3394
3395         /*
3396          * Bogus heuristics for pref_non_data
3397          */
3398         if (pref_non_data)
3399         {
3400                 int count = 0;
3401
3402                 for (k=0; k < n_slots; k++)
3403                         if (slots[k].args->te != NULL &&
3404                                 slots[k].args->te->section == SECTION_DATA)
3405                                 count++;
3406                 if (n_slots == 0 || count * 4 < n_slots)
3407                         pref_non_data = false;
3408         }
3409
3410         /*
3411          * Advance first_unprocessed if possible.
3412          */
3413         for (te = *first_unprocessed; te != AH->toc; te = te->next)
3414         {
3415                 if (!te->restored)
3416                         break;
3417         }
3418         *first_unprocessed = te;
3419
3420         /*
3421          * Search from first_unprocessed until we find an available item.
3422          */
3423         for (; te != AH->toc; te = te->next)
3424         {
3425                 bool conflicts = false;
3426
3427                 /* Ignore if already done or still waiting on dependencies */
3428                 if (te->restored || te->depCount > 0)
3429                         continue;
3430
3431                 /*
3432                  * Check to see if the item would need exclusive lock on something
3433                  * that a currently running item also needs lock on, or vice versa.
3434                  * If so, we don't want to schedule them together.
3435                  */
3436                 for (i = 0; i < n_slots && !conflicts; i++)
3437                 {
3438                         TocEntry *running_te;
3439
3440                         if (slots[i].args == NULL)
3441                                 continue;
3442                         running_te = slots[i].args->te;
3443
3444                         if (has_lock_conflicts(te, running_te) ||
3445                                 has_lock_conflicts(running_te, te))
3446                         {
3447                                 conflicts = true;
3448                                 break;
3449                         }
3450                 }
3451
3452                 if (conflicts)
3453                         continue;
3454
3455                 if (pref_non_data && te->section == SECTION_DATA)
3456                 {
3457                         if (data_te == NULL)
3458                                 data_te = te;
3459                         continue;
3460                 }
3461
3462                 /* passed all tests, so this item can run */
3463                 return te;
3464         }
3465
3466         if (data_te != NULL)
3467                 return data_te;
3468
3469         ahlog(AH,2,"no item ready\n");
3470         return NULL;
3471 }
3472
3473
3474 /*
3475  * Restore a single TOC item in parallel with others
3476  *
3477  * this is the procedure run as a thread (Windows) or a
3478  * separate process (everything else).
3479  */
3480 static parallel_restore_result
3481 parallel_restore(RestoreArgs *args)
3482 {
3483         ArchiveHandle *AH = args->AH;
3484         TocEntry *te = args->te;
3485         RestoreOptions *ropt = AH->ropt;
3486         int retval;
3487
3488         /*
3489          * Close and reopen the input file so we have a private file pointer
3490          * that doesn't stomp on anyone else's file pointer, if we're actually 
3491          * going to need to read from the file. Otherwise, just close it
3492          * except on Windows, where it will possibly be needed by other threads.
3493          *
3494          * Note: on Windows, since we are using threads not processes, the
3495          * reopen call *doesn't* close the original file pointer but just open 
3496          * a new one.
3497          */
3498         if (te->section == SECTION_DATA )
3499                 (AH->ReopenPtr) (AH);
3500 #ifndef WIN32
3501         else
3502                 (AH->ClosePtr) (AH);
3503 #endif
3504
3505         /*
3506          * We need our own database connection, too
3507          */
3508         ConnectDatabase((Archive *) AH, ropt->dbname,
3509                                         ropt->pghost, ropt->pgport, ropt->username,
3510                                         ropt->promptPassword);
3511
3512         _doSetFixedOutputState(AH);
3513
3514         /* Restore the TOC item */
3515         retval = restore_toc_entry(AH, te, ropt, true);
3516
3517         /* And clean up */
3518         PQfinish(AH->connection);
3519         AH->connection = NULL;
3520
3521         /* If we reopened the file, we are done with it, so close it now */
3522         if (te->section == SECTION_DATA )
3523                 (AH->ClosePtr) (AH);
3524
3525         if (retval == 0 && AH->public.n_errors)
3526                 retval = WORKER_IGNORED_ERRORS;
3527
3528 #ifndef WIN32
3529         exit(retval);
3530 #else
3531         return retval;
3532 #endif
3533 }
3534
3535
3536 /*
3537  * Housekeeping to be done after a step has been parallel restored.
3538  *
3539  * Clear the appropriate slot, free all the extra memory we allocated,
3540  * update status, and reduce the dependency count of any dependent items.
3541  */
3542 static void
3543 mark_work_done(ArchiveHandle *AH, thandle worker, int status,
3544                            ParallelSlot *slots, int n_slots)
3545 {
3546         TocEntry *te = NULL;
3547         int i;
3548
3549         for (i = 0; i < n_slots; i++)
3550         {
3551                 if (slots[i].child_id == worker)
3552                 {
3553                         slots[i].child_id = 0;
3554                         te = slots[i].args->te;
3555                         DeCloneArchive(slots[i].args->AH);
3556                         free(slots[i].args);
3557                         slots[i].args = NULL;
3558
3559                         break;
3560                 }
3561         }
3562
3563         if (te == NULL)
3564                 die_horribly(AH, modulename, "could not find slot of finished worker\n");
3565
3566         ahlog(AH, 1, "finished item %d %s %s\n",
3567                   te->dumpId, te->desc, te->tag);
3568
3569         if (status == WORKER_CREATE_DONE)
3570                 mark_create_done(AH, te);
3571         else if (status == WORKER_INHIBIT_DATA)
3572         {
3573                 inhibit_data_for_failed_table(AH, te);
3574                 AH->public.n_errors++;
3575         }
3576         else if (status == WORKER_IGNORED_ERRORS)
3577                 AH->public.n_errors++;
3578         else if (status != 0)
3579                 die_horribly(AH, modulename, "worker process failed: exit code %d\n",
3580                                          status);
3581
3582         reduce_dependencies(AH, te);
3583 }
3584
3585
3586 /*
3587  * Process the dependency information into a form useful for parallel restore.
3588  *
3589  * We set up depCount fields that are the number of as-yet-unprocessed
3590  * dependencies for each TOC entry.
3591  *
3592  * We also identify locking dependencies so that we can avoid trying to
3593  * schedule conflicting items at the same time.
3594  */
3595 static void
3596 fix_dependencies(ArchiveHandle *AH)
3597 {
3598         TocEntry  **tocsByDumpId;
3599         TocEntry   *te;
3600         int i;
3601
3602         /*
3603          * For some of the steps here, it is convenient to have an array that
3604          * indexes the TOC entries by dump ID, rather than searching the TOC
3605          * list repeatedly.  Entries for dump IDs not present in the TOC will
3606          * be NULL.
3607          *
3608          * Also, initialize the depCount fields.
3609          */
3610         tocsByDumpId = (TocEntry **) calloc(AH->maxDumpId, sizeof(TocEntry *));
3611         for (te = AH->toc->next; te != AH->toc; te = te->next)
3612         {
3613                 tocsByDumpId[te->dumpId - 1] = te;
3614                 te->depCount = te->nDeps;
3615         }
3616
3617         /*
3618          * POST_DATA items that are shown as depending on a table need to be
3619          * re-pointed to depend on that table's data, instead.  This ensures they
3620          * won't get scheduled until the data has been loaded.  We handle this by
3621          * first finding TABLE/TABLE DATA pairs and then scanning all the
3622          * dependencies.
3623          *
3624          * Note: currently, a TABLE DATA should always have exactly one
3625          * dependency, on its TABLE item.  So we don't bother to search,
3626          * but look just at the first dependency.  We do trouble to make sure
3627          * that it's a TABLE, if possible.  However, if the dependency isn't
3628          * in the archive then just assume it was a TABLE; this is to cover
3629          * cases where the table was suppressed but we have the data and some
3630          * dependent post-data items.
3631          */
3632         for (te = AH->toc->next; te != AH->toc; te = te->next)
3633         {
3634                 if (strcmp(te->desc, "TABLE DATA") == 0 && te->nDeps > 0)
3635                 {
3636                         DumpId  tableId = te->dependencies[0];
3637
3638                         if (tocsByDumpId[tableId - 1] == NULL ||
3639                                 strcmp(tocsByDumpId[tableId - 1]->desc, "TABLE") == 0)
3640                         {
3641                                 repoint_table_dependencies(AH, tableId, te->dumpId);
3642                         }
3643                 }
3644         }
3645
3646         /*
3647          * Pre-8.4 versions of pg_dump neglected to set up a dependency from
3648          * BLOB COMMENTS to BLOBS.  Cope.  (We assume there's only one BLOBS
3649          * and only one BLOB COMMENTS in such files.)
3650          */
3651         if (AH->version < K_VERS_1_11)
3652         {
3653                 for (te = AH->toc->next; te != AH->toc; te = te->next)
3654                 {
3655                         if (strcmp(te->desc, "BLOB COMMENTS") == 0 && te->nDeps == 0)
3656                         {
3657                                 TocEntry   *te2;
3658
3659                                 for (te2 = AH->toc->next; te2 != AH->toc; te2 = te2->next)
3660                                 {
3661                                         if (strcmp(te2->desc, "BLOBS") == 0)
3662                                         {
3663                                                 te->dependencies = (DumpId *) malloc(sizeof(DumpId));
3664                                                 te->dependencies[0] = te2->dumpId;
3665                                                 te->nDeps++;
3666                                                 te->depCount++;
3667                                                 break;
3668                                         }
3669                                 }
3670                                 break;
3671                         }
3672                 }
3673         }
3674
3675         /*
3676          * It is possible that the dependencies list items that are not in the
3677          * archive at all.  Subtract such items from the depCounts.
3678          */
3679         for (te = AH->toc->next; te != AH->toc; te = te->next)
3680         {
3681                 for (i = 0; i < te->nDeps; i++)
3682                 {
3683                         if (tocsByDumpId[te->dependencies[i] - 1] == NULL)
3684                                 te->depCount--;
3685                 }
3686         }
3687
3688         /*
3689          * Lastly, work out the locking dependencies.
3690          */
3691         for (te = AH->toc->next; te != AH->toc; te = te->next)
3692         {
3693                 te->lockDeps = NULL;
3694                 te->nLockDeps = 0;
3695                 identify_locking_dependencies(te, tocsByDumpId);
3696         }
3697
3698         free(tocsByDumpId);
3699 }
3700
3701 /*
3702  * Change dependencies on tableId to depend on tableDataId instead,
3703  * but only in POST_DATA items.
3704  */
3705 static void
3706 repoint_table_dependencies(ArchiveHandle *AH,
3707                                                    DumpId tableId, DumpId tableDataId)
3708 {
3709         TocEntry   *te;
3710         int i;
3711
3712         for (te = AH->toc->next; te != AH->toc; te = te->next)
3713         {
3714                 if (te->section != SECTION_POST_DATA)
3715                         continue;
3716                 for (i = 0; i < te->nDeps; i++)
3717                 {
3718                         if (te->dependencies[i] == tableId)
3719                         {
3720                                 te->dependencies[i] = tableDataId;
3721                                 ahlog(AH, 2, "transferring dependency %d -> %d to %d\n",
3722                                           te->dumpId, tableId, tableDataId);
3723                         }
3724                 }
3725         }
3726 }
3727
3728 /*
3729  * Identify which objects we'll need exclusive lock on in order to restore
3730  * the given TOC entry (*other* than the one identified by the TOC entry
3731  * itself).  Record their dump IDs in the entry's lockDeps[] array.
3732  * tocsByDumpId[] is a convenience array to avoid searching the TOC
3733  * for each dependency.
3734  */
3735 static void
3736 identify_locking_dependencies(TocEntry *te, TocEntry **tocsByDumpId)
3737 {
3738         DumpId     *lockids;
3739         int                     nlockids;
3740         int                     i;
3741
3742         /* Quick exit if no dependencies at all */
3743         if (te->nDeps == 0)
3744                 return;
3745
3746         /* Exit if this entry doesn't need exclusive lock on other objects */
3747         if (!(strcmp(te->desc, "CONSTRAINT") == 0 ||
3748                   strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
3749                   strcmp(te->desc, "FK CONSTRAINT") == 0 ||
3750                   strcmp(te->desc, "RULE") == 0 ||
3751                   strcmp(te->desc, "TRIGGER") == 0))
3752                 return;
3753
3754         /*
3755          * We assume the item requires exclusive lock on each TABLE DATA item
3756          * listed among its dependencies.  (This was originally a dependency
3757          * on the TABLE, but fix_dependencies repointed it to the data item.
3758          * Note that all the entry types we are interested in here are POST_DATA,
3759          * so they will all have been changed this way.)
3760          */
3761         lockids = (DumpId *) malloc(te->nDeps * sizeof(DumpId));
3762         nlockids = 0;
3763         for (i = 0; i < te->nDeps; i++)
3764         {
3765                 DumpId  depid = te->dependencies[i];
3766
3767                 if (tocsByDumpId[depid - 1] &&
3768                         strcmp(tocsByDumpId[depid - 1]->desc, "TABLE DATA") == 0)
3769                         lockids[nlockids++] = depid;
3770         }
3771
3772         if (nlockids == 0)
3773         {
3774                 free(lockids);
3775                 return;
3776         }
3777
3778         te->lockDeps = realloc(lockids, nlockids * sizeof(DumpId));
3779         te->nLockDeps = nlockids;
3780 }
3781
3782 /*
3783  * Remove the specified TOC entry from the depCounts of items that depend on
3784  * it, thereby possibly making them ready-to-run.
3785  */
3786 static void
3787 reduce_dependencies(ArchiveHandle *AH, TocEntry *te)
3788 {
3789         DumpId target = te->dumpId;
3790         int i;
3791
3792         ahlog(AH,2,"reducing dependencies for %d\n",target);
3793
3794         /*
3795          * We must examine all entries, not only the ones after the target item,
3796          * because if the user used a -L switch then the original dependency-
3797          * respecting order has been destroyed by SortTocFromFile.
3798          */
3799         for (te = AH->toc->next; te != AH->toc; te = te->next)
3800         {
3801                 for (i = 0; i < te->nDeps; i++)
3802                 {
3803                         if (te->dependencies[i] == target)
3804                                 te->depCount--;
3805                 }
3806         }
3807 }
3808
3809 /*
3810  * Set the created flag on the DATA member corresponding to the given
3811  * TABLE member
3812  */
3813 static void
3814 mark_create_done(ArchiveHandle *AH, TocEntry *te)
3815 {
3816         TocEntry   *tes;
3817
3818         for (tes = AH->toc->next; tes != AH->toc; tes = tes->next)
3819         {
3820                 if (strcmp(tes->desc, "TABLE DATA") == 0 &&
3821                         strcmp(tes->tag, te->tag) == 0 &&
3822                         strcmp(tes->namespace ? tes->namespace : "",
3823                                    te->namespace ? te->namespace : "") == 0)
3824                 {
3825                         tes->created = true;
3826                         break;
3827                 }
3828         }
3829 }
3830
3831 /*
3832  * Mark the DATA member corresponding to the given TABLE member
3833  * as not wanted
3834  */
3835 static void
3836 inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te)
3837 {
3838         RestoreOptions *ropt = AH->ropt;
3839         TocEntry   *tes;
3840
3841         ahlog(AH, 1, "table \"%s\" could not be created, will not restore its data\n",
3842                   te->tag);
3843
3844         for (tes = AH->toc->next; tes != AH->toc; tes = tes->next)
3845         {
3846                 if (strcmp(tes->desc, "TABLE DATA") == 0 &&
3847                         strcmp(tes->tag, te->tag) == 0 &&
3848                         strcmp(tes->namespace ? tes->namespace : "",
3849                                    te->namespace ? te->namespace : "") == 0)
3850                 {
3851                         /* mark it unwanted; we assume idWanted array already exists */
3852                         ropt->idWanted[tes->dumpId - 1] = false;
3853                         break;
3854                 }
3855         }
3856 }
3857
3858
3859 /*
3860  * Clone and de-clone routines used in parallel restoration.
3861  *
3862  * Enough of the structure is cloned to ensure that there is no
3863  * conflict between different threads each with their own clone.
3864  *
3865  * These could be public, but no need at present.
3866  */
3867 static ArchiveHandle *
3868 CloneArchive(ArchiveHandle *AH)
3869 {
3870         ArchiveHandle *clone;
3871
3872         /* Make a "flat" copy */
3873         clone = (ArchiveHandle *) malloc(sizeof(ArchiveHandle)); 
3874         if (clone == NULL)
3875                 die_horribly(AH, modulename, "out of memory\n");
3876         memcpy(clone, AH, sizeof(ArchiveHandle));
3877
3878         /* Handle format-independent fields */
3879         clone->pgCopyBuf = createPQExpBuffer();
3880         clone->sqlBuf = createPQExpBuffer();
3881         clone->sqlparse.tagBuf = NULL;
3882
3883         /* The clone will have its own connection, so disregard connection state */
3884         clone->connection = NULL;
3885         clone->currUser = NULL;
3886         clone->currSchema = NULL;
3887         clone->currTablespace = NULL;
3888         clone->currWithOids = -1;
3889
3890         /* savedPassword must be local in case we change it while connecting */
3891         if (clone->savedPassword)
3892                 clone->savedPassword = strdup(clone->savedPassword);
3893
3894         /* clone has its own error count, too */
3895         clone->public.n_errors = 0;
3896
3897         /* Let the format-specific code have a chance too */
3898         (clone->ClonePtr) (clone);
3899
3900         return clone;
3901 }
3902
3903 /*
3904  * Release clone-local storage.
3905  *
3906  * Note: we assume any clone-local connection was already closed.
3907  */
3908 static void
3909 DeCloneArchive(ArchiveHandle *AH)
3910 {
3911         /* Clear format-specific state */
3912         (AH->DeClonePtr) (AH);
3913
3914         /* Clear state allocated by CloneArchive */
3915         destroyPQExpBuffer(AH->pgCopyBuf);
3916         destroyPQExpBuffer(AH->sqlBuf);
3917         if (AH->sqlparse.tagBuf)
3918                 destroyPQExpBuffer(AH->sqlparse.tagBuf);
3919
3920         /* Clear any connection-local state */
3921         if (AH->currUser)
3922                 free(AH->currUser);
3923         if (AH->currSchema)
3924                 free(AH->currSchema);
3925         if (AH->currTablespace)
3926                 free(AH->currTablespace);
3927         if (AH->savedPassword)
3928                 free(AH->savedPassword);
3929
3930         free(AH);
3931 }