Reimplement pg_dumpall in C. Currently no change in functionality,

except that it's more robust, reconnects less often, and is NLS'ed.
This commit is contained in:
Peter Eisentraut 2002-08-27 18:57:26 +00:00
parent 6deb649cd3
commit 7af5ea736f
13 changed files with 949 additions and 516 deletions

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.48 2002/08/18 09:36:25 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.49 2002/08/27 18:57:26 petere Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
@ -112,13 +112,13 @@ PostgreSQL documentation
does not block other users accessing the database (readers or does not block other users accessing the database (readers or
writers). writers).
</para> </para>
</refsect1>
<refsect2 id="pg-dump-options"> <refsect1 id="pg-dump-options">
<title>Options</title> <title>Options</title>
<para> <para>
<command>pg_dump</command> accepts the following command The following command-line options are used to control the output format.
line arguments. (Long option forms are only available on some platforms.)
<variablelist> <variablelist>
<varlistentry> <varlistentry>
@ -408,7 +408,9 @@ PostgreSQL documentation
<term><option>--verbose</></term> <term><option>--verbose</></term>
<listitem> <listitem>
<para> <para>
Specifies verbose mode. Specifies verbose mode. This will cause
<application>pg_dump</application> to print progress messages
to standard error.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -499,13 +501,11 @@ PostgreSQL documentation
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
</para> </para>
<para> <para>
<command>pg_dump</command> also accepts The following command-line options control the database connection parameters.
the following command line arguments for connection parameters:
<variablelist> <variablelist>
<varlistentry> <varlistentry>
@ -555,8 +555,10 @@ PostgreSQL documentation
</varlistentry> </varlistentry>
</variablelist> </variablelist>
</para> </para>
</refsect2>
<para>
Long option forms are only available on some platforms.
</para>
</refsect1> </refsect1>
<refsect1> <refsect1>

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dumpall.sgml,v 1.31 2002/08/27 03:55:17 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dumpall.sgml,v 1.32 2002/08/27 18:57:26 petere Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
@ -12,18 +12,13 @@ PostgreSQL documentation
<refnamediv> <refnamediv>
<refname>pg_dumpall</refname> <refname>pg_dumpall</refname>
<refpurpose>extract all <productname>PostgreSQL</productname> databases into a script file</refpurpose> <refpurpose>extract a <productname>PostgreSQL</productname> database cluster into a script file</refpurpose>
</refnamediv> </refnamediv>
<refsynopsisdiv> <refsynopsisdiv>
<cmdsynopsis> <cmdsynopsis>
<command>pg_dumpall</command> <command>pg_dumpall</command>
<group><arg>-c</arg><arg>--clean</arg></group> <arg rep="repeat"><replaceable>options</replaceable></arg>
<group><arg>-g</arg><arg>--globals-only</arg></group>
<arg>-h <replaceable>host</replaceable></arg>
<arg>-p <replaceable>port</replaceable></arg>
<arg>-U <replaceable>username</replaceable></arg>
<arg>-W</arg>
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -66,22 +61,13 @@ PostgreSQL documentation
The SQL script will be written to the standard output. Shell The SQL script will be written to the standard output. Shell
operators should be used to redirect it into a file. operators should be used to redirect it into a file.
</para> </para>
<para>
<application>pg_dumpall</application> will need to connect several times to the
<productname>PostgreSQL</productname> server, asking for the password each
time. It will probably be very convenient to have a PGPASSWORDFILE in that case.
</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
<title>Options</title> <title>Options</title>
<para> <para>
<application>pg_dumpall</application> accepts the following The following command-line options are used to control the output format.
command line arguments:
<variablelist> <variablelist>
<varlistentry> <varlistentry>
@ -96,6 +82,35 @@ PostgreSQL documentation
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>-d</option></term>
<term><option>--inserts</option></term>
<listitem>
<para>
Dump data as <command>INSERT</command> commands (rather
than <command>COPY</command>). This will make restoration very
slow, but it makes the output more portable to other RDBMS
packages.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-D</option></term>
<term><option>--column-inserts</option></term>
<term><option>--attribute-inserts</option></term>
<listitem>
<para>
Dump data as <command>INSERT</command> commands with explicit
column names (<literal>INSERT INTO
<replaceable>table</replaceable>
(<replaceable>column</replaceable>, ...) VALUES
...</literal>). This will make restoration very slow,
but it is necessary if you desire to rearrange column ordering.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term>-g, --globals-only</term> <term>-g, --globals-only</term>
<listitem> <listitem>
@ -105,6 +120,55 @@ PostgreSQL documentation
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>-i</></term>
<term><option>--ignore-version</></term>
<listitem>
<para>
Ignore version mismatch between
<application>pg_dumpall</application> and the database server.
Since <application>pg_dumpall</application> knows a great deal
about system catalogs, any given version of
<application>pg_dumpall</application> is only intended to work
with the corresponding release of the database server. Use
this option if you need to override the version check (and if
<application>pg_dumpall</application> then fails, don't say
you weren't warned).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-o</></term>
<term><option>--oids</></term>
<listitem>
<para>
Dump object identifiers (<acronym>OID</acronym>s) for every
table. Use this option if your application references the OID
columns in some way (e.g., in a foreign key constraint).
Otherwise, this option should not be used.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-v</></term>
<term><option>--verbose</></term>
<listitem>
<para>
Specifies verbose mode. This will cause
<application>pg_dumpall</application> to print progress
messages to standard error.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
The following command-line options control the database connection parameters.
<variablelist>
<varlistentry> <varlistentry>
<term>-h <replaceable>host</replaceable></term> <term>-h <replaceable>host</replaceable></term>
<listitem> <listitem>
@ -151,12 +215,7 @@ PostgreSQL documentation
</para> </para>
<para> <para>
Any other command line parameters are passed to the underlying Long options are only available on some platforms.
<xref linkend="app-pgdump">
calls. This is useful to control some aspects of the output
format, but some options such as <option>-f</option>,
<option>-F</option>, <option>-t</option>, and <replaceable
class="parameter">dbname</replaceable> should be avoided.
</para> </para>
</refsect1> </refsect1>
@ -180,6 +239,26 @@ PostgreSQL documentation
</refsect1> </refsect1>
<refsect1>
<title>Notes</title>
<para>
Since <application>pg_dumpall</application> calls
<application>pg_dump</application> internally, some diagnostic
messages will refer to <application>pg_dump</application>.
</para>
<para>
<application>pg_dumpall</application> will need to connect several
times to the <productname>PostgreSQL</productname> server. If password
authentication is configured, it will ask for a password each time. In
that case it would be convenient to set up a password file.
</para>
<comment>But where is that password file documented?</comment>
</refsect1>
<refsect1 id="app-pg-dumpall-ex"> <refsect1 id="app-pg-dumpall-ex">
<title>Examples</title> <title>Examples</title>
<para> <para>

View File

@ -5,7 +5,7 @@
# Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group # Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California # Portions Copyright (c) 1994, Regents of the University of California
# #
# $Header: /cvsroot/pgsql/src/bin/pg_dump/Makefile,v 1.37 2002/08/18 09:36:25 petere Exp $ # $Header: /cvsroot/pgsql/src/bin/pg_dump/Makefile,v 1.38 2002/08/27 18:57:26 petere Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -14,11 +14,12 @@ top_builddir = ../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
OBJS= pg_backup_archiver.o pg_backup_db.o pg_backup_custom.o \ OBJS= pg_backup_archiver.o pg_backup_db.o pg_backup_custom.o \
pg_backup_files.o pg_backup_null.o pg_backup_tar.o sprompt.o pg_backup_files.o pg_backup_null.o pg_backup_tar.o \
sprompt.o dumputils.o
EXTRA_OBJS = $(top_builddir)/src/backend/parser/keywords.o EXTRA_OBJS = $(top_builddir)/src/backend/parser/keywords.o
override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) -DBINDIR=\"$(bindir)\"
all: submake-libpq submake-libpgport submake-backend pg_dump pg_restore pg_dumpall all: submake-libpq submake-libpgport submake-backend pg_dump pg_restore pg_dumpall
@ -29,12 +30,8 @@ pg_dump: pg_dump.o common.o $(OBJS) $(libpq_builddir)/libpq.a
pg_restore: pg_restore.o $(OBJS) $(libpq_builddir)/libpq.a pg_restore: pg_restore.o $(OBJS) $(libpq_builddir)/libpq.a
$(CC) $(CFLAGS) pg_restore.o $(OBJS) $(EXTRA_OBJS) $(libpq) $(LDFLAGS) $(LIBS) -o $@ $(CC) $(CFLAGS) pg_restore.o $(OBJS) $(EXTRA_OBJS) $(libpq) $(LDFLAGS) $(LIBS) -o $@
pg_dumpall: pg_dumpall.sh pg_dumpall: pg_dumpall.o $(libpq_builddir)/libpq.a
sed -e 's,@VERSION@,$(VERSION),g' \ $(CC) $(CFLAGS) pg_dumpall.o dumputils.o sprompt.o $(EXTRA_OBJS) $(libpq) $(LDFLAGS) $(LIBS) -o $@
-e 's,@MULTIBYTE@,$(MULTIBYTE),g' \
-e 's,@bindir@,$(bindir),g' \
$< >$@
chmod a+x $@
.PHONY: submake-backend .PHONY: submake-backend
submake-backend: submake-backend:
@ -44,13 +41,13 @@ submake-backend:
install: all installdirs install: all installdirs
$(INSTALL_PROGRAM) pg_dump$(X) $(DESTDIR)$(bindir)/pg_dump$(X) $(INSTALL_PROGRAM) pg_dump$(X) $(DESTDIR)$(bindir)/pg_dump$(X)
$(INSTALL_PROGRAM) pg_restore$(X) $(DESTDIR)$(bindir)/pg_restore$(X) $(INSTALL_PROGRAM) pg_restore$(X) $(DESTDIR)$(bindir)/pg_restore$(X)
$(INSTALL_SCRIPT) pg_dumpall $(DESTDIR)$(bindir)/pg_dumpall $(INSTALL_PROGRAM) pg_dumpall$(X) $(DESTDIR)$(bindir)/pg_dumpall$(X)
installdirs: installdirs:
$(mkinstalldirs) $(DESTDIR)$(bindir) $(mkinstalldirs) $(DESTDIR)$(bindir)
uninstall: uninstall:
rm -f $(addprefix $(DESTDIR)$(bindir)/, pg_dump$(X) pg_restore$(X) pg_dumpall) rm -f $(addprefix $(DESTDIR)$(bindir)/, pg_dump$(X) pg_restore$(X) pg_dumpall$(X))
clean distclean maintainer-clean: clean distclean maintainer-clean:
rm -f pg_dump$(X) pg_restore$(X) $(OBJS) pg_dump.o common.o pg_restore.o pg_dumpall rm -f pg_dump$(X) pg_restore$(X) pg_dumpall$(X) $(OBJS) pg_dump.o common.o pg_restore.o pg_dumpall.o

