Revise psql pattern-matching switches as per discussion. The rule is now

to process all inclusion switches then all exclusion switches, so that the
behavior is independent of switch ordering.
Use of -T does not cause non-table objects to be suppressed.  And
the patterns are now interpreted the same way psql's \d commands do it,
rather than as pure regex commands; this allows for example -t schema.tab
to do what it should have been doing all along.  Re-enable the --blobs
switch to do something useful, ie, add back blobs into a dump they were
otherwise suppressed from.
This commit is contained in:
Tom Lane 2006-10-09 23:36:59 +00:00
parent 77d2b1b625
commit 24e9752863
4 changed files with 554 additions and 381 deletions

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.89 2006/10/07 20:59:04 petere Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.90 2006/10/09 23:36:58 tgl Exp $
PostgreSQL documentation
-->
@ -14,7 +14,7 @@ PostgreSQL documentation
<refname>pg_dump</refname>
<refpurpose>
extract a <productname>PostgreSQL</productname> database into a script file or other archive file
extract a <productname>PostgreSQL</productname> database into a script file or other archive file
</refpurpose>
</refnamediv>
@ -126,6 +126,19 @@ PostgreSQL documentation
</listitem>
</varlistentry>
<varlistentry>
<term><option>-b</></term>
<term><option>--blobs</></term>
<listitem>
<para>
Include large objects in the dump. This is the default behavior
except when <option>--schema</>, <option>--table</>, or
<option>--schema-only</> is specified, so the <option>-b</>
switch is only useful to add large objects to selective dumps.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-c</option></term>
<term><option>--clean</option></term>
@ -170,12 +183,14 @@ PostgreSQL documentation
Dump data as <command>INSERT</command> commands (rather
than <command>COPY</command>). This will make restoration very slow;
it is mainly useful for making dumps that can be loaded into
non-<productname>PostgreSQL</productname> databases. Note that
non-<productname>PostgreSQL</productname> databases.
Also, since this option generates a separate command for each row,
an error in reloading a row causes only that row to be lost rather
than the entire table contents.
Note that
the restore may fail altogether if you have rearranged column order.
The <option>-D</option> option is safer, though even slower.
Also, while this option generates errors for invalid data,
it allows other <command>INSERT</command>s to continue loading
data into the table.
The <option>-D</option> option is safe against column order changes,
though even slower.
</para>
</listitem>
</varlistentry>
@ -193,9 +208,9 @@ PostgreSQL documentation
...</literal>). This will make restoration very slow; it is mainly
useful for making dumps that can be loaded into
non-<productname>PostgreSQL</productname> databases.
Also, while this option generates errors for invalid data,
it allows other <command>INSERT</command>s to continue loading
data into the table.
Also, since this option generates a separate command for each row,
an error in reloading a row causes only that row to be lost rather
than the entire table contents.
</para>
</listitem>
</varlistentry>
@ -238,7 +253,7 @@ PostgreSQL documentation
<term><literal>plain</></term>
<listitem>
<para>
Output a plain-text <acronym>SQL</acronym> script file (default)
Output a plain-text <acronym>SQL</acronym> script file (the default).
</para>
</listitem>
</varlistentry>
@ -248,10 +263,10 @@ PostgreSQL documentation
<term><literal>custom</></term>
<listitem>
<para>
Output a custom archive suitable for input into
<application>pg_restore</application>. This is the most flexible
format in that it allows reordering of loading data as well
as object definitions. This format is also compressed by default.
Output a custom archive suitable for input into
<application>pg_restore</application>. This is the most flexible
format in that it allows reordering of loading data as well
as object definitions. This format is also compressed by default.
</para>
</listitem>
</varlistentry>
@ -261,11 +276,11 @@ PostgreSQL documentation
<term><literal>tar</></term>
<listitem>
<para>
Output a <command>tar</command> archive suitable for input into
<application>pg_restore</application>. Using this archive format
allows reordering and/or exclusion of database objects
at the time the database is restored. It is also possible to limit
which data is reloaded at restore time.
Output a <command>tar</command> archive suitable for input into
<application>pg_restore</application>. Using this archive format
allows reordering and/or exclusion of database objects
at the time the database is restored. It is also possible to limit
which data is reloaded at restore time.
</para>
</listitem>
</varlistentry>
@ -286,9 +301,11 @@ PostgreSQL documentation
</para>
<para>
<application>pg_dump</application> can handle databases from
<application>pg_dump</application> can dump from servers running
previous releases of <productname>PostgreSQL</>, but very old
versions are not supported anymore (currently prior to 7.0).
versions are not supported anymore (currently, those prior to 7.0).
Dumping from a server newer than <application>pg_dump</application>
is likely not to work at all.
Use this option if you need to override the version check (and
if <application>pg_dump</application> then fails, don't say
you weren't warned).
@ -301,20 +318,61 @@ PostgreSQL documentation
<term><option>--schema=<replaceable class="parameter">schema</replaceable></option></term>
<listitem>
<para>
Dump the contents of <replaceable class="parameter">schema</>
only. If this option is not specified, all non-system schemas
in the target database will be dumped.
Dump only schemas matching <replaceable
class="parameter">schema</replaceable>; this selects both the
schema itself, and all its contained objects. When this option is
not specified, all non-system schemas in the target database will be
dumped. Multiple schemas can be
selected by writing multiple <option>-n</> switches. Also, the
<replaceable class="parameter">schema</replaceable> parameter is
interpreted as a pattern according to the same rules used by
<application>psql</>'s <literal>\d</> commands (see <xref
linkend="APP-PSQL-patterns" endterm="APP-PSQL-patterns-title">),
so multiple schemas can also be selected by writing wildcard characters
in the pattern. When using wildcards, be careful to quote the pattern
if needed to prevent the shell from expanding the wildcards.
</para>
<note>
<para>
In this mode, <application>pg_dump</application> makes no
attempt to dump any other database objects that objects in the
selected schema may depend upon. Therefore, there is no
guarantee that the results of a single-schema dump can be
successfully restored by themselves into a clean database.
When <option>-n</> is specified, <application>pg_dump</application>
makes no attempt to dump any other database objects that the selected
schema(s) may depend upon. Therefore, there is no guarantee
that the results of a specific-schema dump can be successfully
restored by themselves into a clean database.
</para>
</note>
<note>
<para>
Non-schema objects such as blobs are not dumped when <option>-n</> is
specified. You can add blobs back to the dump with the
<option>--blobs</> switch.
</para>
</note>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-N <replaceable class="parameter">schema</replaceable></option></term>
<term><option>--exclude-schema=<replaceable class="parameter">schema</replaceable></option></term>
<listitem>
<para>
Do not dump any schemas matching the <replaceable
class="parameter">schema</replaceable> pattern. The pattern is
interpreted according to the same rules as for <option>-n</>.
<option>-N</> can be given more than once to exclude schemas
matching any of several patterns.
</para>
<para>
When both <option>-n</> and <option>-N</> are given, the behavior
is to dump just the schemas that match at least one <option>-n</>
switch but no <option>-N</> switches. If <option>-N</> appears
without <option>-n</>, then schemas matching <option>-N</> are
excluded from what is otherwise a normal dump.
</para>
</listitem>
</varlistentry>
@ -340,7 +398,7 @@ PostgreSQL documentation
Do not output commands to set
ownership of objects to match the original database.
By default, <application>pg_dump</application> issues
<command>ALTER OWNER</> or
<command>ALTER OWNER</> or
<command>SET SESSION AUTHORIZATION</command>
statements to set ownership of created database objects.
These statements
@ -397,67 +455,47 @@ PostgreSQL documentation
<term><option>--table=<replaceable class="parameter">table</replaceable></option></term>
<listitem>
<para>
Dump data for <replaceable class="parameter">table</replaceable>
only. It is possible for there to be multiple tables with the same
name in different schemas; if that is the case, all matching tables
will be dumped. Also, if any POSIX regular expression character appears
in the table name (<literal>([{\.?+</>, the string will be interpreted
as a regular expression. Note that when in regular expression mode, the
string will not be anchored to the start/end unless <literal>^</> and
<literal>$</> are used at the beginning/end of the string.
Dump only tables (or views or sequences) matching <replaceable
class="parameter">table</replaceable>. Multiple tables can be
selected by writing multiple <option>-t</> switches. Also, the
<replaceable class="parameter">table</replaceable> parameter is
interpreted as a pattern according to the same rules used by
<application>psql</>'s <literal>\d</> commands (see <xref
linkend="APP-PSQL-patterns" endterm="APP-PSQL-patterns-title">),
so multiple tables can also be selected by writing wildcard characters
in the pattern. When using wildcards, be careful to quote the pattern
if needed to prevent the shell from expanding the wildcards.
</para>
<para>
The options <option>-t</>, <option>-T</>, <option>-n</>, and <option>-N</>
can be used together to achieve a high degree of control over what is
dumped. Multiple arguments can be used, and are parsed in the order
given to build a list of valid tables and schemas. The schema options are
parsed first to create a list of schemas to dump, and then the table options
are parsed to only find tables in the matching schemas.
The <option>-n</> and <option>-N</> switches have no effect when
<option>-t</> is used, because tables selected by <option>-t</> will
be dumped regardless of those switches, and non-table objects will not
be dumped.
</para>
<para>For example, to dump a single table named <literal>pg_class</>:
<screen>
<prompt>$</prompt> <userinput>pg_dump -t pg_class mydb &gt; db.out</userinput>
</screen>
</para>
<para>To dump all tables starting with <literal>employee</> in the
<literal>detroit</> schema, except for the table named <literal>employee_log</literal>:
<screen>
<prompt>$</prompt> <userinput>pg_dump -n detroit -t ^employee -T employee_log mydb &gt; db.out</userinput>
</screen>
</para>
<para>To dump all schemas starting with <literal>east</> or <literal>west</> and ending in
<literal>gsm</>, but not schemas that contain the letters <literal>test</>, except for
one named <literal>east_alpha_test_five</>:
<screen>
<prompt>$</prompt> <userinput>pg_dump -n "^(east|west).*gsm$" -N test -n east_alpha_test_five mydb &gt; db.out</userinput>
</screen>
</para>
<para>To dump all tables except for those beginning with <literal>ts_</literal>:
<screen>
<prompt>$</prompt> <userinput>pg_dump -T "^ts_" mydb &gt; db.out</userinput>
</screen>
</para>
<note>
<para>
In this mode, <application>pg_dump</application> makes no
attempt to dump any other database objects that the selected tables
may depend upon. Therefore, there is no guarantee
When <option>-t</> is specified, <application>pg_dump</application>
makes no attempt to dump any other database objects that the selected
table(s) may depend upon. Therefore, there is no guarantee
that the results of a specific-table dump can be successfully
restored by themselves into a clean database.
</para>
</note>
<note>
<para>
The behavior of the <option>-t</> switch is not entirely upward
compatible with pre-8.2 <productname>PostgreSQL</productname>
versions. Formerly, writing <literal>-t tab</> would dump all
tables named <literal>tab</>, but now it just dumps whichever one
is visible in your default search path. To get the old behavior
you can write <literal>-t '*.tab'</>. Also, you must write something
like <literal>-t sch.tab</> to select a table in a particular schema,
rather than the old locution of <literal>-n sch -t tab</>.
</para>
</note>
</listitem>
</varlistentry>
@ -466,36 +504,20 @@ PostgreSQL documentation
<term><option>--exclude-table=<replaceable class="parameter">table</replaceable></option></term>
<listitem>
<para>
Do not dump any matching <replaceable class="parameter">tables</replaceable>.
More than one option can be used, and POSIX regular expressions are handled just
like <literal>-t</>.
Do not dump any tables matching the <replaceable
class="parameter">table</replaceable> pattern. The pattern is
interpreted according to the same rules as for <option>-t</>.
<option>-T</> can be given more than once to exclude tables
matching any of several patterns.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-n <replaceable class="parameter">schema</replaceable></option></term>
<term><option>--schema=<replaceable class="parameter">schema</replaceable></option></term>
<listitem>
<para>
Dump only the matching <replaceable class="parameter">schemas</replaceable>.
More than one option can be used, and POSIX regular expressions are handled just
like <literal>-t</>.
When both <option>-t</> and <option>-T</> are given, the behavior
is to dump just the tables that match at least one <option>-t</>
switch but no <option>-T</> switches. If <option>-T</> appears
without <option>-t</>, then tables matching <option>-T</> are
excluded from what is otherwise a normal dump.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-N <replaceable class="parameter">schema</replaceable></option></term>
<term><option>--exclude-schema=<replaceable class="parameter">schema</replaceable></option></term>
<listitem>
<para>
Do not dump the matching <replaceable class="parameter">schemas</replaceable>.
More than one option can be used, and POSIX regular expressions are handled just
like <literal>-t</>.
</para>
</listitem>
</varlistentry>
@ -506,7 +528,7 @@ PostgreSQL documentation
<para>
Specifies verbose mode. This will cause
<application>pg_dump</application> to output detailed object
comments and start/stop times to the dump file, and progress
comments and start/stop times to the dump file, and progress
messages to standard error.
</para>
</listitem>
@ -742,33 +764,80 @@ CREATE DATABASE foo WITH TEMPLATE template0;
<title>Examples</title>
<para>
To dump a database:
To dump a database called <literal>mydb</> into a SQL-script file:
<screen>
<prompt>$</prompt> <userinput>pg_dump mydb &gt; db.out</userinput>
<prompt>$</prompt> <userinput>pg_dump mydb &gt; db.sql</userinput>
</screen>
</para>
<para>
To reload this database:
To reload such a script into a (freshly created) database named
<literal>newdb</>:
<screen>
<prompt>$</prompt> <userinput>psql -d database -f db.out</userinput>
<prompt>$</prompt> <userinput>psql -d newdb -f db.sql</userinput>
</screen>
</para>
<para>
To dump a database called <literal>mydb</> to a file in custom format:
file:
To dump a database into a custom-format archive file:
<screen>
<prompt>$</prompt> <userinput>pg_dump -Fc mydb &gt; db.out</userinput>
<prompt>$</prompt> <userinput>pg_dump -Fc mydb &gt; db.dump</userinput>
</screen>
</para>
<para>
To reload this dump into an existing database called <literal>newdb</>:
To reload an archive file into a (freshly created) database named
<literal>newdb</>:
<screen>
<prompt>$</prompt> <userinput>pg_restore -d newdb db.out</userinput>
<prompt>$</prompt> <userinput>pg_restore -d newdb db.dump</userinput>
</screen>
</para>
<para>
To dump a single table named <literal>mytab</>:
<screen>
<prompt>$</prompt> <userinput>pg_dump -t mytab mydb &gt; db.sql</userinput>
</screen>
</para>
<para>
To dump all tables whose names start with <literal>emp</> in the
<literal>detroit</> schema, except for the table named
<literal>employee_log</literal>:
<screen>
<prompt>$</prompt> <userinput>pg_dump -t 'detroit.emp*' -T detroit.employee_log mydb &gt; db.sql</userinput>
</screen>
</para>
<para>
To dump all schemas whose names start with <literal>east</> or
<literal>west</> and end in <literal>gsm</>, excluding any schemas whose
names contain the word <literal>test</>:
<screen>
<prompt>$</prompt> <userinput>pg_dump -n 'east*gsm' -n 'west*gsm' -N '*test*' mydb &gt; db.sql</userinput>
</screen>
</para>
<para>
The same, using regular expression notation to consolidate the switches:
<screen>
<prompt>$</prompt> <userinput>pg_dump -n '(east|west)*gsm' -N '*test*' mydb &gt; db.sql</userinput>
</screen>
</para>
<para>
To dump all database objects except for tables whose names begin with
<literal>ts_</literal>:
<screen>
<prompt>$</prompt> <userinput>pg_dump -T 'ts_*' mydb &gt; db.sql</userinput>
</screen>
</para>

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.93 2006/09/27 15:41:23 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.94 2006/10/09 23:36:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -402,16 +402,14 @@ AssignDumpId(DumpableObject *dobj)
{
newAlloc = 256;
dumpIdMap = (DumpableObject **)
malloc(newAlloc * sizeof(DumpableObject *));
pg_malloc(newAlloc * sizeof(DumpableObject *));
}
else
{
newAlloc = allocedDumpIds * 2;
dumpIdMap = (DumpableObject **)
realloc(dumpIdMap, newAlloc * sizeof(DumpableObject *));
pg_realloc(dumpIdMap, newAlloc * sizeof(DumpableObject *));
}
if (dumpIdMap == NULL)
exit_horribly(NULL, NULL, "out of memory\n");
memset(dumpIdMap + allocedDumpIds, 0,
(newAlloc - allocedDumpIds) * sizeof(DumpableObject *));
allocedDumpIds = newAlloc;
@ -541,9 +539,7 @@ getDumpableObjects(DumpableObject ***objs, int *numObjs)
j;
*objs = (DumpableObject **)
malloc(allocedDumpIds * sizeof(DumpableObject *));
if (*objs == NULL)
exit_horribly(NULL, NULL, "out of memory\n");
pg_malloc(allocedDumpIds * sizeof(DumpableObject *));
j = 0;
for (i = 1; i < allocedDumpIds; i++)
{
@ -567,17 +563,15 @@ addObjectDependency(DumpableObject *dobj, DumpId refId)
{
dobj->allocDeps = 16;
dobj->dependencies = (DumpId *)
malloc(dobj->allocDeps * sizeof(DumpId));
pg_malloc(dobj->allocDeps * sizeof(DumpId));
}
else
{
dobj->allocDeps *= 2;
dobj->dependencies = (DumpId *)
realloc(dobj->dependencies,
dobj->allocDeps * sizeof(DumpId));
pg_realloc(dobj->dependencies,
dobj->allocDeps * sizeof(DumpId));
}
if (dobj->dependencies == NULL)
exit_horribly(NULL, NULL, "out of memory\n");
}
dobj->dependencies[dobj->nDeps++] = refId;
}
@ -707,7 +701,8 @@ findParentsByOid(TableInfo *self,
if (numParents > 0)
{
self->parents = (TableInfo **) malloc(sizeof(TableInfo *) * numParents);
self->parents = (TableInfo **)
pg_malloc(sizeof(TableInfo *) * numParents);
j = 0;
for (i = 0; i < numInherits; i++)
{
@ -806,3 +801,124 @@ strInArray(const char *pattern, char **arr, int arr_size)
}
return -1;
}
/*
* Support for simple list operations
*/
void
simple_oid_list_append(SimpleOidList *list, Oid val)
{
SimpleOidListCell *cell;
cell = (SimpleOidListCell *) pg_malloc(sizeof(SimpleOidListCell));
cell->next = NULL;
cell->val = val;
if (list->tail)
list->tail->next = cell;
else
list->head = cell;
list->tail = cell;
}
void
simple_string_list_append(SimpleStringList *list, const char *val)
{
SimpleStringListCell *cell;
/* this calculation correctly accounts for the null trailing byte */
cell = (SimpleStringListCell *)
pg_malloc(sizeof(SimpleStringListCell) + strlen(val));
cell->next = NULL;
strcpy(cell->val, val);
if (list->tail)
list->tail->next = cell;
else
list->head = cell;
list->tail = cell;
}
bool
simple_oid_list_member(SimpleOidList *list, Oid val)
{
SimpleOidListCell *cell;
for (cell = list->head; cell; cell = cell->next)
{
if (cell->val == val)
return true;
}
return false;
}
bool
simple_string_list_member(SimpleStringList *list, const char *val)
{
SimpleStringListCell *cell;
for (cell = list->head; cell; cell = cell->next)
{
if (strcmp(cell->val, val) == 0)
return true;
}
return false;
}
/*
* Safer versions of some standard C library functions. If an
* out-of-memory condition occurs, these functions will bail out
* safely; therefore, their return value is guaranteed to be non-NULL.
*
* XXX need to refactor things so that these can be in a file that can be
* shared by pg_dumpall and pg_restore as well as pg_dump.
*/
char *
pg_strdup(const char *string)
{
char *tmp;
if (!string)
exit_horribly(NULL, NULL, "cannot duplicate null pointer\n");
tmp = strdup(string);
if (!tmp)
exit_horribly(NULL, NULL, "out of memory\n");
return tmp;
}
void *
pg_malloc(size_t size)
{
void *tmp;
tmp = malloc(size);
if (!tmp)
exit_horribly(NULL, NULL, "out of memory\n");
return tmp;
}
void *
pg_calloc(size_t nmemb, size_t size)
{
void *tmp;
tmp = calloc(nmemb, size);
if (!tmp)
exit_horribly(NULL, NULL, "out of memory\n");
return tmp;
}
void *
pg_realloc(void *ptr, size_t size)
{
void *tmp;
tmp = realloc(ptr, size);
if (!tmp)
exit_horribly(NULL, NULL, "out of memory\n");
return tmp;
}

View File

@ -12,7 +12,7 @@
* by PostgreSQL
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.452 2006/10/07 20:59:04 petere Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.453 2006/10/09 23:36:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -40,8 +40,6 @@
int optreset;
#endif
#include "access/htup.h"
#include "catalog/pg_class.h"
#include "catalog/pg_proc.h"
@ -87,20 +85,24 @@ static const char *username_subquery;
/* obsolete as of 7.3: */
static Oid g_last_builtin_oid; /* value of the last builtin oid */
/* select and exclude tables and schemas */
typedef struct objnameArg
{
struct objnameArg *next;
char *name; /* name of the relation */
bool is_include; /* include/exclude? */
} objnameArg;
/*
* Object inclusion/exclusion lists
*
* The string lists record the patterns given by command-line switches,
* which we then convert to lists of OIDs of matching objects.
*/
static SimpleStringList schema_include_patterns = { NULL, NULL };
static SimpleOidList schema_include_oids = { NULL, NULL };
static SimpleStringList schema_exclude_patterns = { NULL, NULL };
static SimpleOidList schema_exclude_oids = { NULL, NULL };
objnameArg *schemaList = NULL; /* List of schemas to include/exclude */
objnameArg *tableList = NULL; /* List of tables to include/exclude */
static SimpleStringList table_include_patterns = { NULL, NULL };
static SimpleOidList table_include_oids = { NULL, NULL };
static SimpleStringList table_exclude_patterns = { NULL, NULL };
static SimpleOidList table_exclude_oids = { NULL, NULL };
char *matchingSchemas = NULL; /* Final list of schemas to dump by
* oid */
char *matchingTables = NULL; /* Final list of tables to dump by oid */
/* default, if no "inclusion" switches appear, is to dump everything */
static bool include_everything = true;
char g_opaque_type[10]; /* name for the opaque type */
@ -119,6 +121,10 @@ static int disable_dollar_quoting = 0;
static void help(const char *progname);
static void expand_schema_name_patterns(SimpleStringList *patterns,
SimpleOidList *oids);
static void expand_table_name_patterns(SimpleStringList *patterns,
SimpleOidList *oids);
static NamespaceInfo *findNamespace(Oid nsoid, Oid objoid);
static void dumpTableData(Archive *fout, TableDataInfo *tdinfo);
static void dumpComment(Archive *fout, const char *target,
@ -188,11 +194,6 @@ static void check_sql_result(PGresult *res, PGconn *conn, const char *query,
int
main(int argc, char **argv)
{
PQExpBuffer query = createPQExpBuffer();
PGresult *res;
objnameArg *this_obj_name,
*schemaList_tail = NULL,
*tableList_tail = NULL;
int c;
const char *filename = NULL;
const char *format = "p";
@ -208,14 +209,13 @@ main(int argc, char **argv)
DumpableObject **dobjs;
int numObjs;
int i;
bool switch_include_exclude;
bool force_password = false;
int compressLevel = -1;
bool ignore_version = false;
int plainText = 0;
int outputClean = 0;
int outputCreate = 0;
bool outputBlobs = true;
bool outputBlobs = false;
int outputNoOwner = 0;
static int use_setsessauth = 0;
static int disable_triggers = 0;
@ -306,7 +306,7 @@ main(int argc, char **argv)
break;
case 'b': /* Dump blobs */
/* this is now default, so just ignore the switch */
outputBlobs = true;
break;
case 'c': /* clean (i.e., drop) schema prior to create */
@ -347,42 +347,13 @@ main(int argc, char **argv)
ignore_version = true;
break;
case 'n': /* Include schemas */
case 'N': /* Exclude schemas */
case 't': /* Include tables */
case 'T': /* Exclude tables */
case 'n': /* include schema(s) */
simple_string_list_append(&schema_include_patterns, optarg);
include_everything = false;
break;
if (strlen(optarg) < 1)
{
fprintf(stderr, _("%s: invalid -%c option\n"), progname, c);
exit(1);
}
{
/* Create a struct for this name */
objnameArg *new_obj_name = (objnameArg *)
malloc(sizeof(objnameArg));
new_obj_name->next = NULL;
new_obj_name->name = strdup(optarg);
new_obj_name->is_include = islower((unsigned char) c) ? true : false;
/* add new entry to the proper list */
if (tolower((unsigned char) c) == 'n')
{
if (!schemaList_tail)
schemaList_tail = schemaList = new_obj_name;
else
schemaList_tail = schemaList_tail->next = new_obj_name;
}
else
{
if (!tableList_tail)
tableList_tail = tableList = new_obj_name;
else
tableList_tail = tableList_tail->next = new_obj_name;
}
}
case 'N': /* exclude schema(s) */
simple_string_list_append(&schema_exclude_patterns, optarg);
break;
case 'o': /* Dump oids */
@ -403,13 +374,21 @@ main(int argc, char **argv)
case 's': /* dump schema only */
schemaOnly = true;
outputBlobs = false;
break;
case 'S': /* Username for superuser in plain text output */
outputSuperuser = strdup(optarg);
break;
case 't': /* include table(s) */
simple_string_list_append(&table_include_patterns, optarg);
include_everything = false;
break;
case 'T': /* exclude table(s) */
simple_string_list_append(&table_exclude_patterns, optarg);
break;
case 'u':
force_password = true;
username = simple_prompt("User name: ", 100, true);
@ -488,9 +467,6 @@ main(int argc, char **argv)
exit(1);
}
if (matchingTables != NULL || matchingSchemas != NULL)
outputBlobs = false;
if (dumpInserts == true && oids == true)
{
write_msg(NULL, "INSERT (-d, -D) and OID (-o) options cannot be used together\n");
@ -607,162 +583,42 @@ main(int argc, char **argv)
write_msg(NULL, "last built-in OID is %u\n", g_last_builtin_oid);
}
if (schemaList != NULL && g_fout->remoteVersion < 70300)
/* Expand schema selection patterns into OID lists */
if (schema_include_patterns.head != NULL)
{
write_msg(NULL, "server version must be at least 7.3 to use schema switches\n");
exit_nicely();
}
/* Check schema selection flags */
resetPQExpBuffer(query);
switch_include_exclude = true;
for (this_obj_name = schemaList; this_obj_name; this_obj_name = this_obj_name->next)
{
if (switch_include_exclude)
{
/* Special case for when -N is the first argument */
if (this_obj_name == schemaList && !this_obj_name->is_include)
appendPQExpBuffer(query,
"SELECT oid FROM pg_catalog.pg_namespace "
"WHERE nspname NOT LIKE 'pg_%%' AND "
" nspname != 'information_schema' EXCEPT\n");
appendPQExpBuffer(query, "SELECT oid FROM pg_catalog.pg_namespace WHERE");
}
appendPQExpBuffer(query, "%s nspname %c ", switch_include_exclude ? "" : " OR",
/* any meta-characters? */
strpbrk(this_obj_name->name, "([{\\.?+") == NULL ? '=' : '~');
appendStringLiteralAH(query, this_obj_name->name, g_fout);
if (this_obj_name->next && this_obj_name->next->is_include == this_obj_name->is_include)
switch_include_exclude = false;
else
{
switch_include_exclude = true;
/* Add the joiner if needed */
if (this_obj_name->next)
appendPQExpBuffer(query, "\n%s\n",
this_obj_name->next->is_include ? "UNION" : "EXCEPT");
}
}
/* Construct OID list of matching schemas */
if (schemaList)
{
int len;
res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
if (PQntuples(res) == 0)
expand_schema_name_patterns(&schema_include_patterns,
&schema_include_oids);
if (schema_include_oids.head == NULL)
{
write_msg(NULL, "No matching schemas were found\n");
exit_nicely();
}
for (i = 0, len = strlen(" "); i < PQntuples(res); i++)
len += strlen(PQgetvalue(res, i, 0)) + 1;
/*
* Need to use comma separators so it can be used by IN. zero is a
* dummy placeholder. Format is " oid oid oid ".
*/
matchingSchemas = malloc(len + 1);
strcpy(matchingSchemas, " ");
for (i = 0; i < PQntuples(res); i++)
{
strcat(matchingSchemas, PQgetvalue(res, i, 0));
strcat(matchingSchemas, " ");
}
}
expand_schema_name_patterns(&schema_exclude_patterns,
&schema_exclude_oids);
/* non-matching exclusion patterns aren't an error */
/* Check table selection flags */
resetPQExpBuffer(query);
switch_include_exclude = true;
for (this_obj_name = tableList; this_obj_name; this_obj_name = this_obj_name->next)
/* Expand table selection patterns into OID lists */
if (table_include_patterns.head != NULL)
{
if (switch_include_exclude)
{
/* Special case for when -T is the first argument */
if (this_obj_name == tableList && !this_obj_name->is_include && !strlen(query->data))
appendPQExpBuffer(query,
"SELECT pg_class.oid FROM pg_catalog.pg_class, pg_catalog.pg_namespace "
"WHERE relkind='r' AND "
" relnamespace = pg_namespace.oid AND "
" nspname NOT LIKE 'pg_%%' AND "
" nspname != 'information_schema' EXCEPT\n");
appendPQExpBuffer(query, "SELECT oid FROM pg_catalog.pg_class WHERE relkind='r' AND (");
}
appendPQExpBuffer(query, "%srelname %c ", switch_include_exclude ? "" : " OR ",
/* any meta-characters? */
strpbrk(this_obj_name->name, "([{\\.?+") == NULL ? '=' : '~');
appendStringLiteralAH(query, this_obj_name->name, g_fout);
if (this_obj_name->next && this_obj_name->next->is_include == this_obj_name->is_include)
switch_include_exclude = false;
else
{
switch_include_exclude = true;
appendPQExpBuffer(query, ")");
/* Add the joiner if needed */
if (this_obj_name->next)
appendPQExpBuffer(query, "\n%s\n", this_obj_name->next->is_include ?
"UNION" : "EXCEPT");
}
}
/* Construct OID list of matching tables */
if (tableList)
{
int len;
/* Restrict by schema? */
if (matchingSchemas != NULL)
{
char *matchingSchemas_commas = strdup(matchingSchemas),
*p;
/* Construct "IN" SQL string by adding commas, " oid, oid, oid " */
for (p = matchingSchemas_commas; *p; p++)
{
/* No commas for first/last characters */
if (*p == ' ' && p != matchingSchemas_commas && *(p + 1))
*p = ',';
}
appendPQExpBuffer(query,
"\nINTERSECT\nSELECT oid FROM pg_catalog.pg_class WHERE relkind='r' AND relnamespace IN (%s)\n",
matchingSchemas_commas);
}
res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
if (PQntuples(res) == 0)
expand_table_name_patterns(&table_include_patterns,
&table_include_oids);
if (table_include_oids.head == NULL)
{
write_msg(NULL, "No matching tables were found\n");
exit_nicely();
}
for (i = 0, len = strlen(" "); i < PQntuples(res); i++)
len += strlen(PQgetvalue(res, i, 0)) + 1;
matchingTables = malloc(len + 1);
strcpy(matchingTables, " ");
for (i = 0; i < PQntuples(res); i++)
{
strcat(matchingTables, PQgetvalue(res, i, 0));
strcat(matchingTables, " ");
}
}
expand_table_name_patterns(&table_exclude_patterns,
&table_exclude_oids);
/* non-matching exclusion patterns aren't an error */
destroyPQExpBuffer(query);
/*
* Dumping blobs is now default unless we saw an inclusion switch or -s
* ... but even if we did see one of these, -b turns it back on.
*/
if (include_everything && !schemaOnly)
outputBlobs = true;
/*
* Now scan the database and create DumpableObject structs for all the
@ -824,7 +680,7 @@ main(int argc, char **argv)
dumpStdStrings(g_fout);
/* The database item is always next, unless we don't want it at all */
if (!dataOnly && matchingTables == NULL && matchingSchemas == NULL)
if (include_everything && !dataOnly)
dumpDatabase(g_fout);
/* Now the rearrangeable objects. */
@ -884,28 +740,28 @@ help(const char *progname)
printf(_("\nOptions controlling the output content:\n"));
printf(_(" -a, --data-only dump only the data, not the schema\n"));
printf(_(" -b, --blobs include large objects in dump\n"));
printf(_(" -c, --clean clean (drop) schema prior to create\n"));
printf(_(" -C, --create include commands to create database in dump\n"));
printf(_(" -d, --inserts dump data as INSERT commands, rather than COPY\n"));
printf(_(" -D, --column-inserts dump data as INSERT commands with column names\n"));
printf(_(" -E, --encoding=ENCODING dump the data in encoding ENCODING\n"));
printf(_(" -n, --schema=SCHEMA dump the named schema only\n"));
printf(_(" -N, --exclude-schema=SCHEMA\n"
" do NOT dump the named schema\n"));
printf(_(" -n, --schema=SCHEMA dump the named schema(s) only\n"));
printf(_(" -N, --exclude-schema=SCHEMA do NOT dump the named schema(s)\n"));
printf(_(" -o, --oids include OIDs in dump\n"));
printf(_(" -O, --no-owner skip restoration of object ownership\n"
" in plain text format\n"));
printf(_(" -s, --schema-only dump only the schema, no data\n"));
printf(_(" -S, --superuser=NAME specify the superuser user name to use in\n"
" plain text format\n"));
printf(_(" -t, --table=TABLE dump the named table only\n"));
printf(_(" -T, --exclude-table=TABLE do NOT dump the named table\n"));
printf(_(" -t, --table=TABLE dump the named table(s) only\n"));
printf(_(" -T, --exclude-table=TABLE do NOT dump the named table(s)\n"));
printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
printf(_(" --disable-triggers disable triggers during data-only restore\n"));
printf(_(" --use-set-session-authorization\n"
" use SESSION AUTHORIZATION commands instead of\n"
" OWNER TO commands\n"));
" ALTER OWNER commands to set ownership\n"));
printf(_("\nConnection options:\n"));
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
@ -927,6 +783,106 @@ exit_nicely(void)
exit(1);
}
/*
* Find the OIDs of all schemas matching the given list of patterns,
* and append them to the given OID list.
*/
static void
expand_schema_name_patterns(SimpleStringList *patterns, SimpleOidList *oids)
{
PQExpBuffer query;
PGresult *res;
SimpleStringListCell *cell;
int i;
if (patterns->head == NULL)
return; /* nothing to do */
if (g_fout->remoteVersion < 70300)
{
write_msg(NULL, "server version must be at least 7.3 to use schema selection switches\n");
exit_nicely();
}
query = createPQExpBuffer();
/*
* We use UNION ALL rather than UNION; this might sometimes result in
* duplicate entries in the OID list, but we don't care.
*/
for (cell = patterns->head; cell; cell = cell->next)
{
if (cell != patterns->head)
appendPQExpBuffer(query, "UNION ALL\n");
appendPQExpBuffer(query,
"SELECT oid FROM pg_catalog.pg_namespace n\n");
processSQLNamePattern(g_conn, query, cell->val, false, false,
NULL, "n.nspname", NULL,
NULL);
}
res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
for (i = 0; i < PQntuples(res); i++)
{
simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
}
PQclear(res);
destroyPQExpBuffer(query);
}
/*
* Find the OIDs of all tables matching the given list of patterns,
* and append them to the given OID list.
*/
static void
expand_table_name_patterns(SimpleStringList *patterns, SimpleOidList *oids)
{
PQExpBuffer query;
PGresult *res;
SimpleStringListCell *cell;
int i;
if (patterns->head == NULL)
return; /* nothing to do */
query = createPQExpBuffer();
/*
* We use UNION ALL rather than UNION; this might sometimes result in
* duplicate entries in the OID list, but we don't care.
*/
for (cell = patterns->head; cell; cell = cell->next)
{
if (cell != patterns->head)
appendPQExpBuffer(query, "UNION ALL\n");
appendPQExpBuffer(query,
"SELECT c.oid"
"\nFROM pg_catalog.pg_class c"
"\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
"\nWHERE c.relkind in ('%c', '%c', '%c')\n",
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
processSQLNamePattern(g_conn, query, cell->val, true, false,
"n.nspname", "c.relname", NULL,
"pg_catalog.pg_table_is_visible(c.oid)");
}
res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
for (i = 0; i < PQntuples(res); i++)
{
simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
}
PQclear(res);
destroyPQExpBuffer(query);
}
/*
* selectDumpableNamespace: policy-setting subroutine
* Mark a namespace as to be dumped or not
@ -936,27 +892,26 @@ selectDumpableNamespace(NamespaceInfo *nsinfo)
{
/*
* If specific tables are being dumped, do not dump any complete
* namespaces. If specific namespaces are being dumped, dump just those
* namespaces. If specific namespaces are being dumped, dump just those
* namespaces. Otherwise, dump all non-system namespaces.
*/
nsinfo->dobj.dump = false;
if (matchingTables != NULL)
/* false */ ;
else if (matchingSchemas != NULL)
{
char *search_oid = malloc(20);
sprintf(search_oid, " %d ", nsinfo->dobj.catId.oid);
if (strstr(matchingSchemas, search_oid) != NULL)
nsinfo->dobj.dump = true;
free(search_oid);
}
/* The server prevents users from creating pg_ schemas */
else if (strncmp(nsinfo->dobj.name, "pg_", 3) != 0 &&
strcmp(nsinfo->dobj.name, "information_schema") != 0)
if (table_include_oids.head != NULL)
nsinfo->dobj.dump = false;
else if (schema_include_oids.head != NULL)
nsinfo->dobj.dump = simple_oid_list_member(&schema_include_oids,
nsinfo->dobj.catId.oid);
else if (strncmp(nsinfo->dobj.name, "pg_", 3) == 0 ||
strcmp(nsinfo->dobj.name, "information_schema") == 0)
nsinfo->dobj.dump = false;
else
nsinfo->dobj.dump = true;
/*
* In any case, a namespace can be excluded by an exclusion switch
*/
if (nsinfo->dobj.dump &&
simple_oid_list_member(&schema_exclude_oids,
nsinfo->dobj.catId.oid))
nsinfo->dobj.dump = false;
}
/*
@ -967,27 +922,21 @@ static void
selectDumpableTable(TableInfo *tbinfo)
{
/*
* Always dump if dumping parent namespace; else, if a particular
* tablename has been specified, dump matching table name; else, do not
* dump.
* If specific tables are being dumped, dump just those tables;
* else, dump according to the parent namespace's dump flag.
*/
tbinfo->dobj.dump = false;
if (matchingTables == NULL)
{
if (tbinfo->dobj.namespace->dobj.dump)
tbinfo->dobj.dump = true;
}
if (table_include_oids.head != NULL)
tbinfo->dobj.dump = simple_oid_list_member(&table_include_oids,
tbinfo->dobj.catId.oid);
else
{
char *search_oid = malloc(20);
sprintf(search_oid, " %d ", tbinfo->dobj.catId.oid);
if (strstr(matchingTables, search_oid) != NULL)
tbinfo->dobj.dump = true;
free(search_oid);
}
tbinfo->dobj.dump = tbinfo->dobj.namespace->dobj.dump;
/*
* In any case, a table can be excluded by an exclusion switch
*/
if (tbinfo->dobj.dump &&
simple_oid_list_member(&table_exclude_oids,
tbinfo->dobj.catId.oid))
tbinfo->dobj.dump = false;
}
/*
@ -5596,7 +5545,7 @@ dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
static bool
shouldDumpProcLangs(void)
{
if (matchingTables != NULL || matchingSchemas != NULL)
if (!include_everything)
return false;
/* And they're schema not data */
if (dataOnly)

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.129 2006/08/21 00:57:25 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.130 2006/10/09 23:36:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -41,6 +41,35 @@ typedef struct
typedef int DumpId;
/*
* Data structures for simple lists of OIDs and strings. The support for
* these is very primitive compared to the backend's List facilities, but
* it's all we need in pg_dump.
*/
typedef struct SimpleOidListCell
{
struct SimpleOidListCell *next;
Oid val;
} SimpleOidListCell;
typedef struct SimpleOidList
{
SimpleOidListCell *head;
SimpleOidListCell *tail;
} SimpleOidList;
typedef struct SimpleStringListCell
{
struct SimpleStringListCell *next;
char val[1]; /* VARIABLE LENGTH FIELD */
} SimpleStringListCell;
typedef struct SimpleStringList
{
SimpleStringListCell *head;
SimpleStringListCell *tail;
} SimpleStringList;
/*
* The data structures used to store system catalog information. Every
@ -364,6 +393,16 @@ extern TypeInfo *findTypeByOid(Oid oid);
extern FuncInfo *findFuncByOid(Oid oid);
extern OprInfo *findOprByOid(Oid oid);
extern void simple_oid_list_append(SimpleOidList *list, Oid val);
extern void simple_string_list_append(SimpleStringList *list, const char *val);
extern bool simple_oid_list_member(SimpleOidList *list, Oid val);
extern bool simple_string_list_member(SimpleStringList *list, const char *val);
extern char *pg_strdup(const char *string);
extern void *pg_malloc(size_t size);
extern void *pg_calloc(size_t nmemb, size_t size);
extern void *pg_realloc(void *ptr, size_t size);
extern void check_conn_and_db(void);
extern void exit_nicely(void);