diff options
-rw-r--r-- | doc/src/sgml/ref/pg_dump.sgml | 33 | ||||
-rw-r--r-- | doc/src/sgml/ref/pg_restore.sgml | 35 | ||||
-rw-r--r-- | src/bin/pg_dump/dumputils.c | 61 | ||||
-rw-r--r-- | src/bin/pg_dump/dumputils.h | 14 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_backup.h | 15 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_backup_archiver.c | 162 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_backup_archiver.h | 14 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_backup_tar.c | 10 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 93 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_restore.c | 39 |
10 files changed, 238 insertions, 238 deletions
diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml index 12ddd259662..450383083d7 100644 --- a/doc/src/sgml/ref/pg_dump.sgml +++ b/doc/src/sgml/ref/pg_dump.sgml @@ -113,10 +113,12 @@ PostgreSQL documentation <listitem> <para> Dump only the data, not the schema (data definitions). + Table data, large objects, and sequence values are dumped. </para> <para> - This option is equivalent to specifying <option>--section=data</>. + This option is similar to, but for historical reasons not identical + to, specifying <option>--section=data</>. </para> </listitem> </varlistentry> @@ -403,12 +405,18 @@ PostgreSQL documentation Dump only the object definitions (schema), not data. </para> <para> - To exclude table data for only a subset of tables in the database, - see <option>--exclude-table-data</>. + This option is the inverse of <option>--data-only</>. + It is similar to, but for historical reasons not identical to, + specifying + <option>--section=pre-data --section=post-data</>. </para> <para> - This option is equivalent to specifying - <option>--section=pre-data --section=post-data</>. + (Do not confuse this with the <option>--schema</> option, which + uses the word <quote>schema</> in a different meaning.) + </para> + <para> + To exclude table data for only a subset of tables in the database, + see <option>--exclude-table-data</>. </para> </listitem> </varlistentry> @@ -722,14 +730,17 @@ PostgreSQL documentation <term><option>--section=<replaceable class="parameter">sectionname</replaceable></option></term> <listitem> <para> - Only dump the named section. The name can be one of <option>pre-data</>, <option>data</> - and <option>post-data</>. - This option can be specified more than once. The default is to dump all sections. + Only dump the named section. The section name can be + <option>pre-data</>, <option>data</>, or <option>post-data</>. + This option can be specified more than once to select multiple + sections. The default is to dump all sections. </para> <para> - Post-data items consist of definitions of indexes, triggers, rules - and constraints other than validated check constraints. - Pre-data items consist of all other data definition items. + The data section contains actual table data as well as large-object + definitions. + Post-data items consist of definitions of indexes, triggers, rules + and constraints other than validated check constraints. + Pre-data items consist of all other data definition items. </para> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/pg_restore.sgml b/doc/src/sgml/ref/pg_restore.sgml index 513b946e571..bc3d2b7e90f 100644 --- a/doc/src/sgml/ref/pg_restore.sgml +++ b/doc/src/sgml/ref/pg_restore.sgml @@ -92,9 +92,13 @@ <listitem> <para> Restore only the data, not the schema (data definitions). + Table data, large objects, and sequence values are restored, + if present in the archive. </para> + <para> - This option is equivalent to specifying <option>--section=data</>. + This option is similar to, but for historical reasons not identical + to, specifying <option>--section=data</>. </para> </listitem> </varlistentry> @@ -357,15 +361,19 @@ <term><option>--schema-only</option></term> <listitem> <para> - Restore only the schema (data definitions), not the data (table - contents). Current sequence values will not be restored, either. - (Do not confuse this with the <option>--schema</> option, which - uses the word <quote>schema</> in a different meaning.) + Restore only the schema (data definitions), not data, + to the extent that schema entries are present in the archive. </para> <para> - This option is equivalent to specifying + This option is the inverse of <option>--data-only</>. + It is similar to, but for historical reasons not identical to, + specifying <option>--section=pre-data --section=post-data</>. </para> + <para> + (Do not confuse this with the <option>--schema</> option, which + uses the word <quote>schema</> in a different meaning.) + </para> </listitem> </varlistentry> @@ -515,14 +523,17 @@ <term><option>--section=<replaceable class="parameter">sectionname</replaceable></option></term> <listitem> <para> - Only restore the named section. The name can be one of <option>pre-data</>, <option>data</> - and <option>post-data</>. - This option can be specified more than once. The default is to restore all sections. + Only restore the named section. The section name can be + <option>pre-data</>, <option>data</>, or <option>post-data</>. + This option can be specified more than once to select multiple + sections. The default is to restore all sections. </para> <para> - Post-data items consist of definitions of indexes, triggers, rules - and constraints other than validated check constraints. - Pre-data items consist of all other data definition items. + The data section contains actual table data as well as large-object + definitions. + Post-data items consist of definitions of indexes, triggers, rules + and constraints other than validated check constraints. + Pre-data items consist of all other data definition items. </para> </listitem> </varlistentry> diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index b662ad107e5..623c250eb89 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -17,7 +17,6 @@ #include <ctype.h> #include "dumputils.h" -#include "pg_backup.h" #include "parser/keywords.h" @@ -1231,6 +1230,37 @@ emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer, /* + * Parse a --section=foo command line argument. + * + * Set or update the bitmask in *dumpSections according to arg. + * dumpSections is initialised as DUMP_UNSECTIONED by pg_dump and + * pg_restore so they can know if this has even been called. + */ +void +set_dump_section(const char *arg, int *dumpSections) +{ + /* if this is the first call, clear all the bits */ + if (*dumpSections == DUMP_UNSECTIONED) + *dumpSections = 0; + + if (strcmp(arg,"pre-data") == 0) + *dumpSections |= DUMP_PRE_DATA; + else if (strcmp(arg,"data") == 0) + *dumpSections |= DUMP_DATA; + else if (strcmp(arg,"post-data") == 0) + *dumpSections |= DUMP_POST_DATA; + else + { + fprintf(stderr, _("%s: unknown section name \"%s\")\n"), + progname, arg); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + progname); + exit_nicely(1); + } +} + + +/* * Write a printf-style message to stderr. * * The program name is prepended, if "progname" has been set. @@ -1279,35 +1309,6 @@ exit_horribly(const char *modulename, const char *fmt,...) exit_nicely(1); } -/* - * Set the bitmask in dumpSections according to the first argument. - * dumpSections is initialised as DUMP_UNSECTIONED by pg_dump and - * pg_restore so they can know if this has even been called. - */ - -void -set_section (const char *arg, int *dumpSections) -{ - /* if this is the first, clear all the bits */ - if (*dumpSections == DUMP_UNSECTIONED) - *dumpSections = 0; - - if (strcmp(arg,"pre-data") == 0) - *dumpSections |= DUMP_PRE_DATA; - else if (strcmp(arg,"data") == 0) - *dumpSections |= DUMP_DATA; - else if (strcmp(arg,"post-data") == 0) - *dumpSections |= DUMP_POST_DATA; - else - { - fprintf(stderr, _("%s: unknown section name \"%s\")\n"), - progname, arg); - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), - progname); - exit_nicely(1); - } -} - /* Register a callback to be run when exit_nicely is invoked. */ void on_exit_nicely(on_exit_nicely_callback function, void *arg) diff --git a/src/bin/pg_dump/dumputils.h b/src/bin/pg_dump/dumputils.h index 82cf940892c..3d1ed9570ab 100644 --- a/src/bin/pg_dump/dumputils.h +++ b/src/bin/pg_dump/dumputils.h @@ -19,6 +19,16 @@ #include "libpq-fe.h" #include "pqexpbuffer.h" +typedef enum /* bits returned by set_dump_section */ +{ + DUMP_PRE_DATA = 0x01, + DUMP_DATA = 0x02, + DUMP_POST_DATA = 0x04, + DUMP_UNSECTIONED = 0xff +} DumpSections; + +typedef void (*on_exit_nicely_callback) (int code, void *arg); + extern int quote_all_identifiers; extern const char *progname; @@ -52,15 +62,13 @@ extern void buildShSecLabelQuery(PGconn *conn, const char *catalog_name, uint32 objectId, PQExpBuffer sql); extern void emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer, const char *target, const char *objname); +extern void set_dump_section(const char *arg, int *dumpSections); extern void write_msg(const char *modulename, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3))); extern void vwrite_msg(const char *modulename, const char *fmt, va_list ap) __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0))); extern void exit_horribly(const char *modulename, const char *fmt,...) __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3), noreturn)); -extern void set_section (const char *arg, int *dumpSections); - -typedef void (*on_exit_nicely_callback) (int code, void *arg); extern void on_exit_nicely(on_exit_nicely_callback function, void *arg); extern void exit_nicely(int code) __attribute__((noreturn)); diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index 61c68636669..bf7cc1c1ac8 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -68,14 +68,6 @@ typedef enum _teSection SECTION_POST_DATA /* stuff to be processed after data */ } teSection; -typedef enum -{ - DUMP_PRE_DATA = 0x01, - DUMP_DATA = 0x02, - DUMP_POST_DATA = 0x04, - DUMP_UNSECTIONED = 0xff -} DumpSections; - /* * We may want to have some more user-readable data, but in the mean * time this gives us some abstraction and type checking. @@ -114,9 +106,9 @@ typedef struct _restoreOptions int no_security_labels; /* Skip security label entries */ char *superuser; /* Username to use as superuser */ char *use_role; /* Issue SET ROLE to this */ - int dataOnly; int dropSchema; const char *filename; + int dataOnly; int schemaOnly; int dumpSections; int verbose; @@ -187,7 +179,9 @@ extern int EndBlob(Archive *AH, Oid oid); extern void CloseArchive(Archive *AH); -extern void RestoreArchive(Archive *AH, RestoreOptions *ropt); +extern void SetArchiveRestoreOptions(Archive *AH, RestoreOptions *ropt); + +extern void RestoreArchive(Archive *AH); /* Open an existing archive */ extern Archive *OpenArchive(const char *FileSpec, const ArchiveFormat fmt); @@ -203,7 +197,6 @@ extern RestoreOptions *NewRestoreOptions(void); /* Rearrange and filter TOC entries */ extern void SortTocFromFile(Archive *AHX, RestoreOptions *ropt); -extern void InitDummyWantedList(Archive *AHX, RestoreOptions *ropt); /* Convenience functions used only when writing DATA */ extern int archputs(const char *s, Archive *AH); diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 7aaba36385c..c049becf126 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -131,7 +131,7 @@ static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName); static void _selectTablespace(ArchiveHandle *AH, const char *tablespace); static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te); static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te); -static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls); +static teReqs _tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt); static bool _tocEntryIsACL(TocEntry *te); static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); @@ -234,15 +234,35 @@ CloseArchive(Archive *AHX) /* Public */ void -RestoreArchive(Archive *AHX, RestoreOptions *ropt) +SetArchiveRestoreOptions(Archive *AHX, RestoreOptions *ropt) { ArchiveHandle *AH = (ArchiveHandle *) AHX; + TocEntry *te; + teSection curSection; + + /* Save options for later access */ + AH->ropt = ropt; + + /* Decide which TOC entries will be dumped/restored, and mark them */ + curSection = SECTION_PRE_DATA; + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if (te->section != SECTION_NONE) + curSection = te->section; + te->reqs = _tocEntryRequired(te, curSection, ropt); + } +} + +/* Public */ +void +RestoreArchive(Archive *AHX) +{ + ArchiveHandle *AH = (ArchiveHandle *) AHX; + RestoreOptions *ropt = AH->ropt; bool parallel_mode; TocEntry *te; - teReqs reqs; OutputContext sav; - AH->ropt = ropt; AH->stage = STAGE_INITIALIZING; /* @@ -292,8 +312,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt) { for (te = AH->toc->next; te != AH->toc; te = te->next) { - reqs = _tocEntryRequired(te, ropt, false); - if (te->hadDumper && (reqs & REQ_DATA) != 0) + if (te->hadDumper && (te->reqs & REQ_DATA) != 0) exit_horribly(modulename, "cannot restore from compressed archive (compression not supported in this installation)\n"); } } @@ -345,8 +364,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt) for (te = AH->toc->next; te != AH->toc; te = te->next) { - reqs = _tocEntryRequired(te, ropt, true); - if ((reqs & REQ_SCHEMA) != 0) + if ((te->reqs & REQ_SCHEMA) != 0) { /* It's schema, and it's wanted */ impliedDataOnly = 0; break; @@ -403,9 +421,8 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt) { AH->currentTE = te; - reqs = _tocEntryRequired(te, ropt, false /* needn't drop ACLs */ ); /* We want anything that's selected and has a dropStmt */ - if (((reqs & (REQ_SCHEMA | REQ_DATA)) != 0) && te->dropStmt) + if (((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0) && te->dropStmt) { ahlog(AH, 1, "dropping %s %s\n", te->desc, te->tag); /* Select owner and schema as necessary */ @@ -453,11 +470,8 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt) { AH->currentTE = te; - /* Work out what, if anything, we want from this entry */ - reqs = _tocEntryRequired(te, ropt, true); - /* Both schema and data objects might now have ownership/ACLs */ - if ((reqs & (REQ_SCHEMA | REQ_DATA)) != 0) + if ((te->reqs & (REQ_SCHEMA | REQ_DATA)) != 0) { ahlog(AH, 1, "setting owner and privileges for %s %s\n", te->desc, te->tag); @@ -508,7 +522,18 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, AH->currentTE = te; /* Work out what, if anything, we want from this entry */ - reqs = _tocEntryRequired(te, ropt, false); + if (_tocEntryIsACL(te)) + reqs = 0; /* ACLs are never restored here */ + else + reqs = te->reqs; + + /* + * Ignore DATABASE entry unless we should create it. We must check this + * here, not in _tocEntryRequired, because the createDB option should + * not affect emitting a DATABASE entry to an archive file. + */ + if (!ropt->createDB && strcmp(te->desc, "DATABASE") == 0) + reqs = 0; /* Dump any relevant dump warnings to stderr */ if (!ropt->suppressDumpWarnings && strcmp(te->desc, "WARNING") == 0) @@ -588,7 +613,7 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, /* * If we can output the data, then restore it. */ - if (AH->PrintTocDataPtr !=NULL && (reqs & REQ_DATA) != 0) + if (AH->PrintTocDataPtr !=NULL) { _printTocEntry(AH, te, ropt, true, false); @@ -841,8 +866,9 @@ PrintTOCSummary(Archive *AHX, RestoreOptions *ropt) { ArchiveHandle *AH = (ArchiveHandle *) AHX; TocEntry *te; + teSection curSection; OutputContext sav; - char *fmtName; + const char *fmtName; sav = SaveOutput(AH); if (ropt->filename) @@ -880,9 +906,13 @@ PrintTOCSummary(Archive *AHX, RestoreOptions *ropt) /* We should print DATABASE entries whether or not -C was specified */ ropt->createDB = 1; + curSection = SECTION_PRE_DATA; for (te = AH->toc->next; te != AH->toc; te = te->next) { - if (ropt->verbose || _tocEntryRequired(te, ropt, true) != 0) + if (te->section != SECTION_NONE) + curSection = te->section; + if (ropt->verbose || + (_tocEntryRequired(te, curSection, ropt) & (REQ_SCHEMA | REQ_DATA)) != 0) ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId, te->catalogId.tableoid, te->catalogId.oid, te->desc, te->namespace ? te->namespace : "-", @@ -1135,19 +1165,6 @@ SortTocFromFile(Archive *AHX, RestoreOptions *ropt) strerror(errno)); } -/* - * Set up a dummy ID filter that selects all dump IDs - */ -void -InitDummyWantedList(Archive *AHX, RestoreOptions *ropt) -{ - ArchiveHandle *AH = (ArchiveHandle *) AHX; - - /* Allocate space for the 'wanted' array, and init it to 1's */ - ropt->idWanted = (bool *) pg_malloc(sizeof(bool) * AH->maxDumpId); - memset(ropt->idWanted, 1, sizeof(bool) * AH->maxDumpId); -} - /********************** * 'Convenience functions that look like standard IO functions * for writing data when in dump mode. @@ -1591,14 +1608,14 @@ getTocEntryByDumpId(ArchiveHandle *AH, DumpId id) } teReqs -TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt) +TocIDRequired(ArchiveHandle *AH, DumpId id) { TocEntry *te = getTocEntryByDumpId(AH, id); if (!te) return 0; - return _tocEntryRequired(te, ropt, true); + return te->reqs; } size_t @@ -2082,7 +2099,7 @@ WriteDataChunks(ArchiveHandle *AH) for (te = AH->toc->next; te != AH->toc; te = te->next) { - if (te->dataDumper != NULL) + if (te->dataDumper != NULL && (te->reqs & REQ_DATA) != 0) { AH->currToc = te; /* printf("Writing data for %d (%x)\n", te->id, te); */ @@ -2123,14 +2140,26 @@ WriteToc(ArchiveHandle *AH) { TocEntry *te; char workbuf[32]; + int tocCount; int i; - /* printf("%d TOC Entries to save\n", AH->tocCount); */ + /* count entries that will actually be dumped */ + tocCount = 0; + for (te = AH->toc->next; te != AH->toc; te = te->next) + { + if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) != 0) + tocCount++; + } + + /* printf("%d TOC Entries to save\n", tocCount); */ - WriteInt(AH, AH->tocCount); + WriteInt(AH, tocCount); for (te = AH->toc->next; te != AH->toc; te = te->next) { + if ((te->reqs & (REQ_SCHEMA | REQ_DATA | REQ_SPECIAL)) == 0) + continue; + WriteInt(AH, te->dumpId); WriteInt(AH, te->dataDumper ? 1 : 0); @@ -2173,7 +2202,6 @@ ReadToc(ArchiveHandle *AH) int depIdx; int depSize; TocEntry *te; - bool in_post_data = false; AH->tocCount = ReadInt(AH); AH->maxDumpId = 0; @@ -2239,12 +2267,6 @@ ReadToc(ArchiveHandle *AH) te->section = SECTION_PRE_DATA; } - /* will stay true even for SECTION_NONE items */ - if (te->section == SECTION_POST_DATA) - in_post_data = true; - - te->inPostData = in_post_data; - te->defn = ReadStr(AH); te->dropStmt = ReadStr(AH); @@ -2373,38 +2395,43 @@ processStdStringsEntry(ArchiveHandle *AH, TocEntry *te) } static teReqs -_tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls) +_tocEntryRequired(TocEntry *te, teSection curSection, RestoreOptions *ropt) { - teReqs res = REQ_ALL; + teReqs res = REQ_SCHEMA | REQ_DATA; - /* ENCODING and STDSTRINGS items are dumped specially, so always reject */ + /* ENCODING and STDSTRINGS items are treated specially */ if (strcmp(te->desc, "ENCODING") == 0 || strcmp(te->desc, "STDSTRINGS") == 0) - return 0; + return REQ_SPECIAL; /* If it's an ACL, maybe ignore it */ - if ((!include_acls || ropt->aclsSkip) && _tocEntryIsACL(te)) + if (ropt->aclsSkip && _tocEntryIsACL(te)) return 0; /* If it's security labels, maybe ignore it */ if (ropt->no_security_labels && strcmp(te->desc, "SECURITY LABEL") == 0) return 0; - /* Ignore DATABASE entry unless we should create it */ - if (!ropt->createDB && strcmp(te->desc, "DATABASE") == 0) - return 0; - - /* skip (all but) post data section as required */ - /* table data is filtered if necessary lower down */ - if (ropt->dumpSections != DUMP_UNSECTIONED) + /* Ignore it if section is not to be dumped/restored */ + switch (curSection) { - if (!(ropt->dumpSections & DUMP_POST_DATA) && te->inPostData) - return 0; - if (!(ropt->dumpSections & DUMP_PRE_DATA) && ! te->inPostData && strcmp(te->desc, "TABLE DATA") != 0) + case SECTION_PRE_DATA: + if (!(ropt->dumpSections & DUMP_PRE_DATA)) + return 0; + break; + case SECTION_DATA: + if (!(ropt->dumpSections & DUMP_DATA)) + return 0; + break; + case SECTION_POST_DATA: + if (!(ropt->dumpSections & DUMP_POST_DATA)) + return 0; + break; + default: + /* shouldn't get here, really, but ignore it */ return 0; } - /* Check options for selective dump/restore */ if (ropt->schemaNames) { @@ -2486,7 +2513,7 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls) if (ropt->schemaOnly) res = res & REQ_SCHEMA; - /* Mask it we only want data */ + /* Mask it if we only want data */ if (ropt->dataOnly) res = res & REQ_DATA; @@ -3553,11 +3580,9 @@ restore_toc_entries_parallel(ArchiveHandle *AH) { if (next_work_item != NULL) { - teReqs reqs; - - /* If not to be dumped, don't waste time launching a worker */ - reqs = _tocEntryRequired(next_work_item, AH->ropt, false); - if ((reqs & (REQ_SCHEMA | REQ_DATA)) == 0) + /* If not to be restored, don't waste time launching a worker */ + if ((next_work_item->reqs & (REQ_SCHEMA | REQ_DATA)) == 0 || + _tocEntryIsACL(next_work_item)) { ahlog(AH, 1, "skipping item %d %s %s\n", next_work_item->dumpId, @@ -4287,15 +4312,14 @@ mark_create_done(ArchiveHandle *AH, TocEntry *te) static void inhibit_data_for_failed_table(ArchiveHandle *AH, TocEntry *te) { - RestoreOptions *ropt = AH->ropt; - ahlog(AH, 1, "table \"%s\" could not be created, will not restore its data\n", te->tag); if (AH->tableDataId[te->dumpId] != 0) { - /* mark it unwanted; we assume idWanted array already exists */ - ropt->idWanted[AH->tableDataId[te->dumpId] - 1] = false; + TocEntry *ted = AH->tocsByDumpId[AH->tableDataId[te->dumpId]]; + + ted->reqs = 0; } } diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index 8c764a2d493..4361805baab 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -162,9 +162,9 @@ typedef enum typedef enum { - REQ_SCHEMA = 1, - REQ_DATA = 2, - REQ_ALL = REQ_SCHEMA + REQ_DATA + REQ_SCHEMA = 0x01, /* want schema */ + REQ_DATA = 0x02, /* want data */ + REQ_SPECIAL = 0x04 /* for special TOC entries */ } teReqs; typedef struct _archiveHandle @@ -313,13 +313,13 @@ typedef struct _tocEntry void *dataDumperArg; /* Arg for above routine */ void *formatData; /* TOC Entry data specific to file format */ - /* in post data? not quite the same as section, might be SECTION_NONE */ - bool inPostData; + /* working state while dumping/restoring */ + teReqs reqs; /* do we need schema and/or data of object */ + bool created; /* set for DATA member if TABLE was created */ /* working state (needed only for parallel restore) */ struct _tocEntry *par_prev; /* list links for pending/ready items; */ struct _tocEntry *par_next; /* these are NULL if not in either list */ - bool created; /* set for DATA member if TABLE was created */ int depCount; /* number of dependencies not yet restored */ DumpId *revDeps; /* dumpIds of objects depending on this one */ int nRevDeps; /* number of such dependencies */ @@ -339,7 +339,7 @@ extern void WriteToc(ArchiveHandle *AH); extern void ReadToc(ArchiveHandle *AH); extern void WriteDataChunks(ArchiveHandle *AH); -extern teReqs TocIDRequired(ArchiveHandle *AH, DumpId id, RestoreOptions *ropt); +extern teReqs TocIDRequired(ArchiveHandle *AH, DumpId id); extern bool checkSeek(FILE *fp); #define appendStringLiteralAHX(buf,str,AH) \ diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c index 451c9574f7c..9fe2b14df55 100644 --- a/src/bin/pg_dump/pg_backup_tar.c +++ b/src/bin/pg_dump/pg_backup_tar.c @@ -817,6 +817,7 @@ _CloseArchive(ArchiveHandle *AH) lclContext *ctx = (lclContext *) AH->formatData; TAR_MEMBER *th; RestoreOptions *ropt; + RestoreOptions *savRopt; int savVerbose, i; @@ -860,16 +861,21 @@ _CloseArchive(ArchiveHandle *AH) ctx->scriptTH = th; ropt = NewRestoreOptions(); + memcpy(ropt, AH->ropt, sizeof(RestoreOptions)); ropt->dropSchema = 1; ropt->compression = 0; ropt->superuser = NULL; ropt->suppressDumpWarnings = true; + savRopt = AH->ropt; + AH->ropt = ropt; + savVerbose = AH->public.verbose; AH->public.verbose = 0; - RestoreArchive((Archive *) AH, ropt); + RestoreArchive((Archive *) AH); + AH->ropt = savRopt; AH->public.verbose = savVerbose; tarClose(AH, th); @@ -1176,7 +1182,7 @@ _tarPositionTo(ArchiveHandle *AH, const char *filename) ahlog(AH, 4, "skipping tar member %s\n", th->targetFile); id = atoi(th->targetFile); - if ((TocIDRequired(AH, id, AH->ropt) & REQ_DATA) != 0) + if ((TocIDRequired(AH, id) & REQ_DATA) != 0) exit_horribly(modulename, "restoring data out of order is not supported in this archive format: " "\"%s\" is required, but comes before \"%s\" in the archive file.\n", th->targetFile, filename); diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 46ab6ee2bbc..3461f3e34c3 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -90,7 +90,7 @@ bool g_verbose; /* User wants verbose narration of our /* various user-settable parameters */ bool schemaOnly; bool dataOnly; -int dumpSections; /* bitmask of chosen sections */ +int dumpSections; /* bitmask of chosen sections */ bool aclsSkip; const char *lockWaitTimeout; @@ -253,6 +253,7 @@ static const char *getAttrName(int attrnum, TableInfo *tblInfo); static const char *fmtCopyColumnList(const TableInfo *ti); static PGresult *ExecuteSqlQueryForSingleRow(Archive *fout, char *query); + int main(int argc, char **argv) { @@ -499,7 +500,7 @@ main(int argc, char **argv) break; case 5: /* section */ - set_section(optarg, &dumpSections); + set_dump_section(optarg, &dumpSections); break; default: @@ -529,19 +530,6 @@ main(int argc, char **argv) if (dataOnly && schemaOnly) exit_horribly(NULL, "options -s/--schema-only and -a/--data-only cannot be used together\n"); - if ((dataOnly || schemaOnly) && dumpSections != DUMP_UNSECTIONED) - exit_horribly(NULL, "options -s/--schema-only and -a/--data-only cannot be used with --section\n"); - - if (dataOnly) - dumpSections = DUMP_DATA; - else if (schemaOnly) - dumpSections = DUMP_PRE_DATA | DUMP_POST_DATA; - else if ( dumpSections != DUMP_UNSECTIONED) - { - dataOnly = dumpSections == DUMP_DATA; - schemaOnly = !(dumpSections & DUMP_DATA); - } - if (dataOnly && outputClean) exit_horribly(NULL, "options -c/--clean and -a/--data-only cannot be used together\n"); @@ -739,31 +727,40 @@ main(int argc, char **argv) dumpDumpableObject(fout, dobjs[i]); /* - * And finally we can do the actual output. + * Set up options info to ensure we dump what we want. */ - if (plainText) - { - ropt = NewRestoreOptions(); - ropt->filename = filename; - ropt->dropSchema = outputClean; - ropt->aclsSkip = aclsSkip; - ropt->superuser = outputSuperuser; - ropt->createDB = outputCreateDB; - ropt->noOwner = outputNoOwner; - ropt->noTablespace = outputNoTablespaces; - ropt->disable_triggers = disable_triggers; - ropt->use_setsessauth = use_setsessauth; - ropt->dataOnly = dataOnly; - - if (compressLevel == -1) - ropt->compression = 0; - else - ropt->compression = compressLevel; + ropt = NewRestoreOptions(); + ropt->filename = filename; + ropt->dropSchema = outputClean; + ropt->dataOnly = dataOnly; + ropt->schemaOnly = schemaOnly; + ropt->dumpSections = dumpSections; + ropt->aclsSkip = aclsSkip; + ropt->superuser = outputSuperuser; + ropt->createDB = outputCreateDB; + ropt->noOwner = outputNoOwner; + ropt->noTablespace = outputNoTablespaces; + ropt->disable_triggers = disable_triggers; + ropt->use_setsessauth = use_setsessauth; - ropt->suppressDumpWarnings = true; /* We've already shown them */ + if (compressLevel == -1) + ropt->compression = 0; + else + ropt->compression = compressLevel; - RestoreArchive(fout, ropt); - } + ropt->suppressDumpWarnings = true; /* We've already shown them */ + + SetArchiveRestoreOptions(fout, ropt); + + /* + * And finally we can do the actual output. + * + * Note: for non-plain-text output formats, the output file is written + * inside CloseArchive(). This is, um, bizarre; but not worth changing + * right now. + */ + if (plainText) + RestoreArchive(fout); CloseArchive(fout); @@ -7084,28 +7081,6 @@ collectComments(Archive *fout, CommentItem **items) static void dumpDumpableObject(Archive *fout, DumpableObject *dobj) { - - bool skip = false; - - switch (dobj->objType) - { - case DO_INDEX: - case DO_TRIGGER: - case DO_CONSTRAINT: - case DO_FK_CONSTRAINT: - case DO_RULE: - skip = !(dumpSections & DUMP_POST_DATA); - break; - case DO_TABLE_DATA: - skip = !(dumpSections & DUMP_DATA); - break; - default: - skip = !(dumpSections & DUMP_PRE_DATA); - } - - if (skip) - return; - switch (dobj->objType) { case DO_NAMESPACE: diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c index d1a2ce36656..f3715271939 100644 --- a/src/bin/pg_dump/pg_restore.c +++ b/src/bin/pg_dump/pg_restore.c @@ -274,7 +274,7 @@ main(int argc, char **argv) break; case 3: /* section */ - set_section(optarg, &(opts->dumpSections)); + set_dump_section(optarg, &(opts->dumpSections)); break; default: @@ -299,30 +299,6 @@ main(int argc, char **argv) exit_nicely(1); } - if (opts->dataOnly && opts->schemaOnly) - { - fprintf(stderr, _("%s: options -s/--schema-only and -a/--data-only cannot be used together\n"), - progname); - exit_nicely(1); - } - - if ((opts->dataOnly || opts->schemaOnly) && (opts->dumpSections != DUMP_UNSECTIONED)) - { - fprintf(stderr, _("%s: options -s/--schema-only and -a/--data-only cannot be used with --section\n"), - progname); - exit_nicely(1); - } - - if (opts->dataOnly) - opts->dumpSections = DUMP_DATA; - else if (opts->schemaOnly) - opts->dumpSections = DUMP_PRE_DATA | DUMP_POST_DATA; - else if ( opts->dumpSections != DUMP_UNSECTIONED) - { - opts->dataOnly = opts->dumpSections == DUMP_DATA; - opts->schemaOnly = !(opts->dumpSections & DUMP_DATA); - } - /* Should get at most one of -d and -f, else user is confused */ if (opts->dbname) { @@ -396,19 +372,14 @@ main(int argc, char **argv) if (opts->tocFile) SortTocFromFile(AH, opts); - else if (opts->noDataForFailedTables) - { - /* - * we implement this option by clearing idWanted entries, so must - * create a dummy idWanted array if there wasn't a tocFile - */ - InitDummyWantedList(AH, opts); - } if (opts->tocSummary) PrintTOCSummary(AH, opts); else - RestoreArchive(AH, opts); + { + SetArchiveRestoreOptions(AH, opts); + RestoreArchive(AH); + } /* done, print a summary of ignored errors */ if (AH->n_errors) |