Add --section option to pg_dump and pg_restore.

Valid values are --pre-data, data and post-data. The option can be
given more than once. --schema-only is equivalent to
--section=pre-data --section=post-data. --data-only is equivalent
to --section=data.

Andrew Dunstan, reviewed by Joachim Wieland and Josh Berkus.
This commit is contained in:
Andrew Dunstan 2011-12-16 19:09:38 -05:00
parent 4b43b48c9f
commit a4cd6abcc9
10 changed files with 184 additions and 6 deletions

View File

@ -116,9 +116,7 @@ PostgreSQL documentation
</para> </para>
<para> <para>
This option is only meaningful for the plain-text format. For This option is equivalent to specifying <option>--section=data</>.
the archive formats, you can specify the option when you
call <command>pg_restore</command>.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -408,9 +406,29 @@ PostgreSQL documentation
To exclude table data for only a subset of tables in the database, To exclude table data for only a subset of tables in the database,
see <option>--exclude-table-data</>. see <option>--exclude-table-data</>.
</para> </para>
<para>
This option is equivalent to specifying
<option>--section=pre-data --section=post-data</>.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<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.
</para>
<para>
Post-data items consist of definitions of indexes, triggers, rules
and constraints other than check constraints.
Pre-data items consist of all other data definition items.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>-S <replaceable class="parameter">username</replaceable></option></term> <term><option>-S <replaceable class="parameter">username</replaceable></option></term>
<term><option>--superuser=<replaceable class="parameter">username</replaceable></option></term> <term><option>--superuser=<replaceable class="parameter">username</replaceable></option></term>

View File

@ -93,6 +93,9 @@
<para> <para>
Restore only the data, not the schema (data definitions). Restore only the data, not the schema (data definitions).
</para> </para>
<para>
This option is equivalent to specifying <option>--section=data</>.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -359,6 +362,10 @@
(Do not confuse this with the <option>--schema</> option, which (Do not confuse this with the <option>--schema</> option, which
uses the word <quote>schema</> in a different meaning.) uses the word <quote>schema</> in a different meaning.)
</para> </para>
<para>
This option is equivalent to specifying
<option>--section=pre-data --section=post-data</>.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -504,6 +511,22 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
<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.
</para>
<para>
Post-data items consist of definitions of indexes, triggers, rules
and constraints other than check constraints.
Pre-data items consist of all other data definition items.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--use-set-session-authorization</option></term> <term><option>--use-set-session-authorization</option></term>
<listitem> <listitem>

View File

@ -2,7 +2,7 @@
* *
* common.c * common.c
* Catalog routines used by pg_dump; long ago these were shared * Catalog routines used by pg_dump; long ago these were shared
* by another dump tool, but not anymore. * by another dump tool, but not anymore.
* *
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California

View File

@ -17,6 +17,7 @@
#include <ctype.h> #include <ctype.h>
#include "dumputils.h" #include "dumputils.h"
#include "pg_backup.h"
#include "parser/keywords.h" #include "parser/keywords.h"
@ -1262,3 +1263,32 @@ exit_horribly(const char *modulename, const char *fmt,...)
exit(1); exit(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(1);
}
}

View File

@ -58,5 +58,6 @@ extern void vwrite_msg(const char *modulename, const char *fmt, va_list ap)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0))); __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
extern void exit_horribly(const char *modulename, const char *fmt,...) extern void exit_horribly(const char *modulename, const char *fmt,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3))); __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
extern void set_section (const char *arg, int *dumpSections);
#endif /* DUMPUTILS_H */ #endif /* DUMPUTILS_H */

View File

@ -69,6 +69,14 @@ typedef enum _teSection
SECTION_POST_DATA /* stuff to be processed after data */ SECTION_POST_DATA /* stuff to be processed after data */
} teSection; } 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 * We may want to have some more user-readable data, but in the mean
* time this gives us some abstraction and type checking. * time this gives us some abstraction and type checking.
@ -111,6 +119,7 @@ typedef struct _restoreOptions
int dropSchema; int dropSchema;
char *filename; char *filename;
int schemaOnly; int schemaOnly;
int dumpSections;
int verbose; int verbose;
int aclsSkip; int aclsSkip;
int tocSummary; int tocSummary;

View File

