aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-10-09 23:36:59 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-10-09 23:36:59 +0000
commit24e97528631e7e810ce61fc0f5fbcaca0c001c4c (patch)
treea5e9bfd5000f583ea12e72d12a7e00a856254b88
parent77d2b1b625c7decd7a25ec865bced3b927de6d4b (diff)
downloadpostgresql-24e97528631e7e810ce61fc0f5fbcaca0c001c4c.tar.gz
postgresql-24e97528631e7e810ce61fc0f5fbcaca0c001c4c.zip
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.
-rw-r--r--doc/src/sgml/ref/pg_dump.sgml303
-rw-r--r--src/bin/pg_dump/common.c144
-rw-r--r--src/bin/pg_dump/pg_dump.c445
-rw-r--r--src/bin/pg_dump/pg_dump.h41
4 files changed, 553 insertions, 380 deletions
diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml
index deafd7c9a98..9aa4baf84e7 100644
--- a/doc/src/sgml/ref/pg_dump.sgml
+++ b/doc/src/sgml/ref/pg_dump.sgml
@@ -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>
@@ -127,6 +127,19 @@ PostgreSQL documentation
</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>
<listitem>
@@ -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</>.
- </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</>.
+ 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>
@@ -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.sql</userinput>
+</screen>
+ </para>
+
+ <para>
+ To reload such a script into a (freshly created) database named
+ <literal>newdb</>:
+
<screen>
-<prompt>$</prompt> <userinput>pg_dump mydb &gt; db.out</userinput>
+<prompt>$</prompt> <userinput>psql -d newdb -f db.sql</userinput>
</screen>
</para>
<para>
- To reload this database:
+ To dump a database into a custom-format archive file:
+
+<screen>
+<prompt>$</prompt> <userinput>pg_dump -Fc mydb &gt; db.dump</userinput>
+</screen>
+ </para>
+
+ <para>
+ To reload an archive file into a (freshly created) database named
+ <literal>newdb</>:
+
+<screen>
+<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>psql -d database -f db.out</userinput>
+<prompt>$</prompt> <userinput>pg_dump -n 'east*gsm' -n 'west*gsm' -N '*test*' mydb &gt; db.sql</userinput>
</screen>
</para>
<para>
- To dump a database called <literal>mydb</> to a file in custom format:
- file:
+ The same, using regular expression notation to consolidate the switches:
<screen>
-<prompt>$</prompt> <userinput>pg_dump -Fc mydb &gt; db.out</userinput>
+<prompt>$</prompt> <userinput>pg_dump -n '(east|west)*gsm' -N '*test*' mydb &gt; db.sql</userinput>
</screen>
</para>
<para>
- To reload this dump into an existing database called <literal>newdb</>:
+ To dump all database objects except for tables whose names begin with
+ <literal>ts_</literal>:
<screen>
-<prompt>$</prompt> <userinput>pg_restore -d newdb db.out</userinput>
+<prompt>$</prompt> <userinput>pg_dump -T 'ts_*' mydb &gt; db.sql</userinput>
</screen>
</para>
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index f4b4a1e5bbb..44ccb2eab1f 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -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;
+}
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 5cf0b76b50f..c4df03083e1 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -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 */
-
- 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;
+ case 'n': /* include schema(s) */
+ simple_string_list_append(&schema_include_patterns, optarg);
+ include_everything = false;
+ break;
- /* 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"));
@@ -928,66 +784,159 @@ exit_nicely(void)
}
/*
- * selectDumpableNamespace: policy-setting subroutine
- * Mark a namespace as to be dumped or not
+ * Find the OIDs of all schemas matching the given list of patterns,
+ * and append them to the given OID list.
*/
static void
-selectDumpableNamespace(NamespaceInfo *nsinfo)
+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();
+
/*
- * If specific tables are being dumped, do not dump any complete
- * namespaces. If specific namespaces are being dumped, dump just those
- * namespaces. Otherwise, dump all non-system namespaces.
+ * We use UNION ALL rather than UNION; this might sometimes result in
+ * duplicate entries in the OID list, but we don't care.
*/
- nsinfo->dobj.dump = false;
- if (matchingTables != NULL)
- /* false */ ;
- else if (matchingSchemas != NULL)
+ for (cell = patterns->head; cell; cell = cell->next)
{
- char *search_oid = malloc(20);
+ 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);
+ }
- sprintf(search_oid, " %d ", nsinfo->dobj.catId.oid);
- if (strstr(matchingSchemas, search_oid) != NULL)
- nsinfo->dobj.dump = true;
+ res = PQexec(g_conn, query->data);
+ check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
- free(search_oid);
+ for (i = 0; i < PQntuples(res); i++)
+ {
+ simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
}
- /* The server prevents users from creating pg_ schemas */
- else if (strncmp(nsinfo->dobj.name, "pg_", 3) != 0 &&
- strcmp(nsinfo->dobj.name, "information_schema") != 0)
- nsinfo->dobj.dump = true;
+
+ PQclear(res);
+ destroyPQExpBuffer(query);
}
/*
- * selectDumpableTable: policy-setting subroutine
- * Mark a table as to be dumped or not
+ * Find the OIDs of all tables matching the given list of patterns,
+ * and append them to the given OID list.
*/
static void
-selectDumpableTable(TableInfo *tbinfo)
+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();
+
/*
- * Always dump if dumping parent namespace; else, if a particular
- * tablename has been specified, dump matching table name; else, do not
- * dump.
+ * We use UNION ALL rather than UNION; this might sometimes result in
+ * duplicate entries in the OID list, but we don't care.
*/
- tbinfo->dobj.dump = false;
- if (matchingTables == NULL)
+ for (cell = patterns->head; cell; cell = cell->next)
{
- if (tbinfo->dobj.namespace->dobj.dump)
- tbinfo->dobj.dump = true;
+ 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)");
}
- else
- {
- char *search_oid = malloc(20);
- sprintf(search_oid, " %d ", tbinfo->dobj.catId.oid);
- if (strstr(matchingTables, search_oid) != NULL)
- tbinfo->dobj.dump = true;
+ res = PQexec(g_conn, query->data);
+ check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
- free(search_oid);
+ 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
+ */
+static void
+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. Otherwise, dump all non-system namespaces.
+ */
+ 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;
+}
+
+/*
+ * selectDumpableTable: policy-setting subroutine
+ * Mark a table as to be dumped or not
+ */
+static void
+selectDumpableTable(TableInfo *tbinfo)
+{
+ /*
+ * If specific tables are being dumped, dump just those tables;
+ * else, dump according to the parent namespace's dump flag.
+ */
+ if (table_include_oids.head != NULL)
+ tbinfo->dobj.dump = simple_oid_list_member(&table_include_oids,
+ tbinfo->dobj.catId.oid);
+ else
+ 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)
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 65f5e84c416..dad62f96065 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -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);