Add a --role option to pg_dump, pg_dumpall, and pg_restore. This allows

performing dumps and restores in accordance with a security policy that
forbids logging in directly as superuser, but instead specifies that you
should log into an admin account and then SET ROLE to the superuser.

In passing, clean up some ugly and mostly-broken code for quoting shell
arguments in pg_dumpall.

Benedek László, with some help from Tom Lane
This commit is contained in:
Tom Lane 2009-01-05 16:54:37 +00:00
parent f42a7f1e62
commit b0a6ad70a1
8 changed files with 195 additions and 115 deletions

View File

@ -1,5 +1,5 @@
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.105 2008/08/26 00:03:15 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.106 2009/01/05 16:54:36 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
@ -698,6 +698,23 @@ PostgreSQL documentation
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--role=<replaceable class="parameter">rolename</replaceable></option></term>
<listitem>
<para>
Specifies a role name to be used to create the dump.
This option causes <application>pg_dump</> to issue a
<command>SET ROLE</> <replaceable class="parameter">rolename</>
command after connecting to the database. It is useful when the
authenticated user (specified by <option>-U</>) lacks privileges
needed by <application>pg_dump</>, but can switch to a role with
the required rights. Some installations have a policy against
logging in directly as a superuser, and use of this option allows
dumps to be made without violating the policy.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</para> </para>
</refsect1> </refsect1>

View File