131
src/bin/pg_dump/dumputils.c Normal file
View File

@ -0,0 +1,131 @@
/*-------------------------------------------------------------------------
*
* Utility routines for SQL dumping
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v 1.1 2002/08/27 18:57:26 petere Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include "dumputils.h"
#include "parser/keywords.h"
/*
* Quotes input string if it's not a legitimate SQL identifier as-is.
*
* Note that the returned string must be used before calling fmtId again,
* since we re-use the same return buffer each time. Non-reentrant but
* avoids memory leakage.
*/
const char *
fmtId(const char *rawid)
{
static PQExpBuffer id_return = NULL;
const char *cp;
bool need_quotes = false;
if (id_return) /* first time through? */
resetPQExpBuffer(id_return);
else
id_return = createPQExpBuffer();
/* These checks need to match the identifier production in scan.l.
* Don't use islower() etc. */
if (ScanKeywordLookup(rawid))
need_quotes = true;
/* slightly different rules for first character */
else if (!((rawid[0] >= 'a' && rawid[0] <= 'z') || rawid[0] == '_'))
need_quotes = true;
else
{
/* otherwise check the entire string */
for (cp = rawid; *cp; cp++)
{
if (!((*cp >= 'a' && *cp <= 'z')
|| (*cp >= '0' && *cp <= '9')
|| (*cp == '_')))
{
need_quotes = true;
break;
}
}
}
if (!need_quotes)
{
/* no quoting needed */
appendPQExpBufferStr(id_return, rawid);
}
else
{
appendPQExpBufferChar(id_return, '\"');
for (cp = rawid; *cp; cp++)
{
/*
* Did we find a double-quote in the string? Then make this a
* double double-quote per SQL99. Before, we put in a
* backslash/double-quote pair. - thomas 2000-08-05
*/
if (*cp == '\"')
appendPQExpBufferChar(id_return, '\"');
appendPQExpBufferChar(id_return, *cp);
}
appendPQExpBufferChar(id_return, '\"');
}
return id_return->data;
}
/*
* Convert a string value to an SQL string literal and append it to
* the given buffer.
*
* Special characters are escaped. Quote mark ' goes to '' per SQL
* standard, other stuff goes to \ sequences. If escapeAll is false,
* whitespace characters are not escaped (tabs, newlines, etc.). This
* is appropriate for dump file output.
*/
void
appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll)
{
appendPQExpBufferChar(buf, '\'');
while (*str)
{
char ch = *str++;
if (ch == '\\' || ch == '\'')
{
appendPQExpBufferChar(buf, ch); /* double these */
appendPQExpBufferChar(buf, ch);
}
else if ((unsigned char) ch < (unsigned char) ' ' &&
(escapeAll
|| (ch != '\t' && ch != '\n' && ch != '\v' && ch != '\f' && ch != '\r')
))
{
/*
* generate octal escape for control chars other than
* whitespace
*/
appendPQExpBufferChar(buf, '\\');
appendPQExpBufferChar(buf, ((ch >> 6) & 3) + '0');
appendPQExpBufferChar(buf, ((ch >> 3) & 7) + '0');
appendPQExpBufferChar(buf, (ch & 7) + '0');
}
else
appendPQExpBufferChar(buf, ch);
}
appendPQExpBufferChar(buf, '\'');
}