@ -665,6 +665,7 @@ NewRestoreOptions(void)
/* set any fields that shouldn't default to zeroes */ /* set any fields that shouldn't default to zeroes */
opts->format = archUnknown; opts->format = archUnknown;
opts->promptPassword = TRI_DEFAULT; opts->promptPassword = TRI_DEFAULT;
opts->dumpSections = DUMP_UNSECTIONED;
return opts; return opts;
} }
@ -2120,6 +2121,7 @@ ReadToc(ArchiveHandle *AH)
int depIdx; int depIdx;
int depSize; int depSize;
TocEntry *te; TocEntry *te;
bool in_post_data = false;
AH->tocCount = ReadInt(AH); AH->tocCount = ReadInt(AH);
AH->maxDumpId = 0; AH->maxDumpId = 0;
@ -2185,6 +2187,12 @@ ReadToc(ArchiveHandle *AH)
te->section = SECTION_PRE_DATA; 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->defn = ReadStr(AH);
te->dropStmt = ReadStr(AH); te->dropStmt = ReadStr(AH);
@ -2334,6 +2342,17 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
if (!ropt->createDB && strcmp(te->desc, "DATABASE") == 0) if (!ropt->createDB && strcmp(te->desc, "DATABASE") == 0)
return 0; return 0;
/* skip (all but) post data section as required */
/* table data is filtered if necessary lower down */
if (ropt->dumpSections != DUMP_UNSECTIONED)
{
if (!(ropt->dumpSections & DUMP_POST_DATA) && te->inPostData)
return 0;
if (!(ropt->dumpSections & DUMP_PRE_DATA) && ! te->inPostData && strcmp(te->desc, "TABLE DATA") != 0)
return 0;
}
/* Check options for selective dump/restore */ /* Check options for selective dump/restore */
if (ropt->schemaNames) if (ropt->schemaNames)
{ {

View File

@ -287,6 +287,9 @@ typedef struct _tocEntry
void *dataDumperArg; /* Arg for above routine */ void *dataDumperArg; /* Arg for above routine */
void *formatData; /* TOC Entry data specific to file format */ 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 (needed only for parallel restore) */ /* working state (needed only for parallel restore) */
struct _tocEntry *par_prev; /* list links for pending/ready items; */ struct _tocEntry *par_prev; /* list links for pending/ready items; */
struct _tocEntry *par_next; /* these are NULL if not in either list */ struct _tocEntry *par_next; /* these are NULL if not in either list */

View File

@ -91,6 +91,7 @@ PGconn *g_conn; /* the database connection */
/* various user-settable parameters */ /* various user-settable parameters */
bool schemaOnly; bool schemaOnly;
bool dataOnly; bool dataOnly;
int dumpSections; /* bitmask of chosen sections */
bool aclsSkip; bool aclsSkip;
const char *lockWaitTimeout; const char *lockWaitTimeout;
@ -250,7 +251,6 @@ static void do_sql_command(PGconn *conn, const char *query);
static void check_sql_result(PGresult *res, PGconn *conn, const char *query, static void check_sql_result(PGresult *res, PGconn *conn, const char *query,
ExecStatusType expected); ExecStatusType expected);
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
@ -332,6 +332,7 @@ main(int argc, char **argv)
{"no-tablespaces", no_argument, &outputNoTablespaces, 1}, {"no-tablespaces", no_argument, &outputNoTablespaces, 1},
{"quote-all-identifiers", no_argument, &quote_all_identifiers, 1}, {"quote-all-identifiers", no_argument, &quote_all_identifiers, 1},
{"role", required_argument, NULL, 3}, {"role", required_argument, NULL, 3},
{"section", required_argument, NULL, 5},
{"serializable-deferrable", no_argument, &serializable_deferrable, 1}, {"serializable-deferrable", no_argument, &serializable_deferrable, 1},
{"use-set-session-authorization", no_argument, &use_setsessauth, 1}, {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
{"no-security-labels", no_argument, &no_security_labels, 1}, {"no-security-labels", no_argument, &no_security_labels, 1},
@ -349,6 +350,7 @@ main(int argc, char **argv)
strcpy(g_opaque_type, "opaque"); strcpy(g_opaque_type, "opaque");
dataOnly = schemaOnly = false; dataOnly = schemaOnly = false;
dumpSections = DUMP_UNSECTIONED;
lockWaitTimeout = NULL; lockWaitTimeout = NULL;
progname = get_progname(argv[0]); progname = get_progname(argv[0]);
@ -494,6 +496,10 @@ main(int argc, char **argv)
simple_string_list_append(&tabledata_exclude_patterns, optarg); simple_string_list_append(&tabledata_exclude_patterns, optarg);
break; break;
case 5: /* section */
set_section(optarg, &dumpSections);
break;
default: default:
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit(1); exit(1);
@ -524,6 +530,22 @@ main(int argc, char **argv)
exit(1); exit(1);
} }
if ((dataOnly || schemaOnly) && dumpSections != DUMP_UNSECTIONED)
{
write_msg(NULL, "options -s/--schema-only and -a/--data-only cannot be used with --section\n");
exit(1);
}
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) if (dataOnly && outputClean)
{ {
write_msg(NULL, "options -c/--clean and -a/--data-only cannot be used together\n"); write_msg(NULL, "options -c/--clean and -a/--data-only cannot be used together\n");
@ -871,6 +893,7 @@ help(const char *progname)
printf(_(" --no-tablespaces do not dump tablespace assignments\n")); printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
printf(_(" --no-unlogged-table-data do not dump unlogged table data\n")); printf(_(" --no-unlogged-table-data do not dump unlogged table data\n"));
printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n")); printf(_(" --quote-all-identifiers quote all identifiers, even if not key words\n"));
printf(_(" --section=SECTION dump named section (pre-data, data or post-data)\n"));
printf(_(" --serializable-deferrable wait until the dump can run without anomalies\n")); printf(_(" --serializable-deferrable wait until the dump can run without anomalies\n"));
printf(_(" --use-set-session-authorization\n" printf(_(" --use-set-session-authorization\n"
" use SET SESSION AUTHORIZATION commands instead of\n" " use SET SESSION AUTHORIZATION commands instead of\n"
@ -1107,7 +1130,7 @@ selectDumpableTable(TableInfo *tbinfo)
tbinfo->dobj.dumpdata = true; tbinfo->dobj.dumpdata = true;
else else
tbinfo->dobj.dumpdata = false; tbinfo->dobj.dumpdata = false;
} }
/* /*
@ -7093,6 +7116,28 @@ collectComments(Archive *fout, CommentItem **items)
static void static void
dumpDumpableObject(Archive *fout, DumpableObject *dobj) 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) switch (dobj->objType)
{ {
case DO_NAMESPACE: case DO_NAMESPACE:

View File

@ -118,6 +118,7 @@ main(int argc, char **argv)
{"no-data-for-failed-tables", no_argument, &no_data_for_failed_tables, 1}, {"no-data-for-failed-tables", no_argument, &no_data_for_failed_tables, 1},
{"no-tablespaces", no_argument, &outputNoTablespaces, 1}, {"no-tablespaces", no_argument, &outputNoTablespaces, 1},
{"role", required_argument, NULL, 2}, {"role", required_argument, NULL, 2},
{"section", required_argument, NULL, 3},
{"use-set-session-authorization", no_argument, &use_setsessauth, 1}, {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
{"no-security-labels", no_argument, &no_security_labels, 1}, {"no-security-labels", no_argument, &no_security_labels, 1},
@ -272,6 +273,10 @@ main(int argc, char **argv)
opts->use_role = optarg; opts->use_role = optarg;
break; break;
case 3: /* section */
set_section(optarg, &(opts->dumpSections));
break;
default: default:
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit(1); exit(1);
@ -294,6 +299,30 @@ main(int argc, char **argv)
exit(1); exit(1);
} }
if (opts->dataOnly && opts->schemaOnly)
{
fprintf(stderr, _("%s: options -s/--schema-only and -a/--data-only cannot be used together\n"),
progname);
exit(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(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 */ /* Should get at most one of -d and -f, else user is confused */
if (opts->dbname) if (opts->dbname)
{ {
@ -434,6 +463,7 @@ usage(const char *progname)
" created\n")); " created\n"));
printf(_(" --no-security-labels do not restore security labels\n")); printf(_(" --no-security-labels do not restore security labels\n"));
printf(_(" --no-tablespaces do not restore tablespace assignments\n")); printf(_(" --no-tablespaces do not restore tablespace assignments\n"));
printf(_(" --section=SECTION restore named section (pre-data, data or post-data)\n"));
printf(_(" --use-set-session-authorization\n" printf(_(" --use-set-session-authorization\n"
" use SET SESSION AUTHORIZATION commands instead of\n" " use SET SESSION AUTHORIZATION commands instead of\n"
" ALTER OWNER commands to set ownership\n")); " ALTER OWNER commands to set ownership\n"));