1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

pg_dump/pg_restore now always use SET SESSION AUTHORIZATION, not \connect,

to control object ownership.  The use-set-session-authorization and
no-reconnect switches are obsolete (still accepted on the command line,
but they don't do anything).  This is a precursor to fixing handling
of CREATE SCHEMA, which will be a separate commit.
This commit is contained in:
Tom Lane
2003-09-23 22:48:53 +00:00
parent 45de72b683
commit 6767cebc6f
7 changed files with 112 additions and 244 deletions

View File

@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.25 2003/08/28 20:21:34 tgl Exp $
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.26 2003/09/23 22:48:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -62,12 +62,7 @@ typedef int (*DataDumperPtr) (Archive *AH, char *oid, void *userArg);
typedef struct _restoreOptions
{
int create; /* Issue commands to create the database */
int noOwner; /* Don't reconnect to database to match
* original object owner */
int noReconnect; /* Don't reconnect to database under any
* cirsumstances */
int use_setsessauth;/* use SET SESSSION AUTHORIZATION instead
* of \connect */
int noOwner; /* Don't try to match original object owner */
int disable_triggers; /* disable triggers during
* data-only restore */
char *superuser; /* Username to use as superuser */

View File

@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.75 2003/08/28 20:21:34 tgl Exp $
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.76 2003/09/23 22:48:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -49,8 +49,9 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
static int _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData);
static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
static void _reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te);
static void _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user);
static void _reconnectToDB(ArchiveHandle *AH, const char *dbname, const char *user);
static void _becomeUser(ArchiveHandle *AH, const char *user);
static void _becomeOwner(ArchiveHandle *AH, TocEntry *te);
static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName);
static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt);
@ -144,10 +145,6 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
* initially connected to, not the one we will create, which is very
* bad...
*/
if (ropt->create && ropt->noReconnect)
die_horribly(AH, modulename, "-C and -R are incompatible options\n");
if (ropt->create && ropt->dropSchema)
die_horribly(AH, modulename, "-C and -c are incompatible options\n");
@ -221,7 +218,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
/* We want the schema */
ahlog(AH, 1, "dropping %s %s\n", te->desc, te->tag);
/* Select owner and schema as necessary */
_reconnectAsOwner(AH, NULL, te);
_becomeOwner(AH, te);
_selectOutputSchema(AH, te->namespace);
/* Drop it */
ahprintf(AH, "%s", te->dropStmt);
@ -260,7 +257,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
if (strcmp(te->desc, "DATABASE") == 0)
{
ahlog(AH, 1, "connecting to new database \"%s\" as user \"%s\"\n", te->tag, te->owner);
_reconnectAsUser(AH, te->tag, te->owner);
_reconnectToDB(AH, te->tag, te->owner);
}
}
@ -310,11 +307,8 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
{
_disableTriggersIfNecessary(AH, te, ropt);
/*
* Reconnect if necessary (_disableTriggers may
* have reconnected)
*/
_reconnectAsOwner(AH, NULL, te);
/* Select owner and schema as necessary */
_becomeOwner(AH, te);
_selectOutputSchema(AH, te->namespace);
ahlog(AH, 1, "restoring data for table \"%s\"\n", te->tag);
@ -347,7 +341,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
}
}
te = te->next;
}
} /* end loop over TOC entries */
/*
* Now use blobs_xref (if used) to fixup any refs for tables that we
@ -439,9 +433,6 @@ _canRestoreBlobs(ArchiveHandle *AH)
static void
_disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
{
char *oldUser;
char *oldSchema;
/* This hack is only needed in a data-only restore */
if (!ropt->dataOnly || !ropt->disable_triggers)
return;
@ -450,23 +441,12 @@ _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *rop
if (te && strcmp(te->desc, "BLOBS") == 0)
return;
oldUser = strdup(AH->currUser);
oldSchema = strdup(AH->currSchema);
/*
* Become superuser if possible, since they are the only ones who can
* update pg_class. If -S was not given, but we are allowed to use
* SET SESSION AUTHORIZATION, assume the initial user identity is a
* superuser. Otherwise we just have to bull ahead anyway.
* update pg_class. If -S was not given, assume the initial user identity
* is a superuser.
*/
if (ropt->superuser)
{
_reconnectAsUser(AH, NULL, ropt->superuser);
/* be careful to preserve schema setting */
_selectOutputSchema(AH, oldSchema);
}
else if (AH->ropt->use_setsessauth)
_doSetSessionAuth(AH, NULL);
_becomeUser(AH, ropt->superuser);
ahlog(AH, 1, "disabling triggers\n");
@ -487,28 +467,11 @@ _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *rop
else
ahprintf(AH, "UPDATE pg_catalog.pg_class SET reltriggers = 0 FROM pg_catalog.pg_namespace "
"WHERE relnamespace = pg_namespace.oid AND nspname !~ '^pg_';\n\n");
/*
* Restore original user and schema state.
*/
if (ropt->superuser)
{
_reconnectAsUser(AH, NULL, oldUser);
/* be careful to preserve schema setting */
_selectOutputSchema(AH, oldSchema);
}
else if (AH->ropt->use_setsessauth)
_doSetSessionAuth(AH, oldUser);
free(oldUser);
free(oldSchema);
}
static void
_enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt)
{
char *oldUser;
char *oldSchema;
/* This hack is only needed in a data-only restore */
if (!ropt->dataOnly || !ropt->disable_triggers)
return;
@ -517,23 +480,12 @@ _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt
if (te && strcmp(te->desc, "BLOBS") == 0)
return;
oldUser = strdup(AH->currUser);
oldSchema = strdup(AH->currSchema);
/*
* Become superuser if possible, since they are the only ones who can
* update pg_class. If -S was not given, but we are allowed to use
* SET SESSION AUTHORIZATION, assume the initial user identity is a
* superuser. Otherwise we just have to bull ahead anyway.
* update pg_class. If -S was not given, assume the initial user identity
* is a superuser.
*/
if (ropt->superuser)
{
_reconnectAsUser(AH, NULL, ropt->superuser);
/* be careful to preserve schema setting */
_selectOutputSchema(AH, oldSchema);
}
else if (AH->ropt->use_setsessauth)
_doSetSessionAuth(AH, NULL);
_becomeUser(AH, ropt->superuser);
ahlog(AH, 1, "enabling triggers\n");
@ -557,20 +509,6 @@ _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt
"(SELECT pg_catalog.count(*) FROM pg_catalog.pg_trigger where pg_class.oid = tgrelid) "
"FROM pg_catalog.pg_namespace "
"WHERE relnamespace = pg_namespace.oid AND nspname !~ '^pg_';\n\n");
/*
* Restore original user and schema state.
*/
if (ropt->superuser)
{
_reconnectAsUser(AH, NULL, oldUser);
/* be careful to preserve schema setting */
_selectOutputSchema(AH, oldSchema);
}
else if (AH->ropt->use_setsessauth)
_doSetSessionAuth(AH, oldUser);
free(oldUser);
free(oldSchema);
}
/*
@ -2087,8 +2025,8 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt)
/*
* Issue a SET SESSION AUTHORIZATION command. Caller is responsible
* for updating state if appropriate. If user is NULL, the
* specification DEFAULT will be used.
* for updating state if appropriate. If user is NULL or an empty string,
* the specification DEFAULT will be used.
*/
static void
_doSetSessionAuth(ArchiveHandle *AH, const char *user)
@ -2096,11 +2034,11 @@ _doSetSessionAuth(ArchiveHandle *AH, const char *user)
PQExpBuffer cmd = createPQExpBuffer();
appendPQExpBuffer(cmd, "SET SESSION AUTHORIZATION ");
if (user)
/*
* SQL requires a string literal here. Might as well be correct.
*/
/*
* SQL requires a string literal here. Might as well be correct.
*/
if (user && *user)
appendStringLiteral(cmd, user, false);
else
appendPQExpBuffer(cmd, "DEFAULT");
@ -2126,34 +2064,17 @@ _doSetSessionAuth(ArchiveHandle *AH, const char *user)
/*
* Issue the commands to connect to the database as the specified user
* to the specified database. The database name may be NULL, then the
* current database is kept. If reconnects were disallowed by the
* user, this won't do anything.
* Issue the commands to connect to the specified database
* as the specified user.
*
* If we're currently restoring right into a database, this will
* actually establish a connection. Otherwise it puts a \connect into
* the script output.
*/
static void
_reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
_reconnectToDB(ArchiveHandle *AH, const char *dbname, const char *user)
{
if (!user || strlen(user) == 0
|| (strcmp(AH->currUser, user) == 0 && !dbname))
return; /* no need to do anything */
/*
* Use SET SESSION AUTHORIZATION if allowed and no database change
* needed
*/
if (!dbname && AH->ropt->use_setsessauth)
_doSetSessionAuth(AH, user);
else if (AH->ropt && AH->ropt->noReconnect)
{
/* When -R was given, don't do anything. */
return;
}
else if (RestoringToDB(AH))
if (RestoringToDB(AH))
ReconnectToServer(AH, dbname, user);
else
{
@ -2167,11 +2088,6 @@ _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
ahprintf(AH, qry->data);
destroyPQExpBuffer(qry);
/* don't assume we still know the output schema */
if (AH->currSchema)
free(AH->currSchema);
AH->currSchema = strdup("");
}
/*
@ -2182,21 +2098,50 @@ _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user)
free(AH->currUser);
AH->currUser = strdup(user);
/* don't assume we still know the output schema */
if (AH->currSchema)
free(AH->currSchema);
AH->currSchema = strdup("");
}
/*
* Become the specified user, and update state to avoid redundant commands
*
* NULL or empty argument is taken to mean restoring the session default
*/
static void
_becomeUser(ArchiveHandle *AH, const char *user)
{
if (!user)
user = ""; /* avoid null pointers */
if (AH->currUser && strcmp(AH->currUser, user) == 0)
return; /* no need to do anything */
_doSetSessionAuth(AH, user);
/*
* NOTE: currUser keeps track of what the imaginary session user in
* our script is
*/
if (AH->currUser)
free(AH->currUser);
AH->currUser = strdup(user);
}
/*
* Issues the commands to connect to the database (or the current one,
* if NULL) as the owner of the the given TOC entry object. If
* Become the owner of the the given TOC entry object. If
* changes in ownership are not allowed, this doesn't do anything.
*/
static void
_reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te)
_becomeOwner(ArchiveHandle *AH, TocEntry *te)
{
if (AH->ropt && AH->ropt->noOwner)
return;
_reconnectAsUser(AH, dbname, te->owner);
_becomeUser(AH, te->owner);
}
@ -2250,7 +2195,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
char *pfx;
/* Select owner and schema as necessary */
_reconnectAsOwner(AH, NULL, te);
_becomeOwner(AH, te);
_selectOutputSchema(AH, te->namespace);
if (isData)