@ -1,5 +1,5 @@
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/pg_dumpall.sgml,v 1.73 2008/08/29 17:28:43 alvherre Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/pg_dumpall.sgml,v 1.74 2009/01/05 16:54:36 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
@ -129,7 +129,7 @@ PostgreSQL documentation
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><option>-f <replaceable class="parameter">filename</replaceable></option></term> <term><option>-f <replaceable class="parameter">filename</replaceable></option></term>
<term><option>--file=<replaceable class="parameter">filename</replaceable></option></term> <term><option>--file=<replaceable class="parameter">filename</replaceable></option></term>
@ -183,7 +183,7 @@ PostgreSQL documentation
Do not output commands to set Do not output commands to set
ownership of objects to match the original database. ownership of objects to match the original database.
By default, <application>pg_dumpall</application> issues By default, <application>pg_dumpall</application> issues
<command>ALTER OWNER</> or <command>ALTER OWNER</> or
<command>SET SESSION AUTHORIZATION</command> <command>SET SESSION AUTHORIZATION</command>
statements to set ownership of created schema elements. statements to set ownership of created schema elements.
These statements These statements
@ -342,8 +342,8 @@ PostgreSQL documentation
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term>-h <replaceable>host</replaceable></term> <term><option>-h <replaceable>host</replaceable></option></term>
<term>--host=<replaceable>host</replaceable></term> <term><option>--host=<replaceable>host</replaceable></option></term>
<listitem> <listitem>
<para> <para>
Specifies the host name of the machine on which the database Specifies the host name of the machine on which the database
@ -354,10 +354,10 @@ PostgreSQL documentation
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term>-l <replaceable>dbname</replaceable></term> <term><option>-l <replaceable>dbname</replaceable></option></term>
<term>--database=<replaceable>dbname</replaceable></term> <term><option>--database=<replaceable>dbname</replaceable></option></term>
<listitem> <listitem>
<para> <para>
Specifies the name of the database to connect to to dump global Specifies the name of the database to connect to to dump global
@ -369,8 +369,8 @@ PostgreSQL documentation
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term>-p <replaceable>port</replaceable></term> <term><option>-p <replaceable>port</replaceable></option></term>
<term>--port=<replaceable>port</replaceable></term> <term><option>--port=<replaceable>port</replaceable></option></term>
<listitem> <listitem>
<para> <para>
Specifies the TCP port or local Unix domain socket file Specifies the TCP port or local Unix domain socket file
@ -382,8 +382,8 @@ PostgreSQL documentation
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term>-U <replaceable>username</replaceable></term> <term><option>-U <replaceable>username</replaceable></option></term>
<term>--username=<replaceable>username</replaceable></term> <term><option>--username=<replaceable>username</replaceable></option></term>
<listitem> <listitem>
<para> <para>
User name to connect as. User name to connect as.
@ -392,12 +392,12 @@ PostgreSQL documentation
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term>-W</term> <term><option>-W</option></term>
<term>--password</term> <term><option>--password</option></term>
<listitem> <listitem>
<para> <para>
Force <application>pg_dumpall</application> to prompt for a Force <application>pg_dumpall</application> to prompt for a
password before connecting to a database. password before connecting to a database.
</para> </para>
<para> <para>
@ -417,6 +417,23 @@ PostgreSQL documentation
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--role=<replaceable class="parameter">rolename</replaceable></option></term>
<listitem>
<para>
Specifies a role name to be used to create the dump.
This option causes <application>pg_dumpall</> to issue a
<command>SET ROLE</> <replaceable class="parameter">rolename</>
command after connecting to the database. It is useful when the
authenticated user (specified by <option>-U</>) lacks privileges
needed by <application>pg_dumpall</>, but can switch to a role with
the required rights. Some installations have a policy against
logging in directly as a superuser, and use of this option allows
dumps to be made without violating the policy.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</para> </para>
</refsect1> </refsect1>
@ -503,6 +520,6 @@ PostgreSQL documentation
Check <xref linkend="app-pgdump"> for details on possible Check <xref linkend="app-pgdump"> for details on possible
error conditions. error conditions.
</para> </para>
</refsect1> </refsect1>
</refentry> </refentry>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/pg_restore.sgml,v 1.76 2008/09/07 19:12:57 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/ref/pg_restore.sgml,v 1.77 2009/01/05 16:54:36 tgl Exp $ -->
<refentry id="APP-PGRESTORE"> <refentry id="APP-PGRESTORE">
<refmeta> <refmeta>
@ -135,7 +135,7 @@
<listitem> <listitem>
<para> <para>
Exit if an error is encountered while sending SQL commands to Exit if an error is encountered while sending SQL commands to
the database. The default is to continue and to display a count of the database. The default is to continue and to display a count of
errors at the end of the restoration. errors at the end of the restoration.
</para> </para>
</listitem> </listitem>
@ -261,7 +261,7 @@
Do not output commands to set Do not output commands to set
ownership of objects to match the original database. ownership of objects to match the original database.
By default, <application>pg_restore</application> issues By default, <application>pg_restore</application> issues
<command>ALTER OWNER</> or <command>ALTER OWNER</> or
<command>SET SESSION AUTHORIZATION</command> <command>SET SESSION AUTHORIZATION</command>
statements to set ownership of created schema elements. statements to set ownership of created schema elements.
These statements will fail unless the initial connection to the These statements will fail unless the initial connection to the
@ -429,6 +429,20 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>-1</option></term>
<term><option>--single-transaction</option></term>
<listitem>
<para>
Execute the restore as a single transaction (that is, wrap the
emitted commands in <command>BEGIN</>/<command>COMMIT</>). This
ensures that either all the commands complete successfully, or no
changes are applied. This option implies
<option>--exit-on-error</>.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</para> </para>
@ -480,7 +494,7 @@
<listitem> <listitem>
<para> <para>
Force <application>pg_restore</application> to prompt for a Force <application>pg_restore</application> to prompt for a
password before connecting to a database. password before connecting to a database.
</para> </para>
<para> <para>
@ -496,15 +510,18 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><option>-1</option></term> <term><option>--role=<replaceable class="parameter">rolename</replaceable></option></term>
<term><option>--single-transaction</option></term>
<listitem> <listitem>
<para> <para>
Execute the restore as a single transaction (that is, wrap the Specifies a role name to be used to perform the restore.
emitted commands in <command>BEGIN</>/<command>COMMIT</>). This This option causes <application>pg_restore</> to issue a
ensures that either all the commands complete successfully, or no <command>SET ROLE</> <replaceable class="parameter">rolename</>
changes are applied. This option implies command after connecting to the database. It is useful when the
<option>--exit-on-error</>. authenticated user (specified by <option>-U</>) lacks privileges
needed by <application>pg_restore</>, but can switch to a role with
the required rights. Some installations have a policy against
logging in directly as a superuser, and use of this option allows
restores to be performed without violating the policy.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup.h,v 1.47 2008/04/13 03:49:21 tgl Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup.h,v 1.48 2009/01/05 16:54:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -89,6 +89,7 @@ typedef struct _restoreOptions
int use_setsessauth;/* Use SET SESSION AUTHORIZATION commands int use_setsessauth;/* Use SET SESSION AUTHORIZATION commands
* instead of OWNER TO */ * instead of OWNER TO */
char *superuser; /* Username to use as superuser */ char *superuser; /* Username to use as superuser */
char *use_role; /* Issue SET ROLE to this */
int dataOnly; int dataOnly;
int dropSchema; int dropSchema;
char *filename; char *filename;

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.159 2008/12/19 16:25:17 petere Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.160 2009/01/05 16:54:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -462,9 +462,8 @@ NewRestoreOptions(void)
opts = (RestoreOptions *) calloc(1, sizeof(RestoreOptions)); opts = (RestoreOptions *) calloc(1, sizeof(RestoreOptions));
/* set any fields that shouldn't default to zeroes */
opts->format = archUnknown; opts->format = archUnknown;
opts->suppressDumpWarnings = false;
opts->exit_on_error = false;
return opts; return opts;
} }
@ -2146,6 +2145,10 @@ _doSetFixedOutputState(ArchiveHandle *AH)
ahprintf(AH, "SET standard_conforming_strings = %s;\n", ahprintf(AH, "SET standard_conforming_strings = %s;\n",
AH->public.std_strings ? "on" : "off"); AH->public.std_strings ? "on" : "off");
/* Select the role to be used during restore */
if (AH->ropt && AH->ropt->use_role)
ahprintf(AH, "SET ROLE %s;\n", fmtId(AH->ropt->use_role));
/* Make sure function checking is disabled */ /* Make sure function checking is disabled */
ahprintf(AH, "SET check_function_bodies = false;\n"); ahprintf(AH, "SET check_function_bodies = false;\n");