View File

@ -0,0 +1,26 @@
/*-------------------------------------------------------------------------
*
* Utility routines for SQL dumping
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $Header: /cvsroot/pgsql/src/bin/pg_dump/dumputils.h,v 1.1 2002/08/27 18:57:26 petere Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef DUMPUTILS_H
#define DUMPUTILS_H
#include "postgres_fe.h"
#include "pqexpbuffer.h"
extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
extern const char *fmtId(const char *identifier);
extern void appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll);
#endif DUMPUTILS_H

View File

@ -1,8 +1,8 @@
# $Header: /cvsroot/pgsql/src/bin/pg_dump/nls.mk,v 1.6 2001/12/21 22:30:49 petere Exp $ # $Header: /cvsroot/pgsql/src/bin/pg_dump/nls.mk,v 1.7 2002/08/27 18:57:26 petere Exp $
CATALOG_NAME := pg_dump CATALOG_NAME := pg_dump
AVAIL_LANGUAGES := cs de ru sv zh_CN zh_TW AVAIL_LANGUAGES := cs de ru sv zh_CN zh_TW
GETTEXT_FILES := pg_dump.c common.c pg_backup_archiver.c pg_backup_custom.c \ GETTEXT_FILES := pg_dump.c common.c pg_backup_archiver.c pg_backup_custom.c \
pg_backup_db.c pg_backup_files.c pg_backup_null.c \ pg_backup_db.c pg_backup_files.c pg_backup_null.c \
pg_backup_tar.c pg_restore.c pg_backup_tar.c pg_restore.c pg_dumpall.c
GETTEXT_TRIGGERS:= write_msg:2 die_horribly:3 exit_horribly:3 simple_prompt \ GETTEXT_TRIGGERS:= write_msg:2 die_horribly:3 exit_horribly:3 simple_prompt \
ExecuteSqlCommand:3 ahlog:3 ExecuteSqlCommand:3 ahlog:3 _

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.22 2002/08/20 17:54:44 petere Exp $ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.23 2002/08/27 18:57:26 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -118,11 +118,6 @@ extern void
exit_horribly(Archive *AH, const char *modulename, const char *fmt,...) exit_horribly(Archive *AH, const char *modulename, const char *fmt,...)
__attribute__((format(printf, 3, 4))); __attribute__((format(printf, 3, 4)));
extern char *simple_prompt(const char *prompt, int maxlen, bool echo);
extern const char *fmtId(const char *identifier);
extern void appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll);
/* Lets the archive know we have a DB connection to shutdown if it dies */ /* Lets the archive know we have a DB connection to shutdown if it dies */

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.55 2002/08/20 17:54:44 petere Exp $ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.56 2002/08/27 18:57:26 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -24,14 +24,14 @@
#include "pg_dump.h" #include "pg_dump.h"
#include "pg_backup_archiver.h" #include "pg_backup_archiver.h"
#include "pg_backup_db.h" #include "pg_backup_db.h"
#include "dumputils.h"
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> /* for dup */ #include <unistd.h>
#include "pqexpbuffer.h" #include "pqexpbuffer.h"
#include "libpq/libpq-fs.h" #include "libpq/libpq-fs.h"
#include "parser/keywords.h"
typedef enum _teReqs_ typedef enum _teReqs_
@ -2105,117 +2105,6 @@ _selectOutputSchema(ArchiveHandle *AH, const char *schemaName)
} }
/*
* Quotes input string if it's not a legitimate SQL identifier as-is.
*
* Note that the returned string must be used before calling fmtId again,
* since we re-use the same return buffer each time. Non-reentrant but
* avoids memory leakage.
*/
const char *
fmtId(const char *rawid)
{
static PQExpBuffer id_return = NULL;
const char *cp;
bool need_quotes = false;
if (id_return) /* first time through? */
resetPQExpBuffer(id_return);
else
id_return = createPQExpBuffer();
/* These checks need to match the identifier production in scan.l.
* Don't use islower() etc. */
if (ScanKeywordLookup(rawid))
need_quotes = true;
/* slightly different rules for first character */
else if (!((rawid[0] >= 'a' && rawid[0] <= 'z') || rawid[0] == '_'))
need_quotes = true;
else
{
/* otherwise check the entire string */
for (cp = rawid; *cp; cp++)
{
if (!((*cp >= 'a' && *cp <= 'z')
|| (*cp >= '0' && *cp <= '9')
|| (*cp == '_')))
{
need_quotes = true;
break;
}
}
}
if (!need_quotes)
{
/* no quoting needed */
appendPQExpBufferStr(id_return, rawid);
}
else
{
appendPQExpBufferChar(id_return, '\"');
for (cp = rawid; *cp; cp++)
{
/*
* Did we find a double-quote in the string? Then make this a
* double double-quote per SQL99. Before, we put in a
* backslash/double-quote pair. - thomas 2000-08-05
*/
if (*cp == '\"')
appendPQExpBufferChar(id_return, '\"');
appendPQExpBufferChar(id_return, *cp);
}
appendPQExpBufferChar(id_return, '\"');
}
return id_return->data;
}
/*
* Convert a string value to an SQL string literal and append it to
* the given buffer.
*
* Special characters are escaped. Quote mark ' goes to '' per SQL
* standard, other stuff goes to \ sequences. If escapeAll is false,
* whitespace characters are not escaped (tabs, newlines, etc.). This
* is appropriate for dump file output.
*/
void
appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll)
{
appendPQExpBufferChar(buf, '\'');
while (*str)
{
char ch = *str++;
if (ch == '\\' || ch == '\'')
{
appendPQExpBufferChar(buf, ch); /* double these */
appendPQExpBufferChar(buf, ch);
}
else if ((unsigned char) ch < (unsigned char) ' ' &&
(escapeAll
|| (ch != '\t' && ch != '\n' && ch != '\v' && ch != '\f' && ch != '\r')
))
{
/*
* generate octal escape for control chars other than
* whitespace
*/
appendPQExpBufferChar(buf, '\\');
appendPQExpBufferChar(buf, ((ch >> 6) & 3) + '0');
appendPQExpBufferChar(buf, ((ch >> 3) & 7) + '0');
appendPQExpBufferChar(buf, (ch & 7) + '0');
}
else
appendPQExpBufferChar(buf, ch);
}
appendPQExpBufferChar(buf, '\'');
}
static int static int
_printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData) _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData)