View File

@ -12,7 +12,7 @@
* by PostgreSQL
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.348 2003/09/22 00:23:34 petere Exp $
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.349 2003/09/23 22:48:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -174,7 +174,6 @@ main(int argc, char **argv)
int outputCreate = 0;
int outputBlobs = 0;
int outputNoOwner = 0;
int outputNoReconnect = 0;
static int use_setsessauth = 0;
static int disable_triggers = 0;
char *outputSuperuser = NULL;
@ -322,8 +321,8 @@ main(int argc, char **argv)
pgport = optarg;
break;
case 'R': /* No reconnect */
outputNoReconnect = 1;
case 'R':
/* no-op, still accepted for backwards compatibility */
break;
case 's': /* dump schema only */
@ -369,7 +368,7 @@ main(int argc, char **argv)
*/
case 'X':
if (strcmp(optarg, "use-set-session-authorization") == 0)
use_setsessauth = 1;
/* no-op, still allowed for compatibility */ ;
else if (strcmp(optarg, "disable-triggers") == 0)
disable_triggers = 1;
else
@ -585,8 +584,6 @@ main(int argc, char **argv)
ropt->superuser = outputSuperuser;
ropt->create = outputCreate;
ropt->noOwner = outputNoOwner;
ropt->noReconnect = outputNoReconnect;
ropt->use_setsessauth = use_setsessauth;
ropt->disable_triggers = disable_triggers;
if (compressLevel == -1)
@ -633,18 +630,13 @@ help(const char *progname)
printf(_(" -D, --column-inserts dump data as INSERT commands with column names\n"));
printf(_(" -n, --schema=SCHEMA dump the named schema only\n"));
printf(_(" -o, --oids include OIDs in dump\n"));
printf(_(" -O, --no-owner do not output \\connect commands in plain\n"
" text format\n"));
printf(_(" -R, --no-reconnect disable ALL reconnections to the database in\n"
" plain text format\n"));
printf(_(" -O, --no-owner do not output commands to set 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(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
printf(_(" -X use-set-session-authorization, --use-set-session-authorization\n"
" output SET SESSION AUTHORIZATION commands rather\n"
" than \\connect commands\n"));
printf(_(" -X disable-triggers, --disable-triggers\n"
" disable triggers during data-only restore\n"));

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.27 2003/08/07 21:11:58 tgl Exp $
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.28 2003/09/23 22:48:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -659,8 +659,7 @@ runPgDump(const char *dbname)
const char *p;
int ret;
appendPQExpBuffer(cmd, "%s %s -X use-set-session-authorization -Fp '",
pgdumploc, pgdumpopts->data);
appendPQExpBuffer(cmd, "%s %s -Fp '", pgdumploc, pgdumpopts->data);
/* Shell quoting is not quite like SQL quoting, so can't use fmtId */
for (p = dbname; *p; p++)

View File

@ -34,7 +34,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.51 2003/08/28 20:21:34 tgl Exp $
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.52 2003/09/23 22:48:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -209,7 +209,7 @@ main(int argc, char **argv)
opts->rearrange = 1;
break;
case 'R':
opts->noReconnect = 1;
/* no-op, still accepted for backwards compatibility */
break;
case 'P': /* Function */
opts->selTypes = 1;
@ -262,7 +262,7 @@ main(int argc, char **argv)
case 'X':
if (strcmp(optarg, "use-set-session-authorization") == 0)
use_setsessauth = 1;
/* no-op, still allowed for compatibility */ ;
else if (strcmp(optarg, "disable-triggers") == 0)
disable_triggers = 1;
else
@ -290,7 +290,6 @@ main(int argc, char **argv)
else
fileSpec = NULL;
opts->use_setsessauth = use_setsessauth;
opts->disable_triggers = disable_triggers;
if (opts->formatName)
@ -378,21 +377,16 @@ usage(const char *progname)
" output from this file\n"));
printf(_(" -N, --orig-order restore in original dump order\n"));
printf(_(" -o, --oid-order restore in OID order\n"));
printf(_(" -O, --no-owner do not reconnect to database to match\n"
" object owner\n"));
printf(_(" -O, --no-owner do not output commands to set object ownership\n"));
printf(_(" -P, --function=NAME(args)\n"
" restore named function\n"));
printf(_(" -r, --rearrange rearrange output to put indexes etc. at end\n"));
printf(_(" -R, --no-reconnect disallow ALL reconnections to the database\n"));
printf(_(" -s, --schema-only restore only the schema, no data\n"));
printf(_(" -S, --superuser=NAME specify the superuser user name to use for\n"
" disabling triggers\n"));
printf(_(" -t, --table=NAME restore named table\n"));
printf(_(" -T, --trigger=NAME restore named trigger\n"));
printf(_(" -x, --no-privileges skip restoration of access privileges (grant/revoke)\n"));
printf(_(" -X use-set-session-authorization, --use-set-session-authorization\n"
" use SET SESSION AUTHORIZATION commands instead\n"
" of reconnecting, if possible\n"));
printf(_(" -X disable-triggers, --disable-triggers\n"
" disable triggers during data-only restore\n"));