]> granicus.if.org Git - postgresql/commitdiff
Rewrite --section option to decouple it from --schema-only/--data-only.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 30 May 2012 03:22:14 +0000 (23:22 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 30 May 2012 03:22:14 +0000 (23:22 -0400)
The initial implementation of pg_dump's --section option supposed that the
existing --schema-only and --data-only options could be made equivalent to
--section settings.  This is wrong, though, due to dubious but long since
set-in-stone decisions about where to dump SEQUENCE SET items, as seen in
bug report from Martin Pitt.  (And I'm not totally convinced there weren't
other bugs, either.)  Undo that coupling and instead drive --section
filtering off current-section state tracked as we scan through the TOC
list to call _tocEntryRequired().

To make sure those decisions don't shift around and hopefully save a few
cycles, run _tocEntryRequired() only once per TOC entry and save the result
in a new TOC field.  This required minor rejiggering of ACL handling but
also allows a far cleaner implementation of inhibit_data_for_failed_table.

Also, to ensure that pg_dump and pg_restore have the same behavior with
respect to the --section switches, add _tocEntryRequired() filtering to
WriteToc() and WriteDataChunks(), rather than trying to implement section
filtering in an entirely orthogonal way in dumpDumpableObject().  This
required adjusting the handling of the special ENCODING and STDSTRINGS
items, but they were pretty weird before anyway.

Minor other code review for the patch, too.

doc/src/sgml/ref/pg_dump.sgml
doc/src/sgml/ref/pg_restore.sgml
src/bin/pg_dump/dumputils.c
src/bin/pg_dump/dumputils.h
src/bin/pg_dump/pg_backup.h
src/bin/pg_dump/pg_backup_archiver.c
src/bin/pg_dump/pg_backup_archiver.h
src/bin/pg_dump/pg_backup_tar.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_restore.c

index 12ddd2596621781762ce251f8a587696f237617c..450383083d7e1137c4e8c4604d7091ab4daa457a 100644 (file)
@@ -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>
index 513b946e571321373a970011a99b4c5fbdcca29a..bc3d2b7e90fe8760fbbeca735a86e332deb2f5eb 100644 (file)
       <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>
       <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>
 
        <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>
index b662ad107e56e1a7b1006b83ebcb8b688f5bd6bb..623c250eb895ef6ad0bbd4098664086064192689 100644 (file)
@@ -17,7 +17,6 @@
 #include <ctype.h>
 
 #include "dumputils.h"
-#include "pg_backup.h"
 
 #include "parser/keywords.h"
 
@@ -1230,6 +1229,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.
  *
@@ -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)
index 82cf940892cb5c03d6274269b4d46a8bb97b6f68..3d1ed9570abbbbee3e4856268052c4fb4f474465 100644 (file)
 #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));
 
index 61c68636669029b679a515a3064c2dd1e1be8f86..bf7cc1c1ac8bed9e76f19ef5cd5146f3af99d518 100644 (file)
@@ -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);
index 7aaba36385c8b8e2a6f064e9c99d2871feb50a1e..c049becf126cccbd034474a09f818b0daa0c9e09 100644 (file)
@@ -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;
        }
 }
 
index 8c764a2d4938a044bc2a3ed86cc9f614bab8d5ef..4361805baab8eea273a7bcc74d0396704709d9e9 100644 (file)
@@ -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) \
index 451c9574f7cbcefd1a84c3d9fde0fe45ee61d3ac..9fe2b14df5560e127562b7e01fcb68d671c39a56 100644 (file)
@@ -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);
index 46ab6ee2bbceea26aa2ed07cc1130f074852a70f..3461f3e34c39ab7be68c205e271331043cabc72e 100644 (file)
@@ -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:
index d1a2ce366560619a49476c62f64e00a4ffb5b48a..f37152719399b0d8a9340104e134c410f1194abf 100644 (file)
@@ -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)