diff --git a/doc/src/sgml/ref/pg_dumpall.sgml b/doc/src/sgml/ref/pg_dumpall.sgml
index 0a3b44c48a..cdaf277a30 100644
--- a/doc/src/sgml/ref/pg_dumpall.sgml
+++ b/doc/src/sgml/ref/pg_dumpall.sgml
@@ -1,5 +1,5 @@
@@ -128,6 +128,18 @@ PostgreSQL documentation
+
+
+
+
+
+
+ Write the output to the specified file. This is particularly useful
+ on Windows because output redirection does not work for child
+ processes.
+
+
+
diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h
index 3ada7cc73c..a870516d7a 100644
--- a/src/bin/pg_dump/pg_backup.h
+++ b/src/bin/pg_dump/pg_backup.h
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup.h,v 1.44 2006/10/14 23:07:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup.h,v 1.45 2007/01/25 03:30:43 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -46,6 +46,13 @@ typedef enum _archiveFormat
archNull = 4
} ArchiveFormat;
+typedef enum _archiveMode
+{
+ archModeAppend,
+ archModeWrite,
+ archModeRead
+} ArchiveMode;
+
/*
* We may want to have some more user-readable data, but in the mean
* time this gives us some abstraction and type checking.
@@ -166,7 +173,7 @@ extern Archive *OpenArchive(const char *FileSpec, const ArchiveFormat fmt);
/* Create a new archive */
extern Archive *CreateArchive(const char *FileSpec, const ArchiveFormat fmt,
- const int compression);
+ const int compression, ArchiveMode mode);
/* The --list option */
extern void PrintTOCSummary(Archive *AH, RestoreOptions *ropt);
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index a4c5d6d712..cd84c60882 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.139 2007/01/23 17:54:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.140 2007/01/25 03:30:43 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -86,10 +86,10 @@ static void ResetOutput(ArchiveHandle *AH, OutputContext savedContext);
/* Public */
Archive *
CreateArchive(const char *FileSpec, const ArchiveFormat fmt,
- const int compression)
+ const int compression, ArchiveMode mode)
{
- ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression, archModeWrite);
+ ArchiveHandle *AH = _allocAH(FileSpec, fmt, compression, mode);
return (Archive *) AH;
}
@@ -203,7 +203,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
/*
* Setup the output file if necessary.
- */
+ */
if (ropt->filename || ropt->compression)
sav = SetOutput(AH, ropt->filename, ropt->compression);
@@ -940,10 +940,20 @@ SetOutput(ArchiveHandle *AH, char *filename, int compression)
else
#endif
{ /* Use fopen */
- if (fn >= 0)
- AH->OF = fdopen(dup(fn), PG_BINARY_W);
+ if (AH->mode == archModeAppend)
+ {
+ if (fn >= 0)
+ AH->OF = fdopen(dup(fn), PG_BINARY_A);
+ else
+ AH->OF = fopen(filename, PG_BINARY_A);
+ }
else
- AH->OF = fopen(filename, PG_BINARY_W);
+ {
+ if (fn >= 0)
+ AH->OF = fdopen(dup(fn), PG_BINARY_W);
+ else
+ AH->OF = fopen(filename, PG_BINARY_W);
+ }
AH->gzOut = 0;
}
diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h
index b64b8f3d32..4a8cff3598 100644
--- a/src/bin/pg_dump/pg_backup_archiver.h
+++ b/src/bin/pg_dump/pg_backup_archiver.h
@@ -17,7 +17,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.73 2006/10/04 00:30:05 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.74 2007/01/25 03:30:43 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -122,12 +122,6 @@ typedef void (*PrintTocDataPtr) (struct _archiveHandle * AH, struct _tocEntry *
typedef size_t (*CustomOutPtr) (struct _archiveHandle * AH, const void *buf, size_t len);
-typedef enum _archiveMode
-{
- archModeWrite,
- archModeRead
-} ArchiveMode;
-
typedef struct _outputContext
{
void *OF;
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index c8b3e3916a..2fec7326d5 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.458 2007/01/23 17:54:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.459 2007/01/25 03:30:43 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -478,25 +478,31 @@ main(int argc, char **argv)
/* open the output file */
switch (format[0])
{
+ case 'a':
+ case 'A':
+ plainText = 1;
+ g_fout = CreateArchive(filename, archNull, 0, archModeAppend);
+ break;
+
case 'c':
case 'C':
- g_fout = CreateArchive(filename, archCustom, compressLevel);
+ g_fout = CreateArchive(filename, archCustom, compressLevel, archModeWrite);
break;
case 'f':
case 'F':
- g_fout = CreateArchive(filename, archFiles, compressLevel);
+ g_fout = CreateArchive(filename, archFiles, compressLevel, archModeWrite);
break;
case 'p':
case 'P':
plainText = 1;
- g_fout = CreateArchive(filename, archNull, 0);
+ g_fout = CreateArchive(filename, archNull, 0, archModeWrite);
break;
case 't':
case 'T':
- g_fout = CreateArchive(filename, archTar, compressLevel);
+ g_fout = CreateArchive(filename, archTar, compressLevel, archModeWrite);
break;
default:
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 66c66d8a1a..e2e3a9f5bb 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
*
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.88 2007/01/25 02:46:33 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.89 2007/01/25 03:30:43 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -68,23 +68,25 @@ static int disable_triggers = 0;
static int use_setsessauth = 0;
static int server_version;
+static FILE *OPF;
+static char *filename = NULL;
int
main(int argc, char *argv[])
{
- char *pghost = NULL;
- char *pgport = NULL;
- char *pguser = NULL;
- char *pgdb = NULL;
+ char *pghost = NULL;
+ char *pgport = NULL;
+ char *pguser = NULL;
+ char *pgdb = NULL;
bool force_password = false;
bool data_only = false;
bool globals_only = false;
bool roles_only = false;
bool tablespaces_only = false;
bool schema_only = false;
- PGconn *conn;
+ PGconn *conn;
int encoding;
- const char *std_strings;
+ const char *std_strings;
int c,
ret;
@@ -94,6 +96,7 @@ main(int argc, char *argv[])
{"inserts", no_argument, NULL, 'd'},
{"attribute-inserts", no_argument, NULL, 'D'},
{"column-inserts", no_argument, NULL, 'D'},
+ {"file", required_argument, NULL, 'f'},
{"globals-only", no_argument, NULL, 'g'},
{"host", required_argument, NULL, 'h'},
{"ignore-version", no_argument, NULL, 'i'},
@@ -167,7 +170,7 @@ main(int argc, char *argv[])
pgdumpopts = createPQExpBuffer();
- while ((c = getopt_long(argc, argv, "acdDgh:il:oOp:rsS:tU:vWxX:", long_options, &optindex)) != -1)
+ while ((c = getopt_long(argc, argv, "acdDf:gh:il:oOp:rsS:tU:vWxX:", long_options, &optindex)) != -1)
{
switch (c)
{
@@ -184,6 +187,16 @@ main(int argc, char *argv[])
case 'D':
appendPQExpBuffer(pgdumpopts, " -%c", c);
break;
+
+ case 'f':
+ filename = optarg;
+#ifndef WIN32
+ appendPQExpBuffer(pgdumpopts, " -f '%s'", filename);
+#else
+ appendPQExpBuffer(pgdumpopts, " -f \"%s\"", filename);
+#endif
+
+ break;
case 'g':
globals_only = true;
@@ -377,6 +390,22 @@ main(int argc, char *argv[])
exit(1);
}
}
+
+ /*
+ * Open the output file if required, otherwise use stdout
+ */
+ if (filename)
+ {
+ OPF = fopen(filename, PG_BINARY_W);
+ if (!OPF)
+ {
+ fprintf(stderr, _("%s: could not open the output file \"%s\"\n"),
+ progname, filename);
+ exit(1);
+ }
+ }
+ else
+ OPF = stdout;
/*
* Get the active encoding and the standard_conforming_strings setting, so
@@ -387,21 +416,21 @@ main(int argc, char *argv[])
if (!std_strings)
std_strings = "off";
- printf("--\n-- PostgreSQL database cluster dump\n--\n\n");
+ fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n");
if (verbose)
dumpTimestamp("Started on");
- printf("\\connect postgres\n\n");
+ fprintf(OPF, "\\connect postgres\n\n");
if (!data_only)
{
/* Replicate encoding and std_strings in output */
- printf("SET client_encoding = '%s';\n",
+ fprintf(OPF, "SET client_encoding = '%s';\n",
pg_encoding_to_char(encoding));
- printf("SET standard_conforming_strings = %s;\n", std_strings);
+ fprintf(OPF, "SET standard_conforming_strings = %s;\n", std_strings);
if (strcmp(std_strings, "off") == 0)
- printf("SET escape_string_warning = 'off';\n");
- printf("\n");
+ fprintf(OPF, "SET escape_string_warning = 'off';\n");
+ fprintf(OPF, "\n");
if (!tablespaces_only)
{
@@ -434,7 +463,10 @@ main(int argc, char *argv[])
if (verbose)
dumpTimestamp("Completed on");
- printf("--\n-- PostgreSQL database cluster dump complete\n--\n\n");
+ fprintf(OPF, "--\n-- PostgreSQL database cluster dump complete\n--\n\n");
+
+ if (filename)
+ fclose(OPF);
exit(0);
}
@@ -449,6 +481,7 @@ help(void)
printf(_(" %s [OPTION]...\n"), progname);
printf(_("\nGeneral options:\n"));
+ printf(_(" -f, --file=FILENAME output file name\n"));
printf(_(" -i, --ignore-version proceed even when server version mismatches\n"
" pg_dumpall version\n"));
printf(_(" --help show this help, then exit\n"));
@@ -571,7 +604,7 @@ dumpRoles(PGconn *conn)
i_rolcomment = PQfnumber(res, "rolcomment");
if (PQntuples(res) > 0)
- printf("--\n-- Roles\n--\n\n");
+ fprintf(OPF, "--\n-- Roles\n--\n\n");
for (i = 0; i < PQntuples(res); i++)
{
@@ -641,7 +674,7 @@ dumpRoles(PGconn *conn)
appendPQExpBuffer(buf, ";\n");
}
- printf("%s", buf->data);
+ fprintf(OPF, "%s", buf->data);
if (server_version >= 70300)
dumpUserConfig(conn, rolename);
@@ -649,7 +682,7 @@ dumpRoles(PGconn *conn)
PQclear(res);
- printf("\n\n");
+ fprintf(OPF, "\n\n");
destroyPQExpBuffer(buf);
}
@@ -678,7 +711,7 @@ dumpRoleMembership(PGconn *conn)
"ORDER BY 1,2,3");
if (PQntuples(res) > 0)
- printf("--\n-- Role memberships\n--\n\n");
+ fprintf(OPF, "--\n-- Role memberships\n--\n\n");
for (i = 0; i < PQntuples(res); i++)
{
@@ -687,16 +720,16 @@ dumpRoleMembership(PGconn *conn)
char *grantor = PQgetvalue(res, i, 2);
char *option = PQgetvalue(res, i, 3);
- printf("GRANT %s", fmtId(roleid));
- printf(" TO %s", fmtId(member));
+ fprintf(OPF, "GRANT %s", fmtId(roleid));
+ fprintf(OPF, " TO %s", fmtId(member));
if (*option == 't')
- printf(" WITH ADMIN OPTION");
- printf(" GRANTED BY %s;\n", fmtId(grantor));
+ fprintf(OPF, " WITH ADMIN OPTION");
+ fprintf(OPF, " GRANTED BY %s;\n", fmtId(grantor));
}
PQclear(res);
- printf("\n\n");
+ fprintf(OPF, "\n\n");
}
/*
@@ -718,7 +751,7 @@ dumpGroups(PGconn *conn)
"SELECT groname, grolist FROM pg_group ORDER BY 1");
if (PQntuples(res) > 0)
- printf("--\n-- Role memberships\n--\n\n");
+ fprintf(OPF, "--\n-- Role memberships\n--\n\n");
for (i = 0; i < PQntuples(res); i++)
{
@@ -755,8 +788,8 @@ dumpGroups(PGconn *conn)
if (strcmp(groname, usename) == 0)
continue;
- printf("GRANT %s", fmtId(groname));
- printf(" TO %s;\n", fmtId(usename));
+ fprintf(OPF, "GRANT %s", fmtId(groname));
+ fprintf(OPF, " TO %s;\n", fmtId(usename));
}
PQclear(res2);
@@ -765,7 +798,7 @@ dumpGroups(PGconn *conn)
PQclear(res);
destroyPQExpBuffer(buf);
- printf("\n\n");
+ fprintf(OPF, "\n\n");
}
/*
@@ -799,7 +832,7 @@ dumpTablespaces(PGconn *conn)
"ORDER BY 1");
if (PQntuples(res) > 0)
- printf("--\n-- Tablespaces\n--\n\n");
+ fprintf(OPF, "--\n-- Tablespaces\n--\n\n");
for (i = 0; i < PQntuples(res); i++)
{
@@ -841,14 +874,14 @@ dumpTablespaces(PGconn *conn)
appendPQExpBuffer(buf, ";\n");
}
- printf("%s", buf->data);
+ fprintf(OPF, "%s", buf->data);
free(fspcname);
destroyPQExpBuffer(buf);
}
PQclear(res);
- printf("\n\n");
+ fprintf(OPF, "\n\n");
}
/*
@@ -869,7 +902,7 @@ dumpCreateDB(PGconn *conn)
PGresult *res;
int i;
- printf("--\n-- Database creation\n--\n\n");
+ fprintf(OPF, "--\n-- Database creation\n--\n\n");
if (server_version >= 80100)
res = executeQuery(conn,
@@ -998,7 +1031,7 @@ dumpCreateDB(PGconn *conn)
exit(1);
}
- printf("%s", buf->data);
+ fprintf(OPF, "%s", buf->data);
if (server_version >= 70300)
dumpDatabaseConfig(conn, dbname);
@@ -1009,7 +1042,7 @@ dumpCreateDB(PGconn *conn)
PQclear(res);
destroyPQExpBuffer(buf);
- printf("\n\n");
+ fprintf(OPF, "\n\n");
}
@@ -1121,7 +1154,7 @@ makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
appendStringLiteralConn(buf, pos + 1, conn);
appendPQExpBuffer(buf, ";\n");
- printf("%s", buf->data);
+ fprintf(OPF, "%s", buf->data);
destroyPQExpBuffer(buf);
free(mine);
}
@@ -1151,13 +1184,29 @@ dumpDatabases(PGconn *conn)
if (verbose)
fprintf(stderr, _("%s: dumping database \"%s\"...\n"), progname, dbname);
- printf("\\connect %s\n\n", fmtId(dbname));
+ fprintf(OPF, "\\connect %s\n\n", fmtId(dbname));
+
+ if (filename)
+ fclose(OPF);
+
ret = runPgDump(dbname);
if (ret != 0)
{
fprintf(stderr, _("%s: pg_dump failed on database \"%s\", exiting\n"), progname, dbname);
exit(1);
}
+
+ if (filename)
+ {
+ OPF = fopen(filename, PG_BINARY_A);
+ if (!OPF)
+ {
+ fprintf(stderr, _("%s: could not re-open the output file \"%s\"\n"),
+ progname, filename);
+ exit(1);
+ }
+ }
+
}
PQclear(res);
@@ -1179,13 +1228,28 @@ runPgDump(const char *dbname)
* Win32 has to use double-quotes for args, rather than single quotes.
* Strangely enough, this is the only place we pass a database name on the
* command line, except "postgres" which doesn't need quoting.
+ *
+ * If we have a filename, use the undocumented plain-append pg_dump format.
*/
+ if (filename)
+ {
+#ifndef WIN32
+ appendPQExpBuffer(cmd, "%s\"%s\" %s -Fa '", SYSTEMQUOTE, pg_dump_bin,
+#else
+ appendPQExpBuffer(cmd, "%s\"%s\" %s -Fa \"", SYSTEMQUOTE, pg_dump_bin,
+#endif
+ pgdumpopts->data);
+ }
+ else
+ {
#ifndef WIN32
appendPQExpBuffer(cmd, "%s\"%s\" %s -Fp '", SYSTEMQUOTE, pg_dump_bin,
#else
appendPQExpBuffer(cmd, "%s\"%s\" %s -Fp \"", SYSTEMQUOTE, pg_dump_bin,
#endif
pgdumpopts->data);
+ }
+
/* Shell quoting is not quite like SQL quoting, so can't use fmtId */
for (p = dbname; *p; p++)
@@ -1413,5 +1477,5 @@ dumpTimestamp(char *msg)
"%Y-%m-%d %H:%M:%S",
#endif
localtime(&now)) != 0)
- printf("-- %s %s\n\n", msg, buf);
+ fprintf(OPF, "-- %s %s\n\n", msg, buf);
}
diff --git a/src/include/c.h b/src/include/c.h
index dab8dc2e68..9daa9e4c0e 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/c.h,v 1.216 2007/01/11 02:39:52 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/c.h,v 1.217 2007/01/25 03:30:43 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -736,10 +736,12 @@ typedef NameData *Name;
*/
#if defined(WIN32) || defined(__CYGWIN__)
#define PG_BINARY O_BINARY
+#define PG_BINARY_A "ab"
#define PG_BINARY_R "rb"
#define PG_BINARY_W "wb"
#else
#define PG_BINARY 0
+#define PG_BINARY_A "a"
#define PG_BINARY_R "r"
#define PG_BINARY_W "w"
#endif