From 627c0d4472fc513fbd7a2fed709ec81681f1082e Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Wed, 22 Aug 2001 20:23:24 +0000 Subject: [PATCH] Add option to output SET SESSION AUTHORIZATION commands rather than \connect, to avoid possible password prompts and such, at the drawback of having to have superuser access. --- doc/src/sgml/ref/pg_dump.sgml | 189 ++++++++++++++++++++------- doc/src/sgml/ref/pg_restore.sgml | 102 +++++++++++---- src/bin/pg_dump/pg_backup.h | 3 +- src/bin/pg_dump/pg_backup_archiver.c | 94 +++++++++---- src/bin/pg_dump/pg_backup_archiver.h | 4 +- src/bin/pg_dump/pg_backup_db.c | 41 ++++-- src/bin/pg_dump/pg_dump.c | 44 ++++++- src/bin/pg_dump/pg_dump.h | 4 +- src/bin/pg_dump/pg_restore.c | 106 ++++++++++----- 9 files changed, 437 insertions(+), 150 deletions(-) diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml index 2eec491cd4..1da554aa70 100644 --- a/doc/src/sgml/ref/pg_dump.sgml +++ b/doc/src/sgml/ref/pg_dump.sgml @@ -1,5 +1,5 @@ @@ -43,6 +43,7 @@ Postgres documentation -t table -v -x + -X keyword -Z 0...9 -h host -p port @@ -59,44 +60,56 @@ Postgres documentation - pg_dump is a utility for dumping out a - Postgres database into a script or archive - file containing query commands. The script files are in text format - and can be used to reconstruct the database, even on other machines - and other architectures. - The archive files, new with version 7.1, contain enough information for - to rebuild the database, but also - allow pg_restore to be selective about what is restored, or even to - reorder the items prior to being restored. The archive files are - also designed to be portable across architectures. + pg_dump is a utility for saving a + PostgreSQL database into a script or an + archive file. The script files are in plain text format and + contain the SQL commands required to reconstruct the database to + the state it was in at the time is was saved. They can be used to + reconstruct the database even on other machines and other + architectures, with some modifications even on other RDBMS + products. The alternative archive file formats are meant to be + used with to rebuild the database, + and they also allow pg_restore to be selective + about what is restored, or even to reorder the items prior to being + restored. The archive files are also designed to be portable across + architectures. - pg_dump - will produce the queries necessary to re-generate all - user-defined types, functions, tables, indexes, aggregates, and - operators. In addition, all the data is copied out in text format so - that it can be readily copied in again, as well as imported into tools - for editing. + pg_dump will save the information necessary to + re-generate all user-defined types, functions, tables, indexes, + aggregates, and operators. In addition, all the data is copied out + in text format so that it can be readily copied in again, as well + as imported into tools for editing. pg_dump is useful for dumping out the contents of a database to move from one - Postgres installation to another. After running - pg_dump, - one should examine the output for any warnings, especially - in light of the limitations listed below. + Postgres installation to another. - When used with one of the alternate file formats and combined with - pg_restore, it provides a flexible archival - and transfer mechanism. pg_dump can be used - to backup an entire database, then pg_restore - can be used to examine the archive and/or select which parts of the - database are to be restored. - See the documentation for details. + When used with one of the archive file formats and combined with + pg_restore, it provides a flexible archival and + transfer mechanism. pg_dump can be used to + backup an entire database, then pg_restore can + be used to examine the archive and/or select which parts of the + database are to be restored. See the documentation for details. + + + + While running pg_dump, one should examine the + output for any warnings (printed on standard error), especially in + light of the limitations listed below. + + + + pg_dump makes consistent backups even if the + database is being used concurrently. pg_dump + does not block other users accessing the database (readers or + writers). @@ -141,7 +154,7 @@ Postgres documentation --clean - Dump commands to clean (drop) the schema prior to (the + Output commands to clean (drop) the schema prior to (the commands for) creating it. @@ -162,9 +175,10 @@ Postgres documentation --inserts - Dump data as proper INSERT commands (not - COPY). This will make restoration very - slow. + Dump data as proper INSERT commands (rather + than COPY). This will make restoration very + slow, but it makes the archives more portable to other RDBMS + packages. @@ -189,7 +203,8 @@ Postgres documentation --file=file - Send output to the specified file. + Send output to the specified file. If this is omitted, the + standard output is used. @@ -199,7 +214,8 @@ Postgres documentation --format=format - Format can be one of the following: + Selects the format of the output. + format can be one of the following: @@ -289,7 +305,10 @@ Postgres documentation --oids - Dump object identifiers (OIDs) for every table. + Dump object identifiers (OIDs) 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. @@ -299,11 +318,22 @@ Postgres documentation --no-owner - In plain text output mode, do not set object ownership to - match the original database. Typically, - pg_dump issues - (psql-specific) \connect - statements to set ownership of schema elements. + In plain text output mode, do not output commands to set the + object ownership to match the original database. Typically, + pg_dump issues + (psql-specific) \connect + statements to set ownership of schema elements. See also + under and . Note that + does not prevent all reconnections to the + database, only the ones that are exclusively used for + ownership adjustments. + + + + This option is only meaningful for the plain text format. For + the other formats, you need to specify the option when you + call pg_restore. @@ -313,8 +343,27 @@ Postgres documentation --no-reconnect - In plain text output mode, prohibit pg_dump - from issuing any \connect statements. + In plain text output mode, prohibit pg_dump + from outputting a script that would require reconnections to + the database while being restored. An average restoration + script usually has to reconnect several times as different + users to set the original ownerships of the objects. This + option is a rather blunt instrument because it makes + pg_dump lose this ownership information, + unless you use the option. + + + + One possible reason why reconnections during restore might not + be desired is if the access to the database requires manual + interaction (e.g., passwords). + + + + This option is only meaningful for the plain text format. For + the other formats, you need to specify the option when you + call pg_restore. @@ -334,8 +383,10 @@ Postgres documentation --superuser=username - Specify the superuser user name to use when disabling triggers and/or - setting ownership of schema elements. + The scripts or archives created by pg_dump + need to have superuser access in certain cases, such as when + disabling triggers or setting ownership of schema elements. + This option specifies the user name to use for those cases. @@ -366,8 +417,42 @@ Postgres documentation --no-acl - Prevent dumping of access privileges (grant/revoke commands) - and table ownership information. + Prevent dumping of access privileges (grant/revoke commands). + + + + + + -X use-set-session-authorization + --use-set-session-authorization + + + Normally, if a (plain text mode) script generated by + pg_dump must alter the current database + user (e.g., to set correct object ownerships), it uses the + \connect command. + This command actually opens a new connection, which might + require manual interaction (e.g., passwords). If you use the + , then + pg_dump will instead output commands. This has + the same effect, but it requires that the user restoring the + database from the generated script be a database superuser. + This option effectively overrides the + option. + + + + Since is a + standard SQL command, whereas \connect only + works in , this option also enhances + the theoretical portability of the output script. + + + + This option is only meaningful for the plain text format. For + the other formats, you need to specify the option when you + call pg_restore. @@ -442,7 +527,6 @@ Postgres documentation - Diagnostics @@ -551,6 +635,17 @@ connectDBStart() -- connect() failed: No such file or directory + + History + + + The pg_dump utility first appeared in + Postgres95 release 0.02. The + non-plain-text output formats were introduced in + PostgreSQL 7.1. + + + See Also diff --git a/doc/src/sgml/ref/pg_restore.sgml b/doc/src/sgml/ref/pg_restore.sgml index 0acb3fb151..22f264ceac 100644 --- a/doc/src/sgml/ref/pg_restore.sgml +++ b/doc/src/sgml/ref/pg_restore.sgml @@ -1,4 +1,4 @@ - + @@ -44,6 +44,7 @@ -T trigger -v -x + -X keyword -h host -p port -U username @@ -60,38 +61,54 @@ pg_restore is a utility for restoring a - Postgres database dumped by - in one of the non-plain-text formats. + Postgres database from an archive + created by in one of the non-plain-text + formats. - The archive files, new with the 7.1 release, contain enough information for - pg_restore to rebuild the database, but also allow - pg_restore to be selective about what is restored, - or even to reorder the items prior to being restored. The archive files are designed - to be portable across architectures. pg_dump will - produce the queries necessary to re-generate all user-defined types, functions, - tables, indexes, aggregates, and operators. In addition, all the data is copied - out (in text format for scripts) so that it can be readily copied in again. + The archive files contain information for + pg_restore to rebuild the database, but also + allow pg_restore to be selective about what is + restored, or even to reorder the items prior to being restored. The + archive files are designed to be portable across architectures. It + will issue the commands necessary to re-generate all user-defined + types, functions, tables, indexes, aggregates, and operators, as + well as the data in the tables. - pg_restore reads the archive file and outputs the appropriate - SQL in the required order based on the command parameters. Obviously, it can not restore - information that is not present in the dump file; so if the dump is made using the - dump data as INSERTs option, pg_restore will not be able to - load the data using COPY statements. + pg_restore can operate in two modes: If a + database name is specified, the archive is restored directly into + the database. Otherwise, a script containing the SQL commands + necessary to rebuild the database is created (and written to a file + or standard output), similar to the ones created by the + pg_dump plain text format. Some of the options + controlling the script output are therefore analogous to + pg_dump. - The most flexible output file format is the custom format (). It allows for - selection and reordering of all archived items, and is compressed by default. The tar - format () is not compressed and it is not possible to reorder - data when loading, but it is otherwise quite flexible. + Obviously, pg_restore cannot restore information + that is not present in the archive file; for instance, if the + archive was made using the dump data as + INSERTs option, + pg_restore will not be able to load the data + using COPY statements. - To reorder the items, it is first necessary to dump the contents of the archive: + The most flexible output file format is the custom + format (). It allows for selection and + reordering of all archived items, and is compressed by default. The + tar format () is not + compressed and it is not possible to reorder data when loading, but + it is otherwise quite flexible. + + + + To reorder the items, it is first necessary to dump the table of + contents of the archive: $ pg_restore archive.file -l > archive.list @@ -346,8 +363,20 @@ --no-reconnect - Prohibit pg_restore from issuing any \connect - statements or reconnecting to the database if directly connected. + While restoring an archive, pg_restore + typically has to reconnect to the database several times with + different user names to set the correct ownership of the + created objects. If this is undesriable (e.g., because manual + interaction (passwords) would be necessary for each + reconnection), this option prevents + pg_restore from issuing any reconnection + requests. (A connection request while in plain text mode, not + connected to a database, is made by putting out a \connect command.) + However, this option is a rather blunt instrument because it + makes pg_restore lose all object ownership + information, unless you use the + option. @@ -414,6 +443,25 @@ + + -X use-set-session-authorization + --use-set-session-authorization + + + Normally, if restoring an archive requires altering the + current database user (e.g., to set correct object + ownerships), a new connection to the database must be openend, + which might require manual interaction (e.g., passwords). If + you use the , + then pg_restore will instead use the command. This has + the same effect, but it requires that the user restoring the + archive is a database superuser. This option effectively + overrides the option. + + + + @@ -592,6 +640,14 @@ connectDBStart() -- connect() failed: No such file or directory + + History + + + The pg_restore utility first appeared in + PostgreSQL 7.1. + + See Also diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index 7e555957eb..282738d882 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.13 2001/06/27 21:21:37 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.14 2001/08/22 20:23:23 petere Exp $ * * Modifications - 28-Jun-2000 - pjw@rhyme.com.au * @@ -85,6 +85,7 @@ typedef struct _restoreOptions * original object owner */ int noReconnect; /* Don't reconnect to database under any * cirsumstances */ + int use_setsessauth; /* use SET SESSSION AUTHORIZATION instead of \connect */ char *superuser; /* Username to use as superuser */ int dataOnly; int dropSchema; diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 982cabbcf2..4ada30994f 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.31 2001/08/19 22:17:03 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.32 2001/08/22 20:23:23 petere Exp $ * * Modifications - 28-Jun-2000 - pjw@rhyme.com.au * @@ -78,7 +78,7 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt, static int _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData); static void _reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te); -static void _reconnectAsUser(ArchiveHandle *AH, const char *dbname, char *user); +static void _reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user); static int _tocEntryRequired(TocEntry *te, RestoreOptions *ropt); static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); @@ -251,7 +251,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt) /* We want the schema */ ahlog(AH, 1, "dropping %s %s\n", te->desc, te->name); /* Reconnect if necessary */ - _reconnectAsOwner(AH, "-", te); + _reconnectAsOwner(AH, NULL, te); /* Drop it */ ahprintf(AH, "%s", te->dropStmt); } @@ -283,7 +283,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt) if ((reqs & 1) != 0) /* We want the schema */ { /* Reconnect if necessary */ - _reconnectAsOwner(AH, "-", te); + _reconnectAsOwner(AH, NULL, te); ahlog(AH, 1, "creating %s %s\n", te->desc, te->name); _printTocEntry(AH, te, ropt, false); @@ -345,7 +345,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt) * Reconnect if necessary (_disableTriggers may have * reconnected) */ - _reconnectAsOwner(AH, "-", te); + _reconnectAsOwner(AH, NULL, te); ahlog(AH, 1, "restoring data for table %s\n", te->name); @@ -448,6 +448,10 @@ NewRestoreOptions(void) return opts; } +/* + * Returns true if we're restoring directly to the database (and + * aren't just making a psql script that can do the restoration). + */ static int _restoringToDB(ArchiveHandle *AH) { @@ -486,7 +490,7 @@ _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *rop */ if (ropt->noOwner) oldUser = strdup(ConnectedUser(AH)); - _reconnectAsUser(AH, "-", ropt->superuser); + _reconnectAsUser(AH, NULL, ropt->superuser); } } @@ -514,7 +518,7 @@ _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *rop */ if (ropt->noOwner && oldUser) { - _reconnectAsUser(AH, "-", oldUser); + _reconnectAsUser(AH, NULL, oldUser); free(oldUser); } } @@ -546,7 +550,7 @@ _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt if (ropt->noOwner) oldUser = strdup(ConnectedUser(AH)); - _reconnectAsUser(AH, "-", ropt->superuser); + _reconnectAsUser(AH, NULL, ropt->superuser); } } @@ -577,7 +581,7 @@ _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt */ if (ropt->noOwner && oldUser) { - _reconnectAsUser(AH, "-", oldUser); + _reconnectAsUser(AH, NULL, oldUser); free(oldUser); } } @@ -1895,26 +1899,71 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt) return res; } -static void -_reconnectAsUser(ArchiveHandle *AH, const char *dbname, char *user) -{ - if (AH->ropt && AH->ropt->noReconnect) - return; - if (user && strlen(user) != 0 - && ((strcmp(AH->currUser, user) != 0) || (strcmp(dbname, "-") != 0))) +/* + * 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. + * + * If we're currently restoring right into a database, this will + * actuall establish a connection. Otherwise it puts a \connect into + * the script output. + */ +static void +_reconnectAsUser(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) { if (RestoringToDB(AH)) - ReconnectDatabase(AH, dbname, user); - else - ahprintf(AH, "\\connect %s %s\n", dbname, user); - if (AH->currUser) - free(AH->currUser); + { + PQExpBuffer qry = createPQExpBuffer(); + PGresult *res; - AH->currUser = strdup(user); + appendPQExpBuffer(qry, "SET SESSION AUTHORIZATION '%s';", user); + res = PQexec(AH->connection, qry->data); + + if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) + die_horribly(AH, modulename, "could not set session user to %s: %s", + user, PQerrorMessage(AH->connection)); + + PQclear(res); + destroyPQExpBuffer(qry); + } + else + ahprintf(AH, "SET SESSION AUTHORIZATION '%s';\n\n", user); } + /* When -R was given, don't do anything. */ + else if (AH->ropt && AH->ropt->noReconnect) + return; + + else if (RestoringToDB(AH)) + ReconnectToServer(AH, dbname, user); + else + /* FIXME: does not handle mixed case user names */ + ahprintf(AH, "\\connect %s %s\n\n", + dbname ? dbname : "-", + user ? 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 + * changes in ownership are not allowed, this doesn't do anything. + */ static void _reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te) { @@ -1924,6 +1973,7 @@ _reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te) _reconnectAsUser(AH, dbname, te->owner); } + static int _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData) { diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index 16a1c06dfe..fee94d83b0 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -17,7 +17,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.36 2001/07/03 20:21:48 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.37 2001/08/22 20:23:23 petere Exp $ * * Modifications - 28-Jun-2000 - pjw@rhyme.com.au * - Initial version. @@ -310,7 +310,7 @@ extern int isValidTarHeader(char *header); extern OutputContext SetOutput(ArchiveHandle *AH, char *filename, int compression); extern void ResetOutput(ArchiveHandle *AH, OutputContext savedContext); extern int RestoringToDB(ArchiveHandle *AH); -extern int ReconnectDatabase(ArchiveHandle *AH, const char *dbname, char *newUser); +extern int ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *newUser); extern int UserIsSuperuser(ArchiveHandle *AH, char *user); extern char *ConnectedUser(ArchiveHandle *AH); extern int ConnectedUserIsSuperuser(ArchiveHandle *AH); diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c index f08a0d3085..3bc49e4435 100644 --- a/src/bin/pg_dump/pg_backup_db.c +++ b/src/bin/pg_dump/pg_backup_db.c @@ -5,7 +5,7 @@ * Implements the basic DB functions used by the archiver. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.23 2001/08/12 19:02:39 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.24 2001/08/22 20:23:23 petere Exp $ * * NOTES * @@ -40,7 +40,7 @@ static const char *modulename = gettext_noop("archiver (db)"); static void _check_database_version(ArchiveHandle *AH, bool ignoreVersion); -static PGconn *_connectDB(ArchiveHandle *AH, const char *newdbname, char *newUser); +static PGconn *_connectDB(ArchiveHandle *AH, const char *newdbname, const char *newUser); static int _executeSqlCommand(ArchiveHandle *AH, PGconn *conn, PQExpBuffer qry, char *desc); static void notice_processor(void *arg, const char *message); @@ -226,29 +226,44 @@ ConnectedUser(ArchiveHandle *AH) } /* - * Reconnect the DB associated with the archive handle + * Reconnect to the server. If dbname is not NULL, use that database, + * else the one associated with the archive handle. If username is + * not NULL, use that user name, else the one from the handle. If + * both the database and the user and match the existing connection + * already, nothing will be done. + * + * Returns 1 in any case. */ int -ReconnectDatabase(ArchiveHandle *AH, const char *newdbname, char *newUser) +ReconnectToServer(ArchiveHandle *AH, const char *dbname, const char *username) { PGconn *newConn; - char *dbname; + const char *newdbname; + const char *newusername; - if (!newdbname || (strcmp(newdbname, "-") == 0)) - dbname = PQdb(AH->connection); + if (!dbname) + newdbname = PQdb(AH->connection); else - dbname = (char *) newdbname; + newdbname = dbname; + + if (!username) + newusername = PQuser(AH->connection); + else + newusername = username; /* Let's see if the request is already satisfied */ - if (strcmp(PQuser(AH->connection), newUser) == 0 && strcmp(newdbname, PQdb(AH->connection)) == 0) + if (strcmp(newusername, PQuser(AH->connection)) == 0 + && strcmp(newdbname, PQdb(AH->connection)) == 0) return 1; - newConn = _connectDB(AH, dbname, newUser); + newConn = _connectDB(AH, newdbname, newusername); PQfinish(AH->connection); AH->connection = newConn; + free(AH->username); - AH->username = strdup(newUser); + AH->username = strdup(newusername); + /* XXX Why don't we update AH->dbname? */ return 1; } @@ -257,7 +272,7 @@ ReconnectDatabase(ArchiveHandle *AH, const char *newdbname, char *newUser) * Connect to the db again. */ static PGconn * -_connectDB(ArchiveHandle *AH, const char *reqdb, char *requser) +_connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser) { int need_pass; PGconn *newConn; @@ -267,7 +282,7 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, char *requser) char *newdb; char *newuser; - if (!reqdb || (strcmp(reqdb, "-") == 0)) + if (!reqdb) newdb = PQdb(AH->connection); else newdb = (char *) reqdb; diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 56067a34ee..f81439e203 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -22,7 +22,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.223 2001/08/19 22:17:03 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.224 2001/08/22 20:23:23 petere Exp $ * *------------------------------------------------------------------------- */ @@ -167,6 +167,9 @@ help(const char *progname) " -v, --verbose verbose mode\n" " -W, --password force password prompt (should happen automatically)\n" " -x, --no-privileges do not dump privileges (grant/revoke)\n" + " -X use-set-session-authorization, --use-set-session-authorization\n" + " output SET SESSION AUTHORIZATION commands rather\n" + " than \\connect commands\n" " -Z, --compress {0-9} compression level for compressed formats\n" )); #else @@ -198,6 +201,9 @@ help(const char *progname) " -v verbose mode\n" " -W force password prompt (should happen automatically)\n" " -x do not dump privileges (grant/revoke)\n" + " -X use-set-session-authorization\n" + " output SET SESSION AUTHORIZATION commands rather\n" + " than \\connect commands\n" " -Z {0-9} compression level for compressed formats\n" )); #endif @@ -628,6 +634,7 @@ main(int argc, char **argv) int outputBlobs = 0; int outputNoOwner = 0; int outputNoReconnect = 0; + static int use_setsessauth = 0; char *outputSuperuser = NULL; RestoreOptions *ropt; @@ -661,7 +668,11 @@ main(int argc, char **argv) {"no-acl", no_argument, NULL, 'x'}, {"compress", required_argument, NULL, 'Z'}, {"help", no_argument, NULL, '?'}, - {"version", no_argument, NULL, 'V'} + {"version", no_argument, NULL, 'V'}, + + /* the following options don't have an equivalent short option + letter, but are available as '-X long-name' */ + {"use-set-session-authorization", no_argument, &use_setsessauth, 1} }; int optindex; @@ -709,9 +720,9 @@ main(int argc, char **argv) } #ifdef HAVE_GETOPT_LONG - while ((c = getopt_long(argc, argv, "abcCdDf:F:h:inNoOp:RsS:t:uU:vWxzZ:V?", long_options, &optindex)) != -1) + while ((c = getopt_long(argc, argv, "abcCdDf:F:h:inNoOp:RsS:t:uU:vWxX:zZ:V?", long_options, &optindex)) != -1) #else - while ((c = getopt(argc, argv, "abcCdDf:F:h:inNoOp:RsS:t:uU:vWxzZ:V?-")) != -1) + while ((c = getopt(argc, argv, "abcCdDf:F:h:inNoOp:RsS:t:uU:vWxX:zZ:V?-")) != -1) #endif { @@ -851,6 +862,26 @@ main(int argc, char **argv) aclsSkip = true; break; + /* + * Option letters were getting scarce, so I invented + * this new scheme: '-X feature' turns on some + * feature. Compare to the -f option in GCC. You + * should also add an equivalent GNU-style option + * --feature. Features that require arguments should + * use '-X feature=foo'. + */ + case 'X': + if (strcmp(optarg, "use-set-session-authorization")==0) + use_setsessauth = 1; + else + { + fprintf(stderr, + gettext("%s: invalid -X option -- %s\n"), + progname, optarg); + fprintf(stderr, gettext("Try '%s --help' for more information.\n"), progname); + exit(1); + } + break; case 'Z': /* Compression Level */ compressLevel = atoi(optarg); break; @@ -863,6 +894,10 @@ main(int argc, char **argv) progname); exit(1); break; +#else + /* This covers the long options equivalent to -X xxx. */ + case 0: + break; #endif default: fprintf(stderr, gettext("Try '%s --help' for more information.\n"), progname); @@ -1040,6 +1075,7 @@ main(int argc, char **argv) ropt->create = outputCreate; ropt->noOwner = outputNoOwner; ropt->noReconnect = outputNoReconnect; + ropt->use_setsessauth = use_setsessauth; if (outputSuperuser) ropt->superuser = outputSuperuser; diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 4580f268b0..aff3bc7ea0 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_dump.h,v 1.69 2001/08/10 18:57:38 tgl Exp $ + * $Id: pg_dump.h,v 1.70 2001/08/22 20:23:23 petere Exp $ * * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2 * @@ -193,7 +193,7 @@ typedef struct _oprInfo } OprInfo; /* global decls */ -extern bool g_force_quotes; /* double-quotes for identifiers flag */ +extern bool force_quotes; /* double-quotes for identifiers flag */ extern bool g_verbose; /* verbose flag */ extern Oid g_last_builtin_oid; /* value of the last builtin oid */ extern Archive *g_fout; /* the script file */ diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c index 3ba07e848b..0bff04903c 100644 --- a/src/bin/pg_dump/pg_restore.c +++ b/src/bin/pg_dump/pg_restore.c @@ -34,7 +34,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.24 2001/08/19 22:17:03 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.25 2001/08/22 20:23:24 petere Exp $ * * Modifications - 28-Jun-2000 - pjw@rhyme.com.au * @@ -81,39 +81,6 @@ static char *_cleanupName(char *name); typedef struct option optType; -#ifdef HAVE_GETOPT_LONG -struct option cmdopts[] = { - {"clean", 0, NULL, 'c'}, - {"create", 0, NULL, 'C'}, - {"data-only", 0, NULL, 'a'}, - {"dbname", 1, NULL, 'd'}, - {"file", 1, NULL, 'f'}, - {"format", 1, NULL, 'F'}, - {"function", 1, NULL, 'P'}, - {"host", 1, NULL, 'h'}, - {"ignore-version", 0, NULL, 'i'}, - {"index", 1, NULL, 'I'}, - {"list", 0, NULL, 'l'}, - {"no-privileges", 0, NULL, 'x'}, - {"no-acl", 0, NULL, 'x'}, - {"no-owner", 0, NULL, 'O'}, - {"no-reconnect", 0, NULL, 'R'}, - {"port", 1, NULL, 'p'}, - {"oid-order", 0, NULL, 'o'}, - {"orig-order", 0, NULL, 'N'}, - {"password", 0, NULL, 'W'}, - {"rearrange", 0, NULL, 'r'}, - {"schema-only", 0, NULL, 's'}, - {"superuser", 1, NULL, 'S'}, - {"table", 1, NULL, 't'}, - {"trigger", 1, NULL, 'T'}, - {"use-list", 1, NULL, 'L'}, - {"username", 1, NULL, 'U'}, - {"verbose", 0, NULL, 'v'}, - {NULL, 0, NULL, 0} -}; - -#endif int main(int argc, char **argv) @@ -124,6 +91,45 @@ main(int argc, char **argv) char *fileSpec = NULL; extern int optind; extern char *optarg; + static int use_setsessauth = 0; + +#ifdef HAVE_GETOPT_LONG + struct option cmdopts[] = { + {"clean", 0, NULL, 'c'}, + {"create", 0, NULL, 'C'}, + {"data-only", 0, NULL, 'a'}, + {"dbname", 1, NULL, 'd'}, + {"file", 1, NULL, 'f'}, + {"format", 1, NULL, 'F'}, + {"function", 1, NULL, 'P'}, + {"host", 1, NULL, 'h'}, + {"ignore-version", 0, NULL, 'i'}, + {"index", 1, NULL, 'I'}, + {"list", 0, NULL, 'l'}, + {"no-privileges", 0, NULL, 'x'}, + {"no-acl", 0, NULL, 'x'}, + {"no-owner", 0, NULL, 'O'}, + {"no-reconnect", 0, NULL, 'R'}, + {"port", 1, NULL, 'p'}, + {"oid-order", 0, NULL, 'o'}, + {"orig-order", 0, NULL, 'N'}, + {"password", 0, NULL, 'W'}, + {"rearrange", 0, NULL, 'r'}, + {"schema-only", 0, NULL, 's'}, + {"superuser", 1, NULL, 'S'}, + {"table", 1, NULL, 't'}, + {"trigger", 1, NULL, 'T'}, + {"use-list", 1, NULL, 'L'}, + {"username", 1, NULL, 'U'}, + {"verbose", 0, NULL, 'v'}, + + /* the following options don't have an equivalent short option + letter, but are available as '-X long-name' */ + {"use-set-session-authorization", no_argument, &use_setsessauth, 1}, + {NULL, 0, NULL, 0} + }; +#endif /* HAVE_GETOPT_LONG */ + #ifdef ENABLE_NLS setlocale(LC_ALL, ""); @@ -153,9 +159,9 @@ main(int argc, char **argv) } #ifdef HAVE_GETOPT_LONG - while ((c = getopt_long(argc, argv, "acCd:f:F:h:i:lL:NoOp:P:rRsS:t:T:uU:vWx", cmdopts, NULL)) != EOF) + while ((c = getopt_long(argc, argv, "acCd:f:F:h:i:lL:NoOp:P:rRsS:t:T:uU:vWxX:", cmdopts, NULL)) != EOF) #else - while ((c = getopt(argc, argv, "acCd:f:F:h:i:lL:NoOp:P:rRsS:t:T:uU:vWx")) != -1) + while ((c = getopt(argc, argv, "acCd:f:F:h:i:lL:NoOp:P:rRsS:t:T:uU:vWxX:")) != -1) #endif { switch (c) @@ -267,6 +273,26 @@ main(int argc, char **argv) case 'x': /* skip ACL dump */ opts->aclsSkip = 1; break; + + case 'X': + if (strcmp(optarg, "use-set-session-authorization")==0) + use_setsessauth = 1; + else + { + fprintf(stderr, + gettext("%s: invalid -X option -- %s\n"), + progname, optarg); + fprintf(stderr, gettext("Try '%s --help' for more information.\n"), progname); + exit(1); + } + break; + +#ifdef HAVE_GETOPT_LONG + /* This covers the long options equivalent to -X xxx. */ + case 0: + break; +#endif + default: fprintf(stderr, gettext("Try '%s --help' for more information.\n"), progname); exit(1); @@ -278,6 +304,8 @@ main(int argc, char **argv) else fileSpec = NULL; + opts->use_setsessauth = use_setsessauth; + if (opts->formatName) { @@ -381,6 +409,9 @@ usage(const char *progname) " -v, --verbose verbose mode\n" " -W, --password force password prompt (should happen automatically)\n" " -x, --no-privileges skip restoration of access privileges (grant/revoke)\n" + " -X use-set-session-authorization, --use-set-session-authorization\n" + " use SET SESSION AUTHORIZATION commands instead\n" + " of reconnecting, if possible\n" )); #else /* not HAVE_GETOPT_LONG */ @@ -414,6 +445,9 @@ usage(const char *progname) " -v verbose mode\n" " -W force password prompt (should happen automatically)\n" " -x skip restoration of access privileges (grant/revoke)\n" + " -X use-set-session-authorization\n" + " use SET SESSION AUTHORIZATION commands instead\n" + " of reconnecting, if possible\n" )); #endif puts(gettext("If no input file name is supplied, then standard input is used.\n"));