View File

@ -12,7 +12,7 @@
* by PostgreSQL * by PostgreSQL
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.511 2009/01/01 17:23:54 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.512 2009/01/05 16:54:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -227,6 +227,7 @@ main(int argc, char **argv)
bool outputBlobs = false; bool outputBlobs = false;
int outputNoOwner = 0; int outputNoOwner = 0;
char *outputSuperuser = NULL; char *outputSuperuser = NULL;
char *use_role = NULL;
int my_version; int my_version;
int optindex; int optindex;
RestoreOptions *ropt; RestoreOptions *ropt;
@ -274,6 +275,7 @@ main(int argc, char **argv)
{"disable-triggers", no_argument, &disable_triggers, 1}, {"disable-triggers", no_argument, &disable_triggers, 1},
{"lock-wait-timeout", required_argument, NULL, 2}, {"lock-wait-timeout", required_argument, NULL, 2},
{"no-tablespaces", no_argument, &outputNoTablespaces, 1}, {"no-tablespaces", no_argument, &outputNoTablespaces, 1},
{"role", required_argument, NULL, 3},
{"use-set-session-authorization", no_argument, &use_setsessauth, 1}, {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
@ -447,11 +449,14 @@ main(int argc, char **argv)
/* This covers the long options equivalent to -X xxx. */ /* This covers the long options equivalent to -X xxx. */
break; break;
case 2: case 2: /* lock-wait-timeout */
/* lock-wait-timeout */
lockWaitTimeout = optarg; lockWaitTimeout = optarg;
break; break;
case 3: /* SET ROLE */
use_role = optarg;
break;
default: default:
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit(1); exit(1);
@ -570,6 +575,16 @@ main(int argc, char **argv)
std_strings = PQparameterStatus(g_conn, "standard_conforming_strings"); std_strings = PQparameterStatus(g_conn, "standard_conforming_strings");
g_fout->std_strings = (std_strings && strcmp(std_strings, "on") == 0); g_fout->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
/* Set the role if requested */
if (use_role && g_fout->remoteVersion >= 80100)
{
PQExpBuffer query = createPQExpBuffer();
appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
do_sql_command(g_conn, query->data);
destroyPQExpBuffer(query);
}
/* Set the datestyle to ISO to ensure the dump's portability */ /* Set the datestyle to ISO to ensure the dump's portability */
do_sql_command(g_conn, "SET DATESTYLE = ISO"); do_sql_command(g_conn, "SET DATESTYLE = ISO");
@ -807,6 +822,7 @@ help(const char *progname)
printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n")); printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
printf(_(" --disable-triggers disable triggers during data-only restore\n")); printf(_(" --disable-triggers disable triggers during data-only restore\n"));
printf(_(" --no-tablespaces do not dump tablespace assignments\n")); printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
printf(_(" --use-set-session-authorization\n" printf(_(" --use-set-session-authorization\n"
" use SESSION AUTHORIZATION commands instead of\n" " use SESSION AUTHORIZATION commands instead of\n"
" ALTER OWNER commands to set ownership\n")); " ALTER OWNER commands to set ownership\n"));

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* *
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.110 2009/01/01 17:23:54 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.111 2009/01/05 16:54:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -48,6 +48,7 @@ static void makeAlterConfigCommand(PGconn *conn, const char *arrayitem,
const char *type, const char *name); const char *type, const char *name);
static void dumpDatabases(PGconn *conn); static void dumpDatabases(PGconn *conn);
static void dumpTimestamp(char *msg); static void dumpTimestamp(char *msg);
static void doShellQuoting(PQExpBuffer buf, const char *str);
static int runPgDump(const char *dbname); static int runPgDump(const char *dbname);
static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport, static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
@ -77,6 +78,7 @@ main(int argc, char *argv[])
char *pgport = NULL; char *pgport = NULL;
char *pguser = NULL; char *pguser = NULL;
char *pgdb = NULL; char *pgdb = NULL;
char *use_role = NULL;
bool force_password = false; bool force_password = false;
bool data_only = false; bool data_only = false;
bool globals_only = false; bool globals_only = false;
@ -118,9 +120,10 @@ main(int argc, char *argv[])
*/ */
{"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1}, {"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
{"disable-triggers", no_argument, &disable_triggers, 1}, {"disable-triggers", no_argument, &disable_triggers, 1},
{"no-tablespaces", no_argument, &no_tablespaces, 1},
{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
{"lock-wait-timeout", required_argument, NULL, 2}, {"lock-wait-timeout", required_argument, NULL, 2},
{"no-tablespaces", no_argument, &no_tablespaces, 1},
{"role", required_argument, NULL, 3},
{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
@ -191,12 +194,8 @@ main(int argc, char *argv[])
case 'f': case 'f':
filename = optarg; filename = optarg;
#ifndef WIN32 appendPQExpBuffer(pgdumpopts, " -f ");
appendPQExpBuffer(pgdumpopts, " -f '%s'", filename); doShellQuoting(pgdumpopts, filename);
#else
appendPQExpBuffer(pgdumpopts, " -f \"%s\"", filename);
#endif
break; break;
case 'g': case 'g':
@ -205,12 +204,8 @@ main(int argc, char *argv[])
case 'h': case 'h':
pghost = optarg; pghost = optarg;
#ifndef WIN32 appendPQExpBuffer(pgdumpopts, " -h ");
appendPQExpBuffer(pgdumpopts, " -h '%s'", pghost); doShellQuoting(pgdumpopts, pghost);
#else
appendPQExpBuffer(pgdumpopts, " -h \"%s\"", pghost);
#endif
break; break;
case 'i': case 'i':
@ -231,11 +226,8 @@ main(int argc, char *argv[])
case 'p': case 'p':
pgport = optarg; pgport = optarg;
#ifndef WIN32 appendPQExpBuffer(pgdumpopts, " -p ");
appendPQExpBuffer(pgdumpopts, " -p '%s'", pgport); doShellQuoting(pgdumpopts, pgport);
#else
appendPQExpBuffer(pgdumpopts, " -p \"%s\"", pgport);
#endif
break; break;
case 'r': case 'r':
@ -248,11 +240,8 @@ main(int argc, char *argv[])
break; break;
case 'S': case 'S':
#ifndef WIN32 appendPQExpBuffer(pgdumpopts, " -S ");
appendPQExpBuffer(pgdumpopts, " -S '%s'", optarg); doShellQuoting(pgdumpopts, optarg);
#else
appendPQExpBuffer(pgdumpopts, " -S \"%s\"", optarg);
#endif
break; break;
case 't': case 't':
@ -261,11 +250,8 @@ main(int argc, char *argv[])
case 'U': case 'U':
pguser = optarg; pguser = optarg;
#ifndef WIN32 appendPQExpBuffer(pgdumpopts, " -U ");
appendPQExpBuffer(pgdumpopts, " -U '%s'", pguser); doShellQuoting(pgdumpopts, pguser);
#else
appendPQExpBuffer(pgdumpopts, " -U \"%s\"", pguser);
#endif
break; break;
case 'v': case 'v':
@ -307,8 +293,14 @@ main(int argc, char *argv[])
break; break;
case 2: case 2:
appendPQExpBuffer(pgdumpopts, " --lock-wait-timeout="); appendPQExpBuffer(pgdumpopts, " --lock-wait-timeout ");
appendPQExpBuffer(pgdumpopts, "%s", optarg); doShellQuoting(pgdumpopts, optarg);
break;
case 3:
use_role = optarg;
appendPQExpBuffer(pgdumpopts, " --role ");
doShellQuoting(pgdumpopts, use_role);
break; break;
default: default:
@ -426,6 +418,16 @@ main(int argc, char *argv[])
if (!std_strings) if (!std_strings)
std_strings = "off"; std_strings = "off";
/* Set the role if requested */
if (use_role && server_version >= 80100)
{
PQExpBuffer query = createPQExpBuffer();
appendPQExpBuffer(query, "SET ROLE %s", fmtId(use_role));
executeCommand(conn, query->data);
destroyPQExpBuffer(query);
}
fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n"); fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n");
if (verbose) if (verbose)
dumpTimestamp("Started on"); dumpTimestamp("Started on");
@ -513,6 +515,7 @@ help(void)
" disable dollar quoting, use SQL standard quoting\n")); " disable dollar quoting, use SQL standard quoting\n"));
printf(_(" --disable-triggers disable triggers during data-only restore\n")); printf(_(" --disable-triggers disable triggers during data-only restore\n"));
printf(_(" --no-tablespaces do not dump tablespace assignments\n")); printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
printf(_(" --role=ROLENAME do SET ROLE before dump\n"));
printf(_(" --use-set-session-authorization\n" printf(_(" --use-set-session-authorization\n"
" use SESSION AUTHORIZATION commands instead of\n" " use SESSION AUTHORIZATION commands instead of\n"
" OWNER TO commands\n")); " OWNER TO commands\n"));
@ -1271,56 +1274,21 @@ static int
runPgDump(const char *dbname) runPgDump(const char *dbname)
{ {
PQExpBuffer cmd = createPQExpBuffer(); PQExpBuffer cmd = createPQExpBuffer();
const char *p;
int ret; int ret;
appendPQExpBuffer(cmd, SYSTEMQUOTE "\"%s\" %s", pg_dump_bin,
pgdumpopts->data);
/* /*
* 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 * If we have a filename, use the undocumented plain-append pg_dump
* format. * format.
*/ */
if (filename) if (filename)
{ appendPQExpBuffer(cmd, " -Fa ");
#ifndef WIN32
appendPQExpBuffer(cmd, SYSTEMQUOTE"\"%s\" %s -Fa '", pg_dump_bin,
#else
appendPQExpBuffer(cmd, SYSTEMQUOTE"\"%s\" %s -Fa \"", pg_dump_bin,
#endif
pgdumpopts->data);
}
else else
{ appendPQExpBuffer(cmd, " -Fp ");
#ifndef WIN32
appendPQExpBuffer(cmd, SYSTEMQUOTE "\"%s\" %s -Fp '", pg_dump_bin,
#else
appendPQExpBuffer(cmd, SYSTEMQUOTE "\"%s\" %s -Fp \"", pg_dump_bin,
#endif
pgdumpopts->data);
}
doShellQuoting(cmd, dbname);
/* Shell quoting is not quite like SQL quoting, so can't use fmtId */
for (p = dbname; *p; p++)
{
#ifndef WIN32
if (*p == '\'')
appendPQExpBuffer(cmd, "'\"'\"'");
#else
if (*p == '"')
appendPQExpBuffer(cmd, "\\\"");
#endif
else
appendPQExpBufferChar(cmd, *p);
}
#ifndef WIN32
appendPQExpBufferChar(cmd, '\'');
#else
appendPQExpBufferChar(cmd, '"');
#endif
appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE); appendPQExpBuffer(cmd, "%s", SYSTEMQUOTE);
@ -1338,7 +1306,6 @@ runPgDump(const char *dbname)
} }
/* /*
* Make a database connection with the given parameters. An * Make a database connection with the given parameters. An
* interactive password prompt is automatically issued if required. * interactive password prompt is automatically issued if required.
@ -1527,3 +1494,38 @@ dumpTimestamp(char *msg)
localtime(&now)) != 0) localtime(&now)) != 0)
fprintf(OPF, "-- %s %s\n\n", msg, buf); fprintf(OPF, "-- %s %s\n\n", msg, buf);
} }
/*
* Append the given string to the shell command being built in the buffer,
* with suitable shell-style quoting.
*/
static void
doShellQuoting(PQExpBuffer buf, const char *str)
{
const char *p;
#ifndef WIN32
appendPQExpBufferChar(buf, '\'');
for (p = str; *p; p++)
{
if (*p == '\'')
appendPQExpBuffer(buf, "'\"'\"'");
else
appendPQExpBufferChar(buf, *p);
}
appendPQExpBufferChar(buf, '\'');
#else /* WIN32 */
appendPQExpBufferChar(buf, '"');
for (p = str; *p; p++)
{
if (*p == '"')
appendPQExpBuffer(buf, "\\\"");
else
appendPQExpBufferChar(buf, *p);
}
appendPQExpBufferChar(buf, '"');
#endif /* WIN32 */
}

View File

@ -34,7 +34,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_restore.c,v 1.89 2008/12/11 07:34:08 petere Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_restore.c,v 1.90 2009/01/05 16:54:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -51,6 +51,9 @@
#include "getopt_long.h" #include "getopt_long.h"
extern char *optarg;
extern int optind;
#ifndef HAVE_INT_OPTRESET #ifndef HAVE_INT_OPTRESET
int optreset; int optreset;
#endif #endif
@ -72,8 +75,6 @@ main(int argc, char **argv)
int exit_code; int exit_code;
Archive *AH; Archive *AH;
char *inputFileSpec; char *inputFileSpec;
extern int optind;
extern char *optarg;
static int disable_triggers = 0; static int disable_triggers = 0;
static int no_data_for_failed_tables = 0; static int no_data_for_failed_tables = 0;
static int outputNoTablespaces = 0; static int outputNoTablespaces = 0;
@ -114,6 +115,7 @@ main(int argc, char **argv)
{"disable-triggers", no_argument, &disable_triggers, 1}, {"disable-triggers", no_argument, &disable_triggers, 1},
{"no-data-for-failed-tables", no_argument, &no_data_for_failed_tables, 1}, {"no-data-for-failed-tables", no_argument, &no_data_for_failed_tables, 1},
{"no-tablespaces", no_argument, &outputNoTablespaces, 1}, {"no-tablespaces", no_argument, &outputNoTablespaces, 1},
{"role", required_argument, NULL, 2},
{"use-set-session-authorization", no_argument, &use_setsessauth, 1}, {"use-set-session-authorization", no_argument, &use_setsessauth, 1},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
@ -261,13 +263,17 @@ main(int argc, char **argv)
} }
break; break;
case '1': /* Restore data in a single transaction */
opts->single_txn = true;
opts->exit_on_error = true;
break;
case 0: case 0:
/* This covers the long options equivalent to -X xxx. */ /* This covers the long options equivalent to -X xxx. */
break; break;
case '1': /* Restore data in a single transaction */ case 2: /* SET ROLE */
opts->single_txn = true; opts->use_role = optarg;
opts->exit_on_error = true;
break; break;
default: default:
@ -405,6 +411,7 @@ usage(const char *progname)
" do not restore data of tables that could not be\n" " do not restore data of tables that could not be\n"
" created\n")); " created\n"));
printf(_(" --no-tablespaces do not dump tablespace assignments\n")); printf(_(" --no-tablespaces do not dump tablespace assignments\n"));
printf(_(" --role=ROLENAME do SET ROLE before restore\n"));
printf(_(" --use-set-session-authorization\n" printf(_(" --use-set-session-authorization\n"
" use SESSION AUTHORIZATION commands instead of\n" " use SESSION AUTHORIZATION commands instead of\n"
" OWNER TO commands\n")); " OWNER TO commands\n"));