1 /*-------------------------------------------------------------------------
5 * Private implementation of the archiver routines.
7 * See the headers to pg_restore for more details.
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.
13 * The author is not responsible for loss or damages that may
14 * result from its use.
18 * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.124 2006/02/13 21:30:19 tgl Exp $
20 *-------------------------------------------------------------------------
23 #include "pg_backup.h"
25 #include "pg_backup_archiver.h"
26 #include "pg_backup_db.h"
27 #include "dumputils.h"
31 #ifndef WIN32_CLIENT_ONLY
39 #include "pqexpbuffer.h"
40 #include "libpq/libpq-fs.h"
45 static char *modulename = gettext_noop("archiver");
48 static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
49 const int compression, ArchiveMode mode);
50 static void _getObjectDescription(PQExpBuffer buf, TocEntry *te,
52 static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData, bool acl_pass);
55 static void _doSetFixedOutputState(ArchiveHandle *AH);
56 static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
57 static void _doSetWithOids(ArchiveHandle *AH, const bool withOids);
58 static void _reconnectToDB(ArchiveHandle *AH, const char *dbname);
59 static void _becomeUser(ArchiveHandle *AH, const char *user);
60 static void _becomeOwner(ArchiveHandle *AH, TocEntry *te);
61 static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName);
62 static void _selectTablespace(ArchiveHandle *AH, const char *tablespace);
64 static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls);
65 static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
66 static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt);
67 static TocEntry *getTocEntryByDumpId(ArchiveHandle *AH, DumpId id);
68 static void _moveAfter(ArchiveHandle *AH, TocEntry *pos, TocEntry *te);
69 static int _discoverArchiveFormat(ArchiveHandle *AH);
71 static void dump_lo_buf(ArchiveHandle *AH);
72 static void _write_msg(const char *modulename, const char *fmt, va_list ap);
73 static void _die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt, va_list ap);
75 static void dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim);
81 * The objective it to make writing new formats and dumpers as simple
82 * as possible, if necessary at the expense of extra function calls etc.
87 /* Create a new archive */
90 CreateArchive(const char *FileSpec, const ArchiveFormat fmt,
91 const int compression)
94 ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression, archModeWrite);
96 return (Archive *) AH;
99 /* Open an existing archive */
102 OpenArchive(const char *FileSpec, const ArchiveFormat fmt)
104 ArchiveHandle *AH = _allocAH(FileSpec, fmt, 0, archModeRead);
106 return (Archive *) AH;
111 CloseArchive(Archive *AHX)
114 ArchiveHandle *AH = (ArchiveHandle *) AHX;
116 (*AH->ClosePtr) (AH);
118 /* Close the output */
120 res = GZCLOSE(AH->OF);
121 else if (AH->OF != stdout)
122 res = fclose(AH->OF);
125 die_horribly(AH, modulename, "could not close output archive file\n");
130 RestoreArchive(Archive *AHX, RestoreOptions *ropt)
132 ArchiveHandle *AH = (ArchiveHandle *) AHX;
139 AH->stage = STAGE_INITIALIZING;
142 * Check for nonsensical option combinations.
144 * NB: create+dropSchema is useless because if you're creating the DB,
145 * there's no need to drop individual items in it. Moreover, if we tried
146 * to do that then we'd issue the drops in the database initially
147 * connected to, not the one we will create, which is very bad...
149 if (ropt->create && ropt->dropSchema)
150 die_horribly(AH, modulename, "-C and -c are incompatible options\n");
153 * If we're using a DB connection, then connect it.
157 ahlog(AH, 1, "connecting to database for restore\n");
158 if (AH->version < K_VERS_1_3)
159 die_horribly(AH, modulename, "direct database connections are not supported in pre-1.3 archives\n");
161 /* XXX Should get this from the archive */
162 AHX->minRemoteVersion = 070100;
163 AHX->maxRemoteVersion = 999999;
165 ConnectDatabase(AHX, ropt->dbname,
166 ropt->pghost, ropt->pgport, ropt->username,
167 ropt->requirePassword, ropt->ignoreVersion);
170 * If we're talking to the DB directly, don't send comments since they
171 * obscure SQL when displaying errors
173 AH->noTocComments = 1;
177 * Work out if we have an implied data-only restore. This can happen if
178 * the dump was data only or if the user has used a toc list to exclude
179 * all of the schema data. All we do is look for schema entries - if none
180 * are found then we set the dataOnly flag.
182 * We could scan for wanted TABLE entries, but that is not the same as
183 * dataOnly. At this stage, it seems unnecessary (6-Mar-2001).
187 int impliedDataOnly = 1;
189 for (te = AH->toc->next; te != AH->toc; te = te->next)
191 reqs = _tocEntryRequired(te, ropt, true);
192 if ((reqs & REQ_SCHEMA) != 0)
193 { /* It's schema, and it's wanted */
200 ropt->dataOnly = impliedDataOnly;
201 ahlog(AH, 1, "implied data-only restore\n");
206 * Setup the output file if necessary.
208 if (ropt->filename || ropt->compression)
209 sav = SetOutput(AH, ropt->filename, ropt->compression);
211 ahprintf(AH, "--\n-- PostgreSQL database dump\n--\n\n");
213 if (AH->public.verbose)
214 dumpTimestamp(AH, "Started on", AH->createDate);
216 if (ropt->single_txn)
217 ahprintf(AH, "BEGIN;\n\n");
220 * Establish important parameter values right away.
222 _doSetFixedOutputState(AH);
224 AH->stage = STAGE_PROCESSING;
227 * Drop the items at the start, in reverse order
229 if (ropt->dropSchema)
231 for (te = AH->toc->prev; te != AH->toc; te = te->prev)
235 reqs = _tocEntryRequired(te, ropt, false /* needn't drop ACLs */ );
236 if (((reqs & REQ_SCHEMA) != 0) && te->dropStmt)
238 /* We want the schema */
239 ahlog(AH, 1, "dropping %s %s\n", te->desc, te->tag);
240 /* Select owner and schema as necessary */
241 _becomeOwner(AH, te);
242 _selectOutputSchema(AH, te->namespace);
244 ahprintf(AH, "%s", te->dropStmt);
250 * Now process each non-ACL TOC entry
252 for (te = AH->toc->next; te != AH->toc; te = te->next)
256 /* Work out what, if anything, we want from this entry */
257 reqs = _tocEntryRequired(te, ropt, false);
259 /* Dump any relevant dump warnings to stderr */
260 if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0)
262 if (!ropt->dataOnly && te->defn != NULL && strlen(te->defn) != 0)
263 write_msg(modulename, "warning from original dump file: %s\n", te->defn);
264 else if (te->copyStmt != NULL && strlen(te->copyStmt) != 0)
265 write_msg(modulename, "warning from original dump file: %s\n", te->copyStmt);
270 if ((reqs & REQ_SCHEMA) != 0) /* We want the schema */
272 ahlog(AH, 1, "creating %s %s\n", te->desc, te->tag);
274 _printTocEntry(AH, te, ropt, false, false);
277 /* If we created a DB, connect to it... */
278 if (strcmp(te->desc, "DATABASE") == 0)
280 ahlog(AH, 1, "connecting to new database \"%s\"\n", te->tag);
281 _reconnectToDB(AH, te->tag);
286 * If we have a data component, then process it
288 if ((reqs & REQ_DATA) != 0)
291 * hadDumper will be set if there is genuine data component for
292 * this node. Otherwise, we need to check the defn field for
293 * statements that need to be executed in data-only restores.
298 * If we can output the data, then restore it.
300 if (AH->PrintTocDataPtr !=NULL && (reqs & REQ_DATA) != 0)
303 if (AH->compression != 0)
304 die_horribly(AH, modulename, "cannot restore from compressed archive (not configured for compression support)\n");
307 _printTocEntry(AH, te, ropt, true, false);
309 if (strcmp(te->desc, "BLOBS") == 0)
311 ahlog(AH, 1, "restoring large object data\n");
313 _selectOutputSchema(AH, "pg_catalog");
315 (*AH->PrintTocDataPtr) (AH, te, ropt);
319 _disableTriggersIfNecessary(AH, te, ropt);
321 /* Select owner and schema as necessary */
322 _becomeOwner(AH, te);
323 _selectOutputSchema(AH, te->namespace);
325 ahlog(AH, 1, "restoring data for table \"%s\"\n",
329 * If we have a copy statement, use it. As of V1.3,
330 * these are separate to allow easy import from
331 * withing a database connection. Pre 1.3 archives can
332 * not use DB connections and are sent to output only.
334 * For V1.3+, the table data MUST have a copy
335 * statement so that we can go into appropriate mode
338 if (te->copyStmt && strlen(te->copyStmt) > 0)
340 ahprintf(AH, "%s", te->copyStmt);
341 AH->writingCopyData = true;
344 (*AH->PrintTocDataPtr) (AH, te, ropt);
346 AH->writingCopyData = false;
348 _enableTriggersIfNecessary(AH, te, ropt);
352 else if (!defnDumped)
354 /* If we haven't already dumped the defn part, do so now */
355 ahlog(AH, 1, "executing %s %s\n", te->desc, te->tag);
356 _printTocEntry(AH, te, ropt, false, false);
359 } /* end loop over TOC entries */
362 * Scan TOC again to output ownership commands and ACLs
364 for (te = AH->toc->next; te != AH->toc; te = te->next)
368 /* Work out what, if anything, we want from this entry */
369 reqs = _tocEntryRequired(te, ropt, true);
371 if ((reqs & REQ_SCHEMA) != 0) /* We want the schema */
373 ahlog(AH, 1, "setting owner and privileges for %s %s\n",
375 _printTocEntry(AH, te, ropt, false, true);
379 if (ropt->single_txn)
380 ahprintf(AH, "COMMIT;\n\n");
382 if (AH->public.verbose)
383 dumpTimestamp(AH, "Completed on", time(NULL));
385 ahprintf(AH, "--\n-- PostgreSQL database dump complete\n--\n\n");
388 * Clean up & we're done.
390 AH->stage = STAGE_FINALIZING;
392 if (ropt->filename || ropt->compression)
393 ResetOutput(AH, sav);
397 PQfinish(AH->connection);
398 AH->connection = NULL;
403 * Allocate a new RestoreOptions block.
404 * This is mainly so we can initialize it, but also for future expansion,
407 NewRestoreOptions(void)
409 RestoreOptions *opts;
411 opts = (RestoreOptions *) calloc(1, sizeof(RestoreOptions));
413 opts->format = archUnknown;
414 opts->suppressDumpWarnings = false;
415 opts->exit_on_error = false;
421 _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
423 /* This hack is only needed in a data-only restore */
424 if (!ropt->dataOnly || !ropt->disable_triggers)
427 ahlog(AH, 1, "disabling triggers for %s\n", te->tag);
430 * Become superuser if possible, since they are the only ones who can
431 * disable constraint triggers. If -S was not given, assume the initial
432 * user identity is a superuser. (XXX would it be better to become the
435 _becomeUser(AH, ropt->superuser);
440 _selectOutputSchema(AH, te->namespace);
442 ahprintf(AH, "ALTER TABLE %s DISABLE TRIGGER ALL;\n\n",
447 _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
449 /* This hack is only needed in a data-only restore */
450 if (!ropt->dataOnly || !ropt->disable_triggers)
453 ahlog(AH, 1, "enabling triggers for %s\n", te->tag);
456 * Become superuser if possible, since they are the only ones who can
457 * disable constraint triggers. If -S was not given, assume the initial
458 * user identity is a superuser. (XXX would it be better to become the
461 _becomeUser(AH, ropt->superuser);
466 _selectOutputSchema(AH, te->namespace);
468 ahprintf(AH, "ALTER TABLE %s ENABLE TRIGGER ALL;\n\n",
473 * This is a routine that is part of the dumper interface, hence the 'Archive*' parameter.
478 WriteData(Archive *AHX, const void *data, size_t dLen)
480 ArchiveHandle *AH = (ArchiveHandle *) AHX;
483 die_horribly(AH, modulename, "internal error -- WriteData cannot be called outside the context of a DataDumper routine\n");
485 return (*AH->WriteDataPtr) (AH, data, dLen);
489 * Create a new TOC entry. The TOC was designed as a TOC, but is now the
490 * repository for all metadata. But the name has stuck.
495 ArchiveEntry(Archive *AHX,
496 CatalogId catalogId, DumpId dumpId,
498 const char *namespace,
499 const char *tablespace,
500 const char *owner, bool withOids,
501 const char *desc, const char *defn,
502 const char *dropStmt, const char *copyStmt,
503 const DumpId *deps, int nDeps,
504 DataDumperPtr dumpFn, void *dumpArg)
506 ArchiveHandle *AH = (ArchiveHandle *) AHX;
509 newToc = (TocEntry *) calloc(1, sizeof(TocEntry));
511 die_horribly(AH, modulename, "out of memory\n");
514 if (dumpId > AH->maxDumpId)
515 AH->maxDumpId = dumpId;
517 newToc->prev = AH->toc->prev;
518 newToc->next = AH->toc;
519 AH->toc->prev->next = newToc;
520 AH->toc->prev = newToc;
522 newToc->catalogId = catalogId;
523 newToc->dumpId = dumpId;
525 newToc->tag = strdup(tag);
526 newToc->namespace = namespace ? strdup(namespace) : NULL;
527 newToc->tablespace = tablespace ? strdup(tablespace) : NULL;
528 newToc->owner = strdup(owner);
529 newToc->withOids = withOids;
530 newToc->desc = strdup(desc);
531 newToc->defn = strdup(defn);
532 newToc->dropStmt = strdup(dropStmt);
533 newToc->copyStmt = copyStmt ? strdup(copyStmt) : NULL;
537 newToc->dependencies = (DumpId *) malloc(nDeps * sizeof(DumpId));
538 memcpy(newToc->dependencies, deps, nDeps * sizeof(DumpId));
539 newToc->nDeps = nDeps;
543 newToc->dependencies = NULL;
547 newToc->dataDumper = dumpFn;
548 newToc->dataDumperArg = dumpArg;
549 newToc->hadDumper = dumpFn ? true : false;
551 newToc->formatData = NULL;
553 if (AH->ArchiveEntryPtr !=NULL)
554 (*AH->ArchiveEntryPtr) (AH, newToc);
559 PrintTOCSummary(Archive *AHX, RestoreOptions *ropt)
561 ArchiveHandle *AH = (ArchiveHandle *) AHX;
562 TocEntry *te = AH->toc->next;
567 sav = SetOutput(AH, ropt->filename, 0 /* no compression */ );
569 ahprintf(AH, ";\n; Archive created at %s", ctime(&AH->createDate));
570 ahprintf(AH, "; dbname: %s\n; TOC Entries: %d\n; Compression: %d\n",
571 AH->archdbname, AH->tocCount, AH->compression);
588 ahprintf(AH, "; Dump Version: %d.%d-%d\n", AH->vmaj, AH->vmin, AH->vrev);
589 ahprintf(AH, "; Format: %s\n", fmtName);
590 ahprintf(AH, "; Integer: %d bytes\n", (int) AH->intSize);
591 ahprintf(AH, "; Offset: %d bytes\n", (int) AH->offSize);
592 if (AH->archiveRemoteVersion)
593 ahprintf(AH, "; Dumped from database version: %s\n",
594 AH->archiveRemoteVersion);
595 if (AH->archiveDumpVersion)
596 ahprintf(AH, "; Dumped by pg_dump version: %s\n",
597 AH->archiveDumpVersion);
599 ahprintf(AH, ";\n;\n; Selected TOC Entries:\n;\n");
601 while (te != AH->toc)
603 if (_tocEntryRequired(te, ropt, true) != 0)
604 ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
605 te->catalogId.tableoid, te->catalogId.oid,
606 te->desc, te->namespace ? te->namespace : "-",
612 ResetOutput(AH, sav);
619 /* Called by a dumper to signal start of a BLOB */
621 StartBlob(Archive *AHX, Oid oid)
623 ArchiveHandle *AH = (ArchiveHandle *) AHX;
625 if (!AH->StartBlobPtr)
626 die_horribly(AH, modulename, "large-object output not supported in chosen format\n");
628 (*AH->StartBlobPtr) (AH, AH->currToc, oid);
633 /* Called by a dumper to signal end of a BLOB */
635 EndBlob(Archive *AHX, Oid oid)
637 ArchiveHandle *AH = (ArchiveHandle *) AHX;
640 (*AH->EndBlobPtr) (AH, AH->currToc, oid);
650 * Called by a format handler before any blobs are restored
653 StartRestoreBlobs(ArchiveHandle *AH)
656 StartTransaction(AH);
658 ahprintf(AH, "BEGIN;\n\n");
664 * Called by a format handler after all blobs are restored
667 EndRestoreBlobs(ArchiveHandle *AH)
670 CommitTransaction(AH);
672 ahprintf(AH, "COMMIT;\n\n");
674 ahlog(AH, 1, "restored %d large objects\n", AH->blobCount);
679 * Called by a format handler to initiate restoration of a blob
682 StartRestoreBlob(ArchiveHandle *AH, Oid oid)
688 /* Initialize the LO Buffer */
691 ahlog(AH, 2, "restoring large object with OID %u\n", oid);
695 loOid = lo_create(AH->connection, oid);
696 if (loOid == 0 || loOid != oid)
697 die_horribly(AH, modulename, "could not create large object %u\n",
700 AH->loFd = lo_open(AH->connection, oid, INV_WRITE);
702 die_horribly(AH, modulename, "could not open large object\n");
706 ahprintf(AH, "SELECT lo_open(lo_create(%u), %d);\n", oid, INV_WRITE);
713 EndRestoreBlob(ArchiveHandle *AH, Oid oid)
715 if (AH->lo_buf_used > 0)
717 /* Write remaining bytes from the LO buffer */
725 lo_close(AH->connection, AH->loFd);
730 ahprintf(AH, "SELECT lo_close(0);\n\n");
735 * Sorting and Reordering
739 SortTocFromFile(Archive *AHX, RestoreOptions *ropt)
741 ArchiveHandle *AH = (ArchiveHandle *) AHX;
750 /* Allocate space for the 'wanted' array, and init it */
751 ropt->idWanted = (bool *) malloc(sizeof(bool) * AH->maxDumpId);
752 memset(ropt->idWanted, 0, sizeof(bool) * AH->maxDumpId);
753 ropt->limitToList = true;
755 /* Set prev entry as head of list */
759 fh = fopen(ropt->tocFile, PG_BINARY_R);
761 die_horribly(AH, modulename, "could not open TOC file\n");
763 while (fgets(buf, sizeof(buf), fh) != NULL)
765 /* Truncate line at comment, if any */
766 cmnt = strchr(buf, ';');
770 /* Ignore if all blank */
771 if (strspn(buf, " \t\r") == strlen(buf))
774 /* Get an ID, check it's valid and not already seen */
775 id = strtol(buf, &endptr, 10);
776 if (endptr == buf || id <= 0 || id > AH->maxDumpId ||
777 ropt->idWanted[id - 1])
779 write_msg(modulename, "WARNING: line ignored: %s\n", buf);
784 te = getTocEntryByDumpId(AH, id);
786 die_horribly(AH, modulename, "could not find entry for ID %d\n",
789 ropt->idWanted[id - 1] = true;
791 _moveAfter(AH, tePrev, te);
796 die_horribly(AH, modulename, "could not close TOC file: %s\n",
800 /**********************
801 * 'Convenience functions that look like standard IO functions
802 * for writing data when in dump mode.
803 **********************/
807 archputs(const char *s, Archive *AH)
809 return WriteData(AH, s, strlen(s));
814 archprintf(Archive *AH, const char *fmt,...)
818 int bSize = strlen(fmt) + 256;
822 * This is paranoid: deal with the possibility that vsnprintf is willing
823 * to ignore trailing null or returns > 0 even if string does not fit. It
824 * may be the case that it returns cnt = bufsize
826 while (cnt < 0 || cnt >= (bSize - 1))
831 p = (char *) malloc(bSize);
833 exit_horribly(AH, modulename, "out of memory\n");
835 cnt = vsnprintf(p, bSize, fmt, ap);
838 WriteData(AH, p, cnt);
844 /*******************************
845 * Stuff below here should be 'private' to the archiver routines
846 *******************************/
849 SetOutput(ArchiveHandle *AH, char *filename, int compression)
854 /* Replace the AH output file handle */
856 sav.gzOut = AH->gzOut;
865 filename = AH->fSpec;
870 /* If compression explicitly requested, use gzopen */
872 if (compression != 0)
876 /* Don't use PG_BINARY_x since this is zlib */
877 sprintf(fmode, "wb%d", compression);
879 AH->OF = gzdopen(dup(fn), fmode);
881 AH->OF = gzopen(filename, fmode);
888 AH->OF = fdopen(dup(fn), PG_BINARY_W);
890 AH->OF = fopen(filename, PG_BINARY_W);
895 die_horribly(AH, modulename, "could not open output file: %s\n", strerror(errno));
901 ResetOutput(ArchiveHandle *AH, OutputContext sav)
906 res = GZCLOSE(AH->OF);
908 res = fclose(AH->OF);
911 die_horribly(AH, modulename, "could not close output file: %s\n",
914 AH->gzOut = sav.gzOut;
921 * Print formatted text to the output file (usually stdout).
924 ahprintf(ArchiveHandle *AH, const char *fmt,...)
928 int bSize = strlen(fmt) + 256; /* Should be enough */
932 * This is paranoid: deal with the possibility that vsnprintf is willing
933 * to ignore trailing null
937 * or returns > 0 even if string does not fit. It may be the case that it
938 * returns cnt = bufsize
940 while (cnt < 0 || cnt >= (bSize - 1))
945 p = (char *) malloc(bSize);
947 die_horribly(AH, modulename, "out of memory\n");
949 cnt = vsnprintf(p, bSize, fmt, ap);
952 ahwrite(p, 1, cnt, AH);
958 ahlog(ArchiveHandle *AH, int level, const char *fmt,...)
962 if (AH->debugLevel < level && (!AH->public.verbose || level > 1))
966 _write_msg(NULL, fmt, ap);
971 * Single place for logic which says 'We are restoring to a direct DB connection'.
974 RestoringToDB(ArchiveHandle *AH)
976 return (AH->ropt && AH->ropt->useDB && AH->connection);
980 * Dump the current contents of the LO data buffer while writing a BLOB
983 dump_lo_buf(ArchiveHandle *AH)
989 res = lo_write(AH->connection, AH->loFd, AH->lo_buf, AH->lo_buf_used);
990 ahlog(AH, 5, "wrote %lu bytes of large object data (result = %lu)\n",
991 (unsigned long) AH->lo_buf_used, (unsigned long) res);
992 if (res != AH->lo_buf_used)
993 die_horribly(AH, modulename,
994 "could not write to large object (result: %lu, expected: %lu)\n",
995 (unsigned long) res, (unsigned long) AH->lo_buf_used);
1002 str = PQescapeBytea((const unsigned char *) AH->lo_buf,
1003 AH->lo_buf_used, &len);
1005 die_horribly(AH, modulename, "out of memory\n");
1007 /* Hack: turn off writingBlob so ahwrite doesn't recurse to here */
1008 AH->writingBlob = 0;
1009 ahprintf(AH, "SELECT lowrite(0, '%s');\n", str);
1010 AH->writingBlob = 1;
1014 AH->lo_buf_used = 0;
1019 * Write buffer to the output file (usually stdout). This is user for
1020 * outputting 'restore' scripts etc. It is even possible for an archive
1021 * format to create a custom output routine to 'fake' a restore if it
1022 * wants to generate a script (see TAR output).
1025 ahwrite(const void *ptr, size_t size, size_t nmemb, ArchiveHandle *AH)
1029 if (AH->writingBlob)
1031 size_t remaining = size * nmemb;
1033 while (AH->lo_buf_used + remaining > AH->lo_buf_size)
1035 size_t avail = AH->lo_buf_size - AH->lo_buf_used;
1037 memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, avail);
1038 ptr = (const void *) ((const char *) ptr + avail);
1040 AH->lo_buf_used += avail;
1044 memcpy((char *) AH->lo_buf + AH->lo_buf_used, ptr, remaining);
1045 AH->lo_buf_used += remaining;
1047 return size * nmemb;
1051 res = GZWRITE((void *) ptr, size, nmemb, AH->OF);
1052 if (res != (nmemb * size))
1053 die_horribly(AH, modulename, "could not write to compressed archive\n");
1056 else if (AH->CustomOutPtr)
1058 res = AH->CustomOutPtr (AH, ptr, size * nmemb);
1060 if (res != (nmemb * size))
1061 die_horribly(AH, modulename, "could not write to custom output routine\n");
1067 * If we're doing a restore, and it's direct to DB, and we're
1068 * connected then send it to the DB.
1070 if (RestoringToDB(AH))
1071 return ExecuteSqlCommandBuf(AH, (void *) ptr, size * nmemb); /* Always 1, currently */
1074 res = fwrite((void *) ptr, size, nmemb, AH->OF);
1076 die_horribly(AH, modulename, "could not write to output file (%lu != %lu)\n",
1077 (unsigned long) res, (unsigned long) nmemb);
1083 /* Common exit code */
1085 _write_msg(const char *modulename, const char *fmt, va_list ap)
1088 fprintf(stderr, "%s: [%s] ", progname, _(modulename));
1090 fprintf(stderr, "%s: ", progname);
1091 vfprintf(stderr, _(fmt), ap);
1095 write_msg(const char *modulename, const char *fmt,...)
1100 _write_msg(modulename, fmt, ap);
1106 _die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt, va_list ap)
1108 _write_msg(modulename, fmt, ap);
1112 if (AH->public.verbose)
1113 write_msg(NULL, "*** aborted because of error\n");
1115 PQfinish(AH->connection);
1123 exit_horribly(Archive *AH, const char *modulename, const char *fmt,...)
1128 _die_horribly((ArchiveHandle *) AH, modulename, fmt, ap);
1132 /* Archiver use (just different arg declaration) */
1134 die_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...)
1139 _die_horribly(AH, modulename, fmt, ap);
1143 /* on some error, we may decide to go on... */
1145 warn_or_die_horribly(ArchiveHandle *AH,
1146 const char *modulename, const char *fmt,...)
1154 /* Do nothing special */
1157 case STAGE_INITIALIZING:
1158 if (AH->stage != AH->lastErrorStage)
1159 write_msg(modulename, "Error while INITIALIZING:\n");
1162 case STAGE_PROCESSING:
1163 if (AH->stage != AH->lastErrorStage)
1164 write_msg(modulename, "Error while PROCESSING TOC:\n");
1167 case STAGE_FINALIZING:
1168 if (AH->stage != AH->lastErrorStage)
1169 write_msg(modulename, "Error while FINALIZING:\n");
1172 if (AH->currentTE != NULL && AH->currentTE != AH->lastErrorTE)
1174 write_msg(modulename, "Error from TOC entry %d; %u %u %s %s %s\n",
1175 AH->currentTE->dumpId,
1176 AH->currentTE->catalogId.tableoid, AH->currentTE->catalogId.oid,
1177 AH->currentTE->desc, AH->currentTE->tag, AH->currentTE->owner);
1179 AH->lastErrorStage = AH->stage;
1180 AH->lastErrorTE = AH->currentTE;
1183 if (AH->public.exit_on_error)
1184 _die_horribly(AH, modulename, fmt, ap);
1187 _write_msg(modulename, fmt, ap);
1188 AH->public.n_errors++;
1194 _moveAfter(ArchiveHandle *AH, TocEntry *pos, TocEntry *te)
1196 te->prev->next = te->next;
1197 te->next->prev = te->prev;
1200 te->next = pos->next;
1202 pos->next->prev = te;
1209 _moveBefore(ArchiveHandle *AH, TocEntry *pos, TocEntry *te)
1211 te->prev->next = te->next;
1212 te->next->prev = te->prev;
1214 te->prev = pos->prev;
1216 pos->prev->next = te;
1222 getTocEntryByDumpId(ArchiveHandle *AH, DumpId id)
1227 while (te != AH->toc)
1229 if (te->dumpId == id)
1237 TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt)
1239 TocEntry *te = getTocEntryByDumpId(AH, id);
1244 return _tocEntryRequired(te, ropt, true);
1248 WriteOffset(ArchiveHandle *AH, off_t o, int wasSet)
1253 (*AH->WriteBytePtr) (AH, wasSet);
1255 /* Write out off_t smallest byte first, prevents endian mismatch */
1256 for (off = 0; off < sizeof(off_t); off++)
1258 (*AH->WriteBytePtr) (AH, o & 0xFF);
1261 return sizeof(off_t) + 1;
1265 ReadOffset(ArchiveHandle *AH, off_t *o)
1271 /* Initialize to zero */
1274 /* Check for old version */
1275 if (AH->version < K_VERS_1_7)
1277 /* Prior versions wrote offsets using WriteInt */
1279 /* -1 means not set */
1281 return K_OFFSET_POS_NOT_SET;
1283 return K_OFFSET_NO_DATA;
1285 /* Cast to off_t because it was written as an int. */
1287 return K_OFFSET_POS_SET;
1291 * Read the flag indicating the state of the data pointer. Check if valid
1294 * This used to be handled by a negative or zero pointer, now we use an
1295 * extra byte specifically for the state.
1297 offsetFlg = (*AH->ReadBytePtr) (AH) & 0xFF;
1301 case K_OFFSET_POS_NOT_SET:
1302 case K_OFFSET_NO_DATA:
1303 case K_OFFSET_POS_SET:
1308 die_horribly(AH, modulename, "Unexpected data offset flag %d\n", offsetFlg);
1314 for (off = 0; off < AH->offSize; off++)
1316 if (off < sizeof(off_t))
1317 *o |= ((off_t) ((*AH->ReadBytePtr) (AH))) << (off * 8);
1320 if ((*AH->ReadBytePtr) (AH) != 0)
1321 die_horribly(AH, modulename, "file offset in dump file is too large\n");
1329 WriteInt(ArchiveHandle *AH, int i)
1334 * This is a bit yucky, but I don't want to make the binary format very
1335 * dependent on representation, and not knowing much about it, I write out
1336 * a sign byte. If you change this, don't forget to change the file
1337 * version #, and modify readInt to read the new format AS WELL AS the old
1344 (*AH->WriteBytePtr) (AH, 1);
1348 (*AH->WriteBytePtr) (AH, 0);
1350 for (b = 0; b < AH->intSize; b++)
1352 (*AH->WriteBytePtr) (AH, i & 0xFF);
1356 return AH->intSize + 1;
1360 ReadInt(ArchiveHandle *AH)
1365 int sign = 0; /* Default positive */
1368 if (AH->version > K_VERS_1_0)
1369 /* Read a sign byte */
1370 sign = (*AH->ReadBytePtr) (AH);
1372 for (b = 0; b < AH->intSize; b++)
1374 bv = (*AH->ReadBytePtr) (AH) & 0xFF;
1376 res = res + (bv << bitShift);
1387 WriteStr(ArchiveHandle *AH, const char *c)
1393 res = WriteInt(AH, strlen(c));
1394 res += (*AH->WriteBufPtr) (AH, c, strlen(c));
1397 res = WriteInt(AH, -1);
1403 ReadStr(ArchiveHandle *AH)
1413 buf = (char *) malloc(l + 1);
1415 die_horribly(AH, modulename, "out of memory\n");
1417 (*AH->ReadBufPtr) (AH, (void *) buf, l);
1425 _discoverArchiveFormat(ArchiveHandle *AH)
1428 char sig[6]; /* More than enough */
1433 write_msg(modulename, "attempting to ascertain archive format\n");
1437 free(AH->lookahead);
1439 AH->lookaheadSize = 512;
1440 AH->lookahead = calloc(1, 512);
1441 AH->lookaheadLen = 0;
1442 AH->lookaheadPos = 0;
1447 fh = fopen(AH->fSpec, PG_BINARY_R);
1453 die_horribly(AH, modulename, "could not open input file: %s\n", strerror(errno));
1455 cnt = fread(sig, 1, 5, fh);
1460 die_horribly(AH, modulename, "could not read input file: %s\n", strerror(errno));
1462 die_horribly(AH, modulename, "input file is too short (read %lu, expected 5)\n",
1463 (unsigned long) cnt);
1466 /* Save it, just in case we need it later */
1467 strncpy(&AH->lookahead[0], sig, 5);
1468 AH->lookaheadLen = 5;
1470 if (strncmp(sig, "PGDMP", 5) == 0)
1472 AH->vmaj = fgetc(fh);
1473 AH->vmin = fgetc(fh);
1475 /* Save these too... */
1476 AH->lookahead[AH->lookaheadLen++] = AH->vmaj;
1477 AH->lookahead[AH->lookaheadLen++] = AH->vmin;
1479 /* Check header version; varies from V1.0 */
1480 if (AH->vmaj > 1 || ((AH->vmaj == 1) && (AH->vmin > 0))) /* Version > 1.0 */
1482 AH->vrev = fgetc(fh);
1483 AH->lookahead[AH->lookaheadLen++] = AH->vrev;
1488 /* Make a convenient integer <maj><min><rev>00 */
1489 AH->version = ((AH->vmaj * 256 + AH->vmin) * 256 + AH->vrev) * 256 + 0;
1491 AH->intSize = fgetc(fh);
1492 AH->lookahead[AH->lookaheadLen++] = AH->intSize;
1494 if (AH->version >= K_VERS_1_7)
1496 AH->offSize = fgetc(fh);
1497 AH->lookahead[AH->lookaheadLen++] = AH->offSize;
1500 AH->offSize = AH->intSize;
1502 AH->format = fgetc(fh);
1503 AH->lookahead[AH->lookaheadLen++] = AH->format;
1508 * *Maybe* we have a tar archive format file... So, read first 512
1511 cnt = fread(&AH->lookahead[AH->lookaheadLen], 1, 512 - AH->lookaheadLen, fh);
1512 AH->lookaheadLen += cnt;
1514 if (AH->lookaheadLen != 512)
1515 die_horribly(AH, modulename, "input file does not appear to be a valid archive (too short?)\n");
1517 if (!isValidTarHeader(AH->lookahead))
1518 die_horribly(AH, modulename, "input file does not appear to be a valid archive\n");
1520 AH->format = archTar;
1523 /* If we can't seek, then mark the header as read */
1524 if (fseeko(fh, 0, SEEK_SET) != 0)
1527 * NOTE: Formats that use the lookahead buffer can unset this in their
1533 AH->lookaheadLen = 0; /* Don't bother since we've reset the file */
1536 write_msg(modulename, "read %lu bytes into lookahead buffer\n",
1537 (unsigned long) AH->lookaheadLen);
1540 /* Close the file */
1542 if (fclose(fh) != 0)
1543 die_horribly(AH, modulename, "could not close the input file after reading header: %s\n",
1551 * Allocate an archive handle
1553 static ArchiveHandle *
1554 _allocAH(const char *FileSpec, const ArchiveFormat fmt,
1555 const int compression, ArchiveMode mode)
1560 write_msg(modulename, "allocating AH for %s, format %d\n", FileSpec, fmt);
1563 AH = (ArchiveHandle *) calloc(1, sizeof(ArchiveHandle));
1565 die_horribly(AH, modulename, "out of memory\n");
1567 /* AH->debugLevel = 100; */
1569 AH->vmaj = K_VERS_MAJOR;
1570 AH->vmin = K_VERS_MINOR;
1571 AH->vrev = K_VERS_REV;
1573 AH->createDate = time(NULL);
1575 AH->intSize = sizeof(int);
1576 AH->offSize = sizeof(off_t);
1579 AH->fSpec = strdup(FileSpec);
1582 * Not used; maybe later....
1584 * AH->workDir = strdup(FileSpec); for(i=strlen(FileSpec) ; i > 0 ;
1585 * i--) if (AH->workDir[i-1] == '/')
1591 AH->currUser = strdup(""); /* So it's valid, but we can free() it later
1593 AH->currSchema = strdup(""); /* ditto */
1594 AH->currWithOids = -1; /* force SET */
1596 AH->toc = (TocEntry *) calloc(1, sizeof(TocEntry));
1598 die_horribly(AH, modulename, "out of memory\n");
1600 AH->toc->next = AH->toc;
1601 AH->toc->prev = AH->toc;
1604 AH->compression = compression;
1606 AH->pgCopyBuf = createPQExpBuffer();
1607 AH->sqlBuf = createPQExpBuffer();
1609 /* Open stdout with no compression for AH output handle */
1614 * On Windows, we need to use binary mode to read/write non-text archive
1615 * formats. Force stdin/stdout into binary mode if that is what we are
1619 if (fmt != archNull &&
1620 (AH->fSpec == NULL || strcmp(AH->fSpec, "") == 0))
1622 if (mode == archModeWrite)
1623 setmode(fileno(stdout), O_BINARY);
1625 setmode(fileno(stdin), O_BINARY);
1630 write_msg(modulename, "archive format is %d\n", fmt);
1633 if (fmt == archUnknown)
1634 AH->format = _discoverArchiveFormat(AH);
1641 InitArchiveFmt_Custom(AH);
1645 InitArchiveFmt_Files(AH);
1649 InitArchiveFmt_Null(AH);
1653 InitArchiveFmt_Tar(AH);
1657 die_horribly(AH, modulename, "unrecognized file format \"%d\"\n", fmt);
1660 /* sql error handling */
1661 AH->public.exit_on_error = true;
1662 AH->public.n_errors = 0;
1669 WriteDataChunks(ArchiveHandle *AH)
1671 TocEntry *te = AH->toc->next;
1672 StartDataPtr startPtr;
1675 while (te != AH->toc)
1677 if (te->dataDumper != NULL)
1680 /* printf("Writing data for %d (%x)\n", te->id, te); */
1682 if (strcmp(te->desc, "BLOBS") == 0)
1684 startPtr = AH->StartBlobsPtr;
1685 endPtr = AH->EndBlobsPtr;
1689 startPtr = AH->StartDataPtr;
1690 endPtr = AH->EndDataPtr;
1693 if (startPtr != NULL)
1694 (*startPtr) (AH, te);
1697 * printf("Dumper arg for %d is %x\n", te->id, te->dataDumperArg);
1701 * The user-provided DataDumper routine needs to call
1704 (*te->dataDumper) ((Archive *) AH, te->dataDumperArg);
1715 WriteToc(ArchiveHandle *AH)
1721 /* printf("%d TOC Entries to save\n", AH->tocCount); */
1723 WriteInt(AH, AH->tocCount);
1725 for (te = AH->toc->next; te != AH->toc; te = te->next)
1727 WriteInt(AH, te->dumpId);
1728 WriteInt(AH, te->dataDumper ? 1 : 0);
1730 /* OID is recorded as a string for historical reasons */
1731 sprintf(workbuf, "%u", te->catalogId.tableoid);
1732 WriteStr(AH, workbuf);
1733 sprintf(workbuf, "%u", te->catalogId.oid);
1734 WriteStr(AH, workbuf);
1736 WriteStr(AH, te->tag);
1737 WriteStr(AH, te->desc);
1738 WriteStr(AH, te->defn);
1739 WriteStr(AH, te->dropStmt);
1740 WriteStr(AH, te->copyStmt);
1741 WriteStr(AH, te->namespace);
1742 WriteStr(AH, te->tablespace);
1743 WriteStr(AH, te->owner);
1744 WriteStr(AH, te->withOids ? "true" : "false");
1746 /* Dump list of dependencies */
1747 for (i = 0; i < te->nDeps; i++)
1749 sprintf(workbuf, "%d", te->dependencies[i]);
1750 WriteStr(AH, workbuf);
1752 WriteStr(AH, NULL); /* Terminate List */
1754 if (AH->WriteExtraTocPtr)
1755 (*AH->WriteExtraTocPtr) (AH, te);
1760 ReadToc(ArchiveHandle *AH)
1768 TocEntry *te = AH->toc->next;
1770 AH->tocCount = ReadInt(AH);
1773 for (i = 0; i < AH->tocCount; i++)
1775 te = (TocEntry *) calloc(1, sizeof(TocEntry));
1776 te->dumpId = ReadInt(AH);
1778 if (te->dumpId > AH->maxDumpId)
1779 AH->maxDumpId = te->dumpId;
1782 if (te->dumpId <= 0)
1783 die_horribly(AH, modulename,
1784 "entry ID %d out of range -- perhaps a corrupt TOC\n",
1787 te->hadDumper = ReadInt(AH);
1789 if (AH->version >= K_VERS_1_8)
1792 sscanf(tmp, "%u", &te->catalogId.tableoid);
1796 te->catalogId.tableoid = InvalidOid;
1798 sscanf(tmp, "%u", &te->catalogId.oid);
1801 te->tag = ReadStr(AH);
1802 te->desc = ReadStr(AH);
1803 te->defn = ReadStr(AH);
1804 te->dropStmt = ReadStr(AH);
1806 if (AH->version >= K_VERS_1_3)
1807 te->copyStmt = ReadStr(AH);
1809 if (AH->version >= K_VERS_1_6)
1810 te->namespace = ReadStr(AH);
1812 if (AH->version >= K_VERS_1_10)
1813 te->tablespace = ReadStr(AH);
1815 te->owner = ReadStr(AH);
1816 if (AH->version >= K_VERS_1_9)
1818 if (strcmp(ReadStr(AH), "true") == 0)
1819 te->withOids = true;
1821 te->withOids = false;
1824 te->withOids = true;
1826 /* Read TOC entry dependencies */
1827 if (AH->version >= K_VERS_1_5)
1830 deps = (DumpId *) malloc(sizeof(DumpId) * depSize);
1836 break; /* end of list */
1837 if (depIdx >= depSize)
1840 deps = (DumpId *) realloc(deps, sizeof(DumpId) * depSize);
1842 sscanf(tmp, "%d", &deps[depIdx]);
1847 if (depIdx > 0) /* We have a non-null entry */
1849 deps = (DumpId *) realloc(deps, sizeof(DumpId) * depIdx);
1850 te->dependencies = deps;
1856 te->dependencies = NULL;
1862 te->dependencies = NULL;
1866 if (AH->ReadExtraTocPtr)
1867 (*AH->ReadExtraTocPtr) (AH, te);
1869 ahlog(AH, 3, "read TOC entry %d (ID %d) for %s %s\n",
1870 i, te->dumpId, te->desc, te->tag);
1872 te->prev = AH->toc->prev;
1873 AH->toc->prev->next = te;
1880 _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
1882 teReqs res = REQ_ALL;
1884 /* ENCODING objects are dumped specially, so always reject here */
1885 if (strcmp(te->desc, "ENCODING") == 0)
1888 /* If it's an ACL, maybe ignore it */
1889 if ((!include_acls || ropt->aclsSkip) && strcmp(te->desc, "ACL") == 0)
1892 if (!ropt->create && strcmp(te->desc, "DATABASE") == 0)
1895 /* Check if tablename only is wanted */
1898 if (ropt->schemaNames)
1900 /* If no namespace is specified, it means all. */
1903 if (strcmp(ropt->schemaNames, te->namespace) != 0)
1906 if (strcmp(te->desc, "TABLE") == 0 ||
1907 strcmp(te->desc, "TABLE DATA") == 0)
1909 if (!ropt->selTable)
1911 if (ropt->tableNames && strcmp(ropt->tableNames, te->tag) != 0)
1914 else if (strcmp(te->desc, "INDEX") == 0)
1916 if (!ropt->selIndex)
1918 if (ropt->indexNames && strcmp(ropt->indexNames, te->tag) != 0)
1921 else if (strcmp(te->desc, "FUNCTION") == 0)
1923 if (!ropt->selFunction)
1925 if (ropt->functionNames && strcmp(ropt->functionNames, te->tag) != 0)
1928 else if (strcmp(te->desc, "TRIGGER") == 0)
1930 if (!ropt->selTrigger)
1932 if (ropt->triggerNames && strcmp(ropt->triggerNames, te->tag) != 0)
1940 * Check if we had a dataDumper. Indicates if the entry is schema or data
1945 * Special Case: If 'SEQUENCE SET' then it is considered a data entry
1947 if (strcmp(te->desc, "SEQUENCE SET") == 0)
1948 res = res & REQ_DATA;
1950 res = res & ~REQ_DATA;
1954 * Special case: <Init> type with <Max OID> tag; this is obsolete and we
1957 if ((strcmp(te->desc, "<Init>") == 0) && (strcmp(te->tag, "Max OID") == 0))
1960 /* Mask it if we only want schema */
1961 if (ropt->schemaOnly)
1962 res = res & REQ_SCHEMA;
1964 /* Mask it we only want data */
1966 res = res & REQ_DATA;
1968 /* Mask it if we don't have a schema contribution */
1969 if (!te->defn || strlen(te->defn) == 0)
1970 res = res & ~REQ_SCHEMA;
1972 /* Finally, if we used a list, limit based on that as well */
1973 if (ropt->limitToList && !ropt->idWanted[te->dumpId - 1])
1980 * Issue SET commands for parameters that we want to have set the same way
1981 * at all times during execution of a restore script.
1984 _doSetFixedOutputState(ArchiveHandle *AH)
1988 /* If we have an encoding setting, emit that */
1990 while (te != AH->toc)
1992 if (strcmp(te->desc, "ENCODING") == 0)
1994 ahprintf(AH, "%s", te->defn);
2000 /* Make sure function checking is disabled */
2001 ahprintf(AH, "SET check_function_bodies = false;\n");
2003 /* Avoid annoying notices etc */
2004 ahprintf(AH, "SET client_min_messages = warning;\n");
2010 * Issue a SET SESSION AUTHORIZATION command. Caller is responsible
2011 * for updating state if appropriate. If user is NULL or an empty string,
2012 * the specification DEFAULT will be used.
2015 _doSetSessionAuth(ArchiveHandle *AH, const char *user)
2017 PQExpBuffer cmd = createPQExpBuffer();
2019 appendPQExpBuffer(cmd, "SET SESSION AUTHORIZATION ");
2022 * SQL requires a string literal here. Might as well be correct.
2025 appendStringLiteral(cmd, user, false);
2027 appendPQExpBuffer(cmd, "DEFAULT");
2028 appendPQExpBuffer(cmd, ";");
2030 if (RestoringToDB(AH))
2034 res = PQexec(AH->connection, cmd->data);
2036 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2037 /* NOT warn_or_die_horribly... use -O instead to skip this. */
2038 die_horribly(AH, modulename, "could not set session user to \"%s\": %s",
2039 user, PQerrorMessage(AH->connection));
2044 ahprintf(AH, "%s\n\n", cmd->data);
2046 destroyPQExpBuffer(cmd);
2051 * Issue a SET default_with_oids command. Caller is responsible
2052 * for updating state if appropriate.
2055 _doSetWithOids(ArchiveHandle *AH, const bool withOids)
2057 PQExpBuffer cmd = createPQExpBuffer();
2059 appendPQExpBuffer(cmd, "SET default_with_oids = %s;", withOids ?
2062 if (RestoringToDB(AH))
2066 res = PQexec(AH->connection, cmd->data);
2068 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2069 warn_or_die_horribly(AH, modulename,
2070 "could not set default_with_oids: %s",
2071 PQerrorMessage(AH->connection));
2076 ahprintf(AH, "%s\n\n", cmd->data);
2078 destroyPQExpBuffer(cmd);
2083 * Issue the commands to connect to the specified database.
2085 * If we're currently restoring right into a database, this will
2086 * actually establish a connection. Otherwise it puts a \connect into
2087 * the script output.
2089 * NULL dbname implies reconnecting to the current DB (pretty useless).
2092 _reconnectToDB(ArchiveHandle *AH, const char *dbname)
2094 if (RestoringToDB(AH))
2095 ReconnectToServer(AH, dbname, NULL);
2098 PQExpBuffer qry = createPQExpBuffer();
2100 appendPQExpBuffer(qry, "\\connect %s\n\n",
2101 dbname ? fmtId(dbname) : "-");
2102 ahprintf(AH, "%s", qry->data);
2103 destroyPQExpBuffer(qry);
2107 * NOTE: currUser keeps track of what the imaginary session user in our
2108 * script is. It's now effectively reset to the original userID.
2113 AH->currUser = strdup("");
2115 /* don't assume we still know the output schema */
2117 free(AH->currSchema);
2118 AH->currSchema = strdup("");
2119 AH->currWithOids = -1;
2121 /* re-establish fixed state */
2122 _doSetFixedOutputState(AH);
2126 * Become the specified user, and update state to avoid redundant commands
2128 * NULL or empty argument is taken to mean restoring the session default
2131 _becomeUser(ArchiveHandle *AH, const char *user)
2134 user = ""; /* avoid null pointers */
2136 if (AH->currUser && strcmp(AH->currUser, user) == 0)
2137 return; /* no need to do anything */
2139 _doSetSessionAuth(AH, user);
2142 * NOTE: currUser keeps track of what the imaginary session user in our
2148 AH->currUser = strdup(user);
2152 * Become the owner of the the given TOC entry object. If
2153 * changes in ownership are not allowed, this doesn't do anything.
2156 _becomeOwner(ArchiveHandle *AH, TocEntry *te)
2158 if (AH->ropt && (AH->ropt->noOwner || !AH->ropt->use_setsessauth))
2161 _becomeUser(AH, te->owner);
2166 * Set the proper default_with_oids value for the table.
2169 _setWithOids(ArchiveHandle *AH, TocEntry *te)
2171 if (AH->currWithOids != te->withOids)
2173 _doSetWithOids(AH, te->withOids);
2174 AH->currWithOids = te->withOids;
2180 * Issue the commands to select the specified schema as the current schema
2181 * in the target database.
2184 _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
2188 if (!schemaName || *schemaName == '\0' ||
2189 strcmp(AH->currSchema, schemaName) == 0)
2190 return; /* no need to do anything */
2192 qry = createPQExpBuffer();
2194 appendPQExpBuffer(qry, "SET search_path = %s",
2196 if (strcmp(schemaName, "pg_catalog") != 0)
2197 appendPQExpBuffer(qry, ", pg_catalog");
2199 if (RestoringToDB(AH))
2203 res = PQexec(AH->connection, qry->data);
2205 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2206 warn_or_die_horribly(AH, modulename,
2207 "could not set search_path to \"%s\": %s",
2208 schemaName, PQerrorMessage(AH->connection));
2213 ahprintf(AH, "%s;\n\n", qry->data);
2216 free(AH->currSchema);
2217 AH->currSchema = strdup(schemaName);
2219 destroyPQExpBuffer(qry);
2223 * Issue the commands to select the specified tablespace as the current one
2224 * in the target database.
2227 _selectTablespace(ArchiveHandle *AH, const char *tablespace)
2233 have = AH->currTablespace;
2236 /* no need to do anything for non-tablespace object */
2240 if (have && strcmp(want, have) == 0)
2241 return; /* no need to do anything */
2243 qry = createPQExpBuffer();
2245 if (strcmp(want, "") == 0)
2247 /* We want the tablespace to be the database's default */
2248 appendPQExpBuffer(qry, "SET default_tablespace = ''");
2252 /* We want an explicit tablespace */
2253 appendPQExpBuffer(qry, "SET default_tablespace = %s", fmtId(want));
2256 if (RestoringToDB(AH))
2260 res = PQexec(AH->connection, qry->data);
2262 if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
2263 warn_or_die_horribly(AH, modulename,
2264 "could not set default_tablespace to %s: %s",
2265 fmtId(want), PQerrorMessage(AH->connection));
2270 ahprintf(AH, "%s;\n\n", qry->data);
2272 if (AH->currTablespace)
2273 free(AH->currTablespace);
2274 AH->currTablespace = strdup(want);
2276 destroyPQExpBuffer(qry);
2280 * Extract an object description for a TOC entry, and append it to buf.
2282 * This is not quite as general as it may seem, since it really only
2283 * handles constructing the right thing to put into ALTER ... OWNER TO.
2285 * The whole thing is pretty grotty, but we are kind of stuck since the
2286 * information used is all that's available in older dump files.
2289 _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
2291 const char *type = te->desc;
2293 /* Use ALTER TABLE for views and sequences */
2294 if (strcmp(type, "VIEW") == 0 || strcmp(type, "SEQUENCE") == 0)
2297 /* objects named by a schema and name */
2298 if (strcmp(type, "CONVERSION") == 0 ||
2299 strcmp(type, "DOMAIN") == 0 ||
2300 strcmp(type, "TABLE") == 0 ||
2301 strcmp(type, "TYPE") == 0)
2303 appendPQExpBuffer(buf, "%s ", type);
2304 if (te->namespace && te->namespace[0]) /* is null pre-7.3 */
2305 appendPQExpBuffer(buf, "%s.", fmtId(te->namespace));
2308 * Pre-7.3 pg_dump would sometimes (not always) put a fmtId'd name
2309 * into te->tag for an index. This check is heuristic, so make its
2310 * scope as narrow as possible.
2312 if (AH->version < K_VERS_1_7 &&
2313 te->tag[0] == '"' &&
2314 te->tag[strlen(te->tag) - 1] == '"' &&
2315 strcmp(type, "INDEX") == 0)
2316 appendPQExpBuffer(buf, "%s", te->tag);
2318 appendPQExpBuffer(buf, "%s", fmtId(te->tag));
2322 /* objects named by just a name */
2323 if (strcmp(type, "DATABASE") == 0 ||
2324 strcmp(type, "SCHEMA") == 0)
2326 appendPQExpBuffer(buf, "%s %s", type, fmtId(te->tag));
2331 * These object types require additional decoration. Fortunately, the
2332 * information needed is exactly what's in the DROP command.
2334 if (strcmp(type, "AGGREGATE") == 0 ||
2335 strcmp(type, "FUNCTION") == 0 ||
2336 strcmp(type, "OPERATOR") == 0 ||
2337 strcmp(type, "OPERATOR CLASS") == 0)
2339 /* Chop "DROP " off the front and make a modifiable copy */
2340 char *first = strdup(te->dropStmt + 5);
2343 /* point to last character in string */
2344 last = first + strlen(first) - 1;
2346 /* Strip off any ';' or '\n' at the end */
2347 while (last >= first && (*last == '\n' || *last == ';'))
2351 appendPQExpBufferStr(buf, first);
2357 write_msg(modulename, "WARNING: don't know how to set owner for object type %s\n",
2362 _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData, bool acl_pass)
2364 /* ACLs are dumped only during acl pass */
2367 if (strcmp(te->desc, "ACL") != 0)
2372 if (strcmp(te->desc, "ACL") == 0)
2377 * Avoid dumping the public schema, as it will already be created ...
2378 * unless we are using --clean mode, in which case it's been deleted and
2379 * we'd better recreate it.
2381 if (!ropt->dropSchema &&
2382 strcmp(te->desc, "SCHEMA") == 0 && strcmp(te->tag, "public") == 0)
2385 /* Select owner, schema, and tablespace as necessary */
2386 _becomeOwner(AH, te);
2387 _selectOutputSchema(AH, te->namespace);
2388 _selectTablespace(AH, te->tablespace);
2390 /* Set up OID mode too */
2391 if (strcmp(te->desc, "TABLE") == 0)
2392 _setWithOids(AH, te);
2394 /* Emit header comment for item */
2395 if (!AH->noTocComments)
2404 ahprintf(AH, "--\n");
2405 if (AH->public.verbose)
2407 ahprintf(AH, "-- TOC entry %d (class %u OID %u)\n",
2408 te->dumpId, te->catalogId.tableoid, te->catalogId.oid);
2413 ahprintf(AH, "-- Dependencies:");
2414 for (i = 0; i < te->nDeps; i++)
2415 ahprintf(AH, " %d", te->dependencies[i]);
2419 ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
2420 pfx, te->tag, te->desc,
2421 te->namespace ? te->namespace : "-",
2422 ropt->noOwner ? "-" : te->owner);
2424 ahprintf(AH, "; Tablespace: %s", te->tablespace);
2427 if (AH->PrintExtraTocPtr !=NULL)
2428 (*AH->PrintExtraTocPtr) (AH, te);
2429 ahprintf(AH, "--\n\n");
2433 * Actually print the definition.
2435 * Really crude hack for suppressing AUTHORIZATION clause that old pg_dump
2436 * versions put into CREATE SCHEMA. We have to do this when --no-owner
2437 * mode is selected. This is ugly, but I see no other good way ...
2439 if (ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0)
2441 ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
2445 if (strlen(te->defn) > 0)
2446 ahprintf(AH, "%s\n\n", te->defn);
2450 * If we aren't using SET SESSION AUTH to determine ownership, we must
2451 * instead issue an ALTER OWNER command. We assume that anything without
2452 * a DROP command is not a separately ownable object. All the categories
2453 * with DROP commands must appear in one list or the other.
2455 if (!ropt->noOwner && !ropt->use_setsessauth &&
2456 strlen(te->owner) > 0 && strlen(te->dropStmt) > 0)
2458 if (strcmp(te->desc, "AGGREGATE") == 0 ||
2459 strcmp(te->desc, "CONVERSION") == 0 ||
2460 strcmp(te->desc, "DATABASE") == 0 ||
2461 strcmp(te->desc, "DOMAIN") == 0 ||
2462 strcmp(te->desc, "FUNCTION") == 0 ||
2463 strcmp(te->desc, "OPERATOR") == 0 ||
2464 strcmp(te->desc, "OPERATOR CLASS") == 0 ||
2465 strcmp(te->desc, "SCHEMA") == 0 ||
2466 strcmp(te->desc, "TABLE") == 0 ||
2467 strcmp(te->desc, "TYPE") == 0 ||
2468 strcmp(te->desc, "VIEW") == 0 ||
2469 strcmp(te->desc, "SEQUENCE") == 0)
2471 PQExpBuffer temp = createPQExpBuffer();
2473 appendPQExpBuffer(temp, "ALTER ");
2474 _getObjectDescription(temp, te, AH);
2475 appendPQExpBuffer(temp, " OWNER TO %s;", fmtId(te->owner));
2476 ahprintf(AH, "%s\n\n", temp->data);
2477 destroyPQExpBuffer(temp);
2479 else if (strcmp(te->desc, "CAST") == 0 ||
2480 strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
2481 strcmp(te->desc, "CONSTRAINT") == 0 ||
2482 strcmp(te->desc, "DEFAULT") == 0 ||
2483 strcmp(te->desc, "FK CONSTRAINT") == 0 ||
2484 strcmp(te->desc, "INDEX") == 0 ||
2485 strcmp(te->desc, "PROCEDURAL LANGUAGE") == 0 ||
2486 strcmp(te->desc, "RULE") == 0 ||
2487 strcmp(te->desc, "TRIGGER") == 0)
2489 /* these object types don't have separate owners */
2493 write_msg(modulename, "WARNING: don't know how to set owner for object type %s\n",
2499 * If it's an ACL entry, it might contain SET SESSION AUTHORIZATION
2500 * commands, so we can no longer assume we know the current auth setting.
2502 if (strncmp(te->desc, "ACL", 3) == 0)
2506 AH->currUser = NULL;
2511 WriteHead(ArchiveHandle *AH)
2515 (*AH->WriteBufPtr) (AH, "PGDMP", 5); /* Magic code */
2516 (*AH->WriteBytePtr) (AH, AH->vmaj);
2517 (*AH->WriteBytePtr) (AH, AH->vmin);
2518 (*AH->WriteBytePtr) (AH, AH->vrev);
2519 (*AH->WriteBytePtr) (AH, AH->intSize);
2520 (*AH->WriteBytePtr) (AH, AH->offSize);
2521 (*AH->WriteBytePtr) (AH, AH->format);
2524 if (AH->compression != 0)
2525 write_msg(modulename, "WARNING: requested compression not available in this "
2526 "installation -- archive will be uncompressed\n");
2528 AH->compression = 0;
2531 WriteInt(AH, AH->compression);
2533 crtm = *localtime(&AH->createDate);
2534 WriteInt(AH, crtm.tm_sec);
2535 WriteInt(AH, crtm.tm_min);
2536 WriteInt(AH, crtm.tm_hour);
2537 WriteInt(AH, crtm.tm_mday);
2538 WriteInt(AH, crtm.tm_mon);
2539 WriteInt(AH, crtm.tm_year);
2540 WriteInt(AH, crtm.tm_isdst);
2541 WriteStr(AH, PQdb(AH->connection));
2542 WriteStr(AH, AH->public.remoteVersionStr);
2543 WriteStr(AH, PG_VERSION);
2547 ReadHead(ArchiveHandle *AH)
2553 /* If we haven't already read the header... */
2554 if (!AH->readHeader)
2557 (*AH->ReadBufPtr) (AH, tmpMag, 5);
2559 if (strncmp(tmpMag, "PGDMP", 5) != 0)
2560 die_horribly(AH, modulename, "did not find magic string in file header\n");
2562 AH->vmaj = (*AH->ReadBytePtr) (AH);
2563 AH->vmin = (*AH->ReadBytePtr) (AH);
2565 if (AH->vmaj > 1 || ((AH->vmaj == 1) && (AH->vmin > 0))) /* Version > 1.0 */
2566 AH->vrev = (*AH->ReadBytePtr) (AH);
2570 AH->version = ((AH->vmaj * 256 + AH->vmin) * 256 + AH->vrev) * 256 + 0;
2573 if (AH->version < K_VERS_1_0 || AH->version > K_VERS_MAX)
2574 die_horribly(AH, modulename, "unsupported version (%d.%d) in file header\n",
2575 AH->vmaj, AH->vmin);
2577 AH->intSize = (*AH->ReadBytePtr) (AH);
2578 if (AH->intSize > 32)
2579 die_horribly(AH, modulename, "sanity check on integer size (%lu) failed\n",
2580 (unsigned long) AH->intSize);
2582 if (AH->intSize > sizeof(int))
2583 write_msg(modulename, "WARNING: archive was made on a machine with larger integers, some operations may fail\n");
2585 if (AH->version >= K_VERS_1_7)
2586 AH->offSize = (*AH->ReadBytePtr) (AH);
2588 AH->offSize = AH->intSize;
2590 fmt = (*AH->ReadBytePtr) (AH);
2592 if (AH->format != fmt)
2593 die_horribly(AH, modulename, "expected format (%d) differs from format found in file (%d)\n",
2597 if (AH->version >= K_VERS_1_2)
2599 if (AH->version < K_VERS_1_4)
2600 AH->compression = (*AH->ReadBytePtr) (AH);
2602 AH->compression = ReadInt(AH);
2605 AH->compression = Z_DEFAULT_COMPRESSION;
2608 if (AH->compression != 0)
2609 write_msg(modulename, "WARNING: archive is compressed, but this installation does not support compression -- no data will be available\n");
2612 if (AH->version >= K_VERS_1_4)
2614 crtm.tm_sec = ReadInt(AH);
2615 crtm.tm_min = ReadInt(AH);
2616 crtm.tm_hour = ReadInt(AH);
2617 crtm.tm_mday = ReadInt(AH);
2618 crtm.tm_mon = ReadInt(AH);
2619 crtm.tm_year = ReadInt(AH);
2620 crtm.tm_isdst = ReadInt(AH);
2622 AH->archdbname = ReadStr(AH);
2624 AH->createDate = mktime(&crtm);
2626 if (AH->createDate == (time_t) -1)
2627 write_msg(modulename, "WARNING: invalid creation date in header\n");
2630 if (AH->version >= K_VERS_1_10)
2632 AH->archiveRemoteVersion = ReadStr(AH);
2633 AH->archiveDumpVersion = ReadStr(AH);
2641 * check to see if fseek can be performed.
2648 if (fseeko(fp, 0, SEEK_CUR) != 0)
2650 else if (sizeof(off_t) > sizeof(long))
2653 * At this point, off_t is too large for long, so we return based on
2654 * whether an off_t version of fseek is available.
2670 dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim)
2674 if (strftime(buf, 256, "%Y-%m-%d %H:%M:%S %Z", localtime(&tim)) != 0)
2675 ahprintf(AH, "-- %s %s\n\n", msg, buf);