View File

@ -5,7 +5,7 @@
* Implements the basic DB functions used by the archiver. * Implements the basic DB functions used by the archiver.
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.38 2002/08/20 17:54:44 petere Exp $ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.39 2002/08/27 18:57:26 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -13,6 +13,7 @@
#include "pg_backup.h" #include "pg_backup.h"
#include "pg_backup_archiver.h" #include "pg_backup_archiver.h"
#include "pg_backup_db.h" #include "pg_backup_db.h"
#include "dumputils.h"
#include <unistd.h> #include <unistd.h>
#include <ctype.h> #include <ctype.h>

View File

@ -22,7 +22,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.291 2002/08/22 21:35:50 tgl Exp $ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.292 2002/08/27 18:57:26 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -63,6 +63,7 @@
#include "pg_dump.h" #include "pg_dump.h"
#include "pg_backup.h" #include "pg_backup.h"
#include "pg_backup_archiver.h" #include "pg_backup_archiver.h"
#include "dumputils.h"
typedef struct _dumpContext typedef struct _dumpContext
@ -269,9 +270,9 @@ main(int argc, char **argv)
} }
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
while ((c = getopt_long(argc, argv, "abcCdDf:F:h:ioOp:RsS:t:uU:vWxX:zZ:V?", long_options, &optindex)) != -1) while ((c = getopt_long(argc, argv, "abcCdDf:F:h:ioOp:RsS:t:uU:vWxX:Z:", long_options, &optindex)) != -1)
#else #else
while ((c = getopt(argc, argv, "abcCdDf:F:h:ioOp:RsS:t:uU:vWxX:zZ:V?-")) != -1) while ((c = getopt(argc, argv, "abcCdDf:F:h:ioOp:RsS:t:uU:vWxX:Z:-")) != -1)
#endif #endif
{ {
@ -477,7 +478,7 @@ main(int argc, char **argv)
if (dumpData == true && oids == true) if (dumpData == true && oids == true)
{ {
write_msg(NULL, "INSERT (-d, -D) and OID (-o) options cannot be used together.\n"); write_msg(NULL, "INSERT (-d, -D) and OID (-o) options cannot be used together.\n");
write_msg(NULL, "(The INSERT command cannot set oids.)\n"); write_msg(NULL, "(The INSERT command cannot set OIDs.)\n");
exit(1); exit(1);
} }
@ -660,9 +661,7 @@ help(const char *progname)
" -h, --host=HOSTNAME database server host name\n" " -h, --host=HOSTNAME database server host name\n"
" -i, --ignore-version proceed even when server version mismatches\n" " -i, --ignore-version proceed even when server version mismatches\n"
" pg_dump version\n" " pg_dump version\n"
" -n, --no-quotes suppress most quotes around identifiers\n" " -o, --oids include OIDs in dump\n"
" -N, --quotes enable most quotes around identifiers\n"
" -o, --oids include oids in dump\n"
" -O, --no-owner do not output \\connect commands in plain\n" " -O, --no-owner do not output \\connect commands in plain\n"
" text format\n" " text format\n"
" -p, --port=PORT database server port number\n" " -p, --port=PORT database server port number\n"
@ -696,9 +695,7 @@ help(const char *progname)
" -h HOSTNAME database server host name\n" " -h HOSTNAME database server host name\n"
" -i proceed even when server version mismatches\n" " -i proceed even when server version mismatches\n"
" pg_dump version\n" " pg_dump version\n"
" -n suppress most quotes around identifiers\n" " -o include OIDs in dump\n"
" -N enable most quotes around identifiers\n"
" -o include oids in dump\n"
" -O do not output \\connect commands in plain\n" " -O do not output \\connect commands in plain\n"
" text format\n" " text format\n"
" -p PORT database server port number\n" " -p PORT database server port number\n"

View File

@ -0,0 +1,604 @@
/*-------------------------------------------------------------------------
*
* pg_dumpall
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.1 2002/08/27 18:57:26 petere Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include <unistd.h>
#ifdef ENABLE_NLS
#include <locale.h>
#endif
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#ifndef HAVE_STRDUP
#include "strdup.h"
#endif
#include <errno.h>
#include "dumputils.h"
#include "libpq-fe.h"
#include "pg_backup.h"
#include "pqexpbuffer.h"
#define _(x) gettext((x))
static char *progname;
static void help(void);
static void dumpUsers(PGconn *conn);
static void dumpGroups(PGconn *conn);
static void dumpCreateDB(PGconn *conn);
static void dumpDatabases(PGconn *conn);
static int runPgDump(const char *dbname);
static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
const char *pguser, bool require_password);
static PGresult *executeQuery(PGconn *conn, const char *query);
static char *findPgDump(const char *argv0);
char *pgdumploc;
PQExpBuffer pgdumpopts;
bool output_clean = false;
bool verbose = false;
int
main(int argc, char *argv[])
{
char *pghost = NULL;
char *pgport = NULL;
char *pguser = NULL;
bool force_password = false;
bool globals_only = false;
PGconn *conn;
int c;
#ifdef HAVE_GETOPT_LONG
static struct option long_options[] = {
{"clean", no_argument, NULL, 'c'},
{"inserts", no_argument, NULL, 'd'},
{"attribute-inserts", no_argument, NULL, 'D'},
{"column-inserts", no_argument, NULL, 'D'},
{"host", required_argument, NULL, 'h'},
{"ignore-version", no_argument, NULL, 'i'},
{"oids", no_argument, NULL, 'o'},
{"port", required_argument, NULL, 'p'},
{"password", no_argument, NULL, 'W'},
{"username", required_argument, NULL, 'U'},
{"verbose", no_argument, NULL, 'v'},
{NULL, 0, NULL, 0}
};
int optindex;
#endif
#ifdef ENABLE_NLS
setlocale(LC_ALL, "");
bindtextdomain("pg_dump", LOCALEDIR);
textdomain("pg_dump");
#endif
if (!strrchr(argv[0], '/'))
progname = argv[0];
else
progname = strrchr(argv[0], '/') + 1;
if (argc > 1)
{
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
{
help();
exit(0);
}
if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
{
puts("pg_dumpall (PostgreSQL) " PG_VERSION);
exit(0);
}
}
pgdumploc = findPgDump(argv[0]);
pgdumpopts = createPQExpBuffer();
#ifdef HAVE_GETOPT_LONG
while ((c = getopt_long(argc, argv, "cdDgh:iop:U:vW", long_options, &optindex)) != -1)
#else
while ((c = getopt(argc, argv, "cdDgh:iop:U:vW")) != -1)
#endif
{
switch (c)
{
case 'c':
output_clean = true;
appendPQExpBuffer(pgdumpopts, " -c");
break;
case 'd':
case 'D':
appendPQExpBuffer(pgdumpopts, " -%c", c);
break;
case 'g':
globals_only = true;
break;
case 'h':
pghost = optarg;
appendPQExpBuffer(pgdumpopts, " -h '%s'", pghost);
break;
case 'i':
case 'o':
appendPQExpBuffer(pgdumpopts, " -%c", c);
break;
case 'p':
pgport = optarg;
appendPQExpBuffer(pgdumpopts, " -p '%s'", pgport);
break;
case 'U':
pguser = optarg;
appendPQExpBuffer(pgdumpopts, " -U '%s'", pguser);
break;
case 'v':
verbose = true;
appendPQExpBuffer(pgdumpopts, " -v");
break;
case 'W':
force_password = true;
appendPQExpBuffer(pgdumpopts, " -W");
break;
default:
fprintf(stderr, _("Try '%s --help' for more information.\n"), progname);
exit(1);
}
}
if (optind < argc)
{
fprintf(stderr,
_("%s: too many command line options (first is '%s')\n"
"Try '%s --help' for more information.\n"),
progname, argv[optind], progname);
exit(1);
}
conn = connectDatabase("template1", pghost, pgport, pguser, force_password);
printf("--\n");
printf("-- PostgreSQL database cluster dump\n");
printf("--\n\n");
printf("\\connect \"template1\"\n\n");
dumpUsers(conn);
dumpGroups(conn);
if (globals_only)
goto end;
dumpCreateDB(conn);
dumpDatabases(conn);
end:
PQfinish(conn);
exit(0);
}
static void
help(void)
{
printf(_("%s extracts a PostgreSQL database cluster into an SQL script file.\n\n"), progname);
printf(_("Usage:\n"));
printf(_(" %s [OPTIONS]\n\n"), progname);
printf(_("Options:\n"));
#ifdef HAVE_GETOPT_LONG
printf(_(" -c, --clean clean (drop) schema prior to create\n"));
printf(_(" -d, --inserts dump data as INSERT, rather than COPY, commands\n"));
printf(_(" -D, --column-inserts dump data as INSERT commands with column names\n"));
printf(_(" -g, --globals-only only dump global objects, no databases\n"));
printf(_(" -h, --host=HOSTNAME database server host name\n"));
printf(_(" -i, --ignore-version proceed even when server version mismatches\n"
" pg_dumpall version\n"));
printf(_(" -o, --oids include OIDs in dump\n"));
printf(_(" -p, --port=PORT database server port number\n"));
printf(_(" -U, --username=NAME connect as specified database user\n"));
printf(_(" -v, --verbose verbose mode\n"));
printf(_(" -W, --password force password prompt (should happen automatically)\n"));
#else /* not HAVE_GETOPT_LONG */
printf(_(" -c clean (drop) schema prior to create\n"));
printf(_(" -d dump data as INSERT, rather than COPY, commands\n"));
printf(_(" -D dump data as INSERT commands with column names\n"));
printf(_(" -g only dump global objects, no databases\n"));
printf(_(" -h HOSTNAME database server host name\n"));
printf(_(" -i proceed even when server version mismatches\n"
" pg_dumpall version\n"));
printf(_(" -o include oids in dump\n"));
printf(_(" -p PORT database server port number\n"));
printf(_(" -U NAME connect as specified database user\n"));
printf(_(" -v verbose mode\n"));
printf(_(" -W force password prompt (should happen automatically)\n"));
#endif /* not HAVE_GETOPT_LONG */
printf(_("\nThe SQL script will be written to the standard output.\n\n"));
printf(_("Report bugs to <pgsql-bugs@postgresql.org>.\n"));
}
/*
* Dump users (but not the user created by initdb).
*/
static void
dumpUsers(PGconn *conn)
{
PGresult *res;
int i;
printf("DELETE FROM pg_shadow WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');\n\n");
res = executeQuery(conn,
"SELECT usename, usesysid, passwd, usecreatedb, usesuper, CAST(valuntil AS timestamp) "
"FROM pg_shadow "
"WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');");
for (i = 0; i < PQntuples(res); i++)
{
PQExpBuffer buf = createPQExpBuffer();
appendPQExpBuffer(buf, "CREATE USER %s WITH SYSID %s",
fmtId(PQgetvalue(res, i, 0)),
PQgetvalue(res, i, 1));
if (!PQgetisnull(res, i, 2))
{
appendPQExpBuffer(buf, " PASSWORD ");
appendStringLiteral(buf, PQgetvalue(res, i, 2), true);
}
if (strcmp(PQgetvalue(res, i, 3), "t")==0)
appendPQExpBuffer(buf, " CREATEDB");
else
appendPQExpBuffer(buf, " NOCREATEDB");
if (strcmp(PQgetvalue(res, i, 4), "t")==0)
appendPQExpBuffer(buf, " CREATEUSER");
else
appendPQExpBuffer(buf, " NOCREATEUSER");
if (!PQgetisnull(res, i, 5))
appendPQExpBuffer(buf, " VALID UNTIL '%s'", PQgetvalue(res, i, 5));
appendPQExpBuffer(buf, ";\n");
printf("%s", buf->data);
destroyPQExpBuffer(buf);
}
PQclear(res);
printf("\n\n");
}
/*
* Dump groups.
*/
static void
dumpGroups(PGconn *conn)
{
PGresult *res;
int i;
printf("DELETE FROM pg_group;\n\n");
res = executeQuery(conn, "SELECT groname, grosysid, grolist FROM pg_group;");
for (i = 0; i < PQntuples(res); i++)
{
PQExpBuffer buf = createPQExpBuffer();
char *val;
char *tok;
appendPQExpBuffer(buf, "CREATE GROUP %s WITH SYSID %s;\n",
fmtId(PQgetvalue(res, i, 0)),
PQgetvalue(res, i, 1));
val = strdup(PQgetvalue(res, i, 2));
tok = strtok(val, ",{}");
do
{
PGresult *res2;
PQExpBuffer buf2 = createPQExpBuffer();
int j;
appendPQExpBuffer(buf2, "SELECT usename FROM pg_shadow WHERE usesysid = %s;", tok);
res2 = executeQuery(conn, buf2->data);
destroyPQExpBuffer(buf2);
for (j = 0; j < PQntuples(res2); j++)
{
appendPQExpBuffer(buf, "ALTER GROUP %s ", fmtId(PQgetvalue(res, i, 0)));
appendPQExpBuffer(buf, "ADD USER %s;\n", fmtId(PQgetvalue(res2, j, 0)));
}
PQclear(res2);
tok = strtok(NULL, "{},");
}
while (tok);
printf("%s", buf->data);
destroyPQExpBuffer(buf);
}
PQclear(res);
printf("\n\n");
}
/*
* Dump commands to create each database.
*
* To minimize the number of reconnections (and possibly ensuing
* password prompts) required by the output script, we emit all CREATE
* DATABASE commands during the initial phase of the script, and then
* run pg_dump for each database to dump the contents of that
* database. We skip databases marked not datallowconn, since we'd be
* unable to connect to them anyway (and besides, we don't want to
* dump template0).
*/
static void
dumpCreateDB(PGconn *conn)
{
PGresult *res;
int i;
/* Basically this query returns: dbname, dbowner, encoding, istemplate, dbpath */
res = executeQuery(conn, "SELECT datname, coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), pg_encoding_to_char(d.encoding), datistemplate, datpath FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) WHERE datallowconn ORDER BY 1;");
for (i = 0; i < PQntuples(res); i++)
{
PQExpBuffer buf = createPQExpBuffer();
char *dbname = PQgetvalue(res, i, 0);
char *dbowner = PQgetvalue(res, i, 1);
char *dbencoding = PQgetvalue(res, i, 2);
char *dbistemplate = PQgetvalue(res, i, 3);
char *dbpath = PQgetvalue(res, i, 4);
if (strcmp(dbname, "template1")==0)
continue;
if (output_clean)
appendPQExpBuffer(buf, "DROP DATABASE %s\n;", fmtId(dbname));
appendPQExpBuffer(buf, "CREATE DATABASE %s", fmtId(dbname));
appendPQExpBuffer(buf, " WITH OWNER = %s TEMPLATE = template0", fmtId(dbowner));
if (strcmp(dbpath, "")!=0)
{
appendPQExpBuffer(buf, " LOCATION = ");
appendStringLiteral(buf, dbpath, true);
}
appendPQExpBuffer(buf, " ENCODING = ");
appendStringLiteral(buf, dbencoding, true);
appendPQExpBuffer(buf, ";\n");
if (strcmp(dbistemplate, "t")==0)
{
appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = ");
appendStringLiteral(buf, dbname, true);
appendPQExpBuffer(buf, ";\n");
}
printf("%s", buf->data);
destroyPQExpBuffer(buf);
}
PQclear(res);
printf("\n\n");
}
/*
* Dump contents of databases.
*/
static void
dumpDatabases(PGconn *conn)
{
PGresult *res;
int i;
res = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;");
for (i = 0; i < PQntuples(res); i++)
{
int ret;
char *dbname = PQgetvalue(res, i, 0);
if (verbose)
fprintf(stderr, _("%s: dumping database \"%s\"...\n"), progname, dbname);
printf("\\connect %s\n", fmtId(dbname));
ret = runPgDump(dbname);
if (ret != 0)
{
fprintf(stderr, _("%s: pg_dump failed on %s, exiting\n"), progname, dbname);
exit(1);
}
}
PQclear(res);
}
/*
* Run pg_dump on dbname.
*/
static int
runPgDump(const char *dbname)
{
PQExpBuffer cmd = createPQExpBuffer();
int ret;
appendPQExpBuffer(cmd, "%s %s -X use-set-session-authorization -Fp %s",
pgdumploc, pgdumpopts->data, dbname);
if (verbose)
fprintf(stderr, _("%s: running %s\n"), progname, cmd->data);
ret = system(cmd->data);
destroyPQExpBuffer(cmd);
return ret;
}
/*
* Make a database connection with the given parameters. An
* interactive password prompt is automatically issued if required.
*/
static PGconn *
connectDatabase(const char *dbname, const char *pghost, const char *pgport,
const char *pguser, bool require_password)
{
PGconn *conn;
char *password = NULL;
bool need_pass = false;
if (require_password)
password = simple_prompt("Password: ", 100, false);
/*
* Start the connection. Loop until we have a password if requested
* by backend.
*/
do
{
need_pass = false;
conn = PQsetdbLogin(pghost, pgport, NULL, NULL, dbname, pguser, password);
if (!conn)
{
fprintf(stderr, _("%s: could not connection to database %s\n"),
progname, dbname);
exit(0);
}
if (PQstatus(conn) == CONNECTION_BAD &&
strcmp(PQerrorMessage(conn), "fe_sendauth: no password supplied\n") == 0 &&
!feof(stdin))
{
PQfinish(conn);
need_pass = true;
free(password);
password = NULL;
password = simple_prompt("Password: ", 100, false);
}
} while (need_pass);
if (password)
free(password);
/* check to see that the backend connection was successfully made */
if (PQstatus(conn) == CONNECTION_BAD)
{
fprintf(stderr, _("%s: could not connection to database %s: %s\n"),
progname, dbname, PQerrorMessage(conn));
exit(0);
}
return conn;
}
/*
* Run a query, return the results, exit program on failure.
*/
static PGresult *
executeQuery(PGconn *conn, const char *query)
{
PGresult *res;
res = PQexec(conn, query);
if (!res ||
PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, _("%s: query failed: %s"), progname, PQerrorMessage(conn));
fprintf(stderr, _("%s: query was: %s"), progname, query);
PQfinish(conn);
exit(1);
}
return res;
}
/*
* Find location of pg_dump executable.
*/
static char *
findPgDump(const char *argv0)
{
char *last;
PQExpBuffer cmd;
static char *result = NULL;
if (result)
return result;
cmd = createPQExpBuffer();
last = strrchr(argv0, '/');
if (!last)
appendPQExpBuffer(cmd, "pg_dump");
else
{
char *dir = strdup(argv0);
*(dir + (last - argv0)) = '\0';
appendPQExpBuffer(cmd, "%s/pg_dump", dir);
}
result = strdup(cmd->data);
appendPQExpBuffer(cmd, " -V >/dev/null 2>&1");
if (system(cmd->data)==0)
goto end;
result = BINDIR "/pg_dump";
if (system(BINDIR "/pg_dump -V >/dev/null 2>&1")==0)
goto end;
fprintf(stderr, _("%s: could not find pg_dump\n"
"Make sure it is in the path or in the same directory as %s.\n"),
progname, progname);
exit(1);
end:
destroyPQExpBuffer(cmd);
return result;
}

View File

@ -1,289 +0,0 @@
#! /bin/sh
# pg_dumpall
#
# Dumps all databases to standard output. It also dumps the "pg_shadow"
# and "pg_group" tables, which belong to the whole installation rather
# than any one individual database.
#
# $Header: /cvsroot/pgsql/src/bin/pg_dump/Attic/pg_dumpall.sh,v 1.21 2002/04/12 09:37:10 momjian Exp $
CMDNAME="`basename $0`"
# substituted at build
VERSION='@VERSION@'
MULTIBYTE='@MULTIBYTE@'
bindir='@bindir@'
# These handle spaces/tabs in identifiers
_IFS="$IFS"
NL="
"
#
# Find out where we're located
#
PGPATH=
if echo "$0" | grep '/' > /dev/null 2>&1 ; then
# explicit dir name given
PGPATH=`echo "$0" | sed 's,/[^/]*$,,'` # (dirname command is not portable)
else
# look for it in PATH ('which' command is not portable)
echo "$PATH" | sed "s/:/$NL/g" |
while :; do
IFS="$NL"
read dir || break
IFS="$_IFS"
# empty entry in path means current dir
[ x"$dir" = x ] && dir='.'
if [ -f "$dir/$CMDNAME" ] ; then
PGPATH="$dir"
break
fi
done
fi
IFS="$_IFS"
# As last resort use the installation directory. We don't want to use
# this as first resort because depending on how users do release upgrades
# they might temporarily move the installation tree elsewhere, so we'd
# accidentally invoke the newly installed versions of pg_dump and psql.
if [ x"$PGPATH" = x"" ]; then
PGPATH="$bindir"
fi
#
# Look for needed programs
#
for prog in pg_dump psql ; do
if [ ! -x "$PGPATH/$prog" ] ; then
(
echo "The program $prog needed by $CMDNAME could not be found. It was"
echo "expected at:"
echo " $PGPATH/$prog"
echo "If this is not the correct directory, please start $CMDNAME"
echo "with a full search path. Otherwise make sure that the program"
echo "was installed successfully."
) 1>&2
exit 1
fi
done
#
# to adapt to System V vs. BSD 'echo'
#
if echo '\\' | grep '\\\\' >/dev/null 2>&1
then
BS='\' dummy='\' # BSD
else
BS='\\' # System V
fi
# The dummy assignment is necessary to prevent Emacs' font-lock
# mode from going ballistic when editing this file.
usage=
cleanschema=
globals_only=
while [ "$#" -gt 0 ] ; do
case "$1" in
--help)
usage=t
break
;;
--version)
echo "pg_dumpall (PostgreSQL) $VERSION"
exit 0
;;
--host|-h)
connectopts="$connectopts -h $2"
shift;;
-h*)
connectopts="$connectopts $1"
;;
--host=*)
connectopts="$connectopts -h `echo $1 | sed 's/^--host=//'`"
;;
--port|-p)
connectopts="$connectopts -p $2"
shift;;
-p*)
connectopts="$connectopts $1"
;;
--port=*)
connectopts="$connectopts -p `echo $1 | sed 's/^--port=//'`"
;;
--user|--username|-U)
connectopts="$connectopts -U $2"
shift;;
-U*)
connectopts="$connectopts $1"
;;
--user=*|--username=*)
connectopts="$connectopts -U `echo $1 | sed 's/^--user[^=]*=//'`"
;;
-W|--password)
connectopts="$connectopts -W"
;;
-c|--clean)
cleanschema=yes
pgdumpextraopts="$pgdumpextraopts -c"
;;
-g|--globals-only)
globals_only=yes
;;
-F*|--format=*|-f|--file=*|-t|--table=*)
echo "pg_dump can not process option $1, exiting" 1>&2
exit 1
;;
*)
pgdumpextraopts="$pgdumpextraopts $1"
;;
esac
shift
done
if [ "$usage" ] ; then
echo "$CMDNAME extracts a PostgreSQL database cluster into an SQL script file."
echo
echo "Usage:"
echo " $CMDNAME [ options... ]"
echo
echo "Options:"
echo " -c, --clean Clean (drop) schema prior to create"
echo " -g, --globals-only Only dump global objects, no databases"
echo " -h, --host=HOSTNAME Server host name"
echo " -p, --port=PORT Server port number"
echo " -U, --username=NAME Connect as specified database user"
echo " -W, --password Force password prompts (should happen automatically)"
echo "Any other options will be passed to pg_dump. The dump will be written"
echo "to the standard output."
echo
echo "Report bugs to <pgsql-bugs@postgresql.org>."
exit 0
fi
PSQL="${PGPATH}/psql $connectopts"
PGDUMP="${PGPATH}/pg_dump $connectopts $pgdumpextraopts -X use-set-session-authorization -Fp"
echo "--"
echo "-- pg_dumpall ($VERSION) $connectopts $pgdumpextraopts"
echo "--"
echo "${BS}connect \"template1\""
#
# Dump users (but not the user created by initdb)
#
echo "DELETE FROM pg_shadow WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');"
echo
echo "connected to template1..." 1>&2
$PSQL -d template1 -At -c "\
SELECT
'CREATE USER \"' || usename || '\" WITH SYSID ' || usesysid
|| CASE WHEN passwd IS NOT NULL THEN ' PASSWORD ''' || passwd || '''' else '' end
|| CASE WHEN usecreatedb THEN ' CREATEDB'::text ELSE ' NOCREATEDB' END
|| CASE WHEN usesuper THEN ' CREATEUSER'::text ELSE ' NOCREATEUSER' END
|| CASE WHEN valuntil IS NOT NULL THEN ' VALID UNTIL '''::text
|| CAST(valuntil AS TIMESTAMP) || '''' ELSE '' END || ';'
FROM pg_shadow
WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');" \
|| exit 1
echo
#
# Dump groups
#
echo "DELETE FROM pg_group;"
echo
$PSQL -d template1 -At -F "$NL" \
-c 'SELECT groname,grosysid,grolist FROM pg_group;' | \
while : ; do
IFS="$NL"
read GRONAME || break
read GROSYSID || break
read GROLIST || break
IFS="$_IFS"
echo "CREATE GROUP \"$GRONAME\" WITH SYSID ${GROSYSID};"
echo "$GROLIST" | sed 's/^{\(.*\)}$/\1/' | tr ',' '\n' |
while read userid; do
username="`$PSQL -d template1 -At -c \"SELECT usename FROM pg_shadow WHERE usesysid = ${userid};\"`"
echo " ALTER GROUP \"$GRONAME\" ADD USER \"$username\";"
done
done
IFS="$_IFS"
test "$globals_only" = yes && exit 0
# Save stdin for pg_dump password prompts.
exec 4<&0
# To minimize the number of reconnections (and possibly ensuing password
# prompts) required by the output script, we emit all CREATE DATABASE
# commands during the initial phase of the script, and then run pg_dump
# for each database to dump the contents of that database.
# We skip databases marked not datallowconn, since we'd be unable to
# connect to them anyway (and besides, we don't want to dump template0).
$PSQL -d template1 -At -F "$NL" \
-c "SELECT datname, coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), pg_encoding_to_char(d.encoding), datistemplate, datpath FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) WHERE datallowconn ORDER BY 1;" | \
while : ; do
IFS="$NL"
read DATABASE || break
read DBOWNER || break
read ENCODING || break
read ISTEMPLATE || break
read DBPATH || break
IFS="$_IFS"
if [ "$DATABASE" != template1 ] ; then
echo
if [ "$cleanschema" = yes ] ; then
echo "DROP DATABASE \"$DATABASE\";"
fi
createdbcmd="CREATE DATABASE \"$DATABASE\" WITH OWNER = \"$DBOWNER\" TEMPLATE = template0"
if [ x"$DBPATH" != x"" ] ; then
createdbcmd="$createdbcmd LOCATION = '$DBPATH'"
fi
if [ x"$MULTIBYTE" != x"" ] ; then
createdbcmd="$createdbcmd ENCODING = '$ENCODING'"
fi
echo "$createdbcmd;"
if [ x"$ISTEMPLATE" = xt ] ; then
echo "UPDATE pg_database SET datistemplate = 't' WHERE datname = '$DATABASE';"
fi
fi
done
IFS="$_IFS"
$PSQL -d template1 -At -F "$NL" \
-c "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;" | \
while :; do
IFS="$NL"
read DATABASE || break
IFS="$_IFS"
echo "dumping database \"$DATABASE\"..." 1>&2
echo
echo "--"
echo "-- Database $DATABASE"
echo "--"
echo "${BS}connect \"$DATABASE\""
$PGDUMP "$DATABASE" <&4
if [ "$?" -ne 0 ] ; then
echo "pg_dump failed on $DATABASE, exiting" 1>&2
exit 1
fi
done
exit 0

View File

@ -34,13 +34,14 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.38 2002/08/10 16:57:32 petere Exp $ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.39 2002/08/27 18:57:26 petere Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "pg_backup.h" #include "pg_backup.h"
#include "pg_backup_archiver.h" #include "pg_backup_archiver.h"
#include "dumputils.h"
#include <ctype.h> #include <ctype.h>