diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml index 2eec491cd42ee8f294f0274caa53a0b67fcf25a6..1da554aa70e5b31c4e28e20209c53a0d7db8f95c 100644 --- a/doc/src/sgml/ref/pg_dump.sgml +++ b/doc/src/sgml/ref/pg_dump.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.34 2001/08/12 19:02:39 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_dump.sgml,v 1.35 2001/08/22 20:23:23 petere Exp $ Postgres documentation --> @@ -43,6 +43,7 @@ Postgres documentation <arg>-t <replaceable>table</replaceable></arg> <arg>-v</arg> <arg>-x</arg> + <arg>-X <replaceable>keyword</replaceable></arg> <arg>-Z <replaceable>0...9</replaceable></arg> <arg>-h <replaceable>host</replaceable></arg> <arg>-p <replaceable>port</replaceable></arg> @@ -59,44 +60,56 @@ Postgres documentation </title> <para> - <command>pg_dump</command> is a utility for dumping out a - <productname>Postgres</productname> 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 - <xref linkend="app-pgrestore"> to rebuild the database, but also - allow <command>pg_restore</command> 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. + <command>pg_dump</command> is a utility for saving a + <productname>PostgreSQL</productname> 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 <xref linkend="app-pgrestore"> to rebuild the database, + and they also allow <command>pg_restore</command> 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. </para> <para> - <command>pg_dump</command> - 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. + <command>pg_dump</command> 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. </para> <para> <command>pg_dump</command> is useful for dumping out the contents of a database to move from one - <productname>Postgres</productname> installation to another. After running - <command>pg_dump</command>, - one should examine the output for any warnings, especially - in light of the limitations listed below. + <productname>Postgres</productname> installation to another. </para> <para> - When used with one of the alternate file formats and combined with - <command>pg_restore</command>, it provides a flexible archival - and transfer mechanism. <command>pg_dump</command> can be used - to backup an entire database, then <command>pg_restore</command> - can be used to examine the archive and/or select which parts of the - database are to be restored. - See the <xref linkend="app-pgrestore"> documentation for details. + When used with one of the archive file formats and combined with + <command>pg_restore</command>, it provides a flexible archival and + transfer mechanism. <command>pg_dump</command> can be used to + backup an entire database, then <command>pg_restore</command> can + be used to examine the archive and/or select which parts of the + database are to be restored. See the <xref + linkend="app-pgrestore"> documentation for details. + </para> + + <para> + While running <command>pg_dump</command>, one should examine the + output for any warnings (printed on standard error), especially in + light of the limitations listed below. + </para> + + <para> + <command>pg_dump</command> makes consistent backups even if the + database is being used concurrently. <command>pg_dump</command> + does not block other users accessing the database (readers or + writers). </para> <refsect2 id="pg-dump-options"> @@ -141,7 +154,7 @@ Postgres documentation <term>--clean</term> <listitem> <para> - Dump commands to clean (drop) the schema prior to (the + Output commands to clean (drop) the schema prior to (the commands for) creating it. </para> </listitem> @@ -162,9 +175,10 @@ Postgres documentation <term>--inserts</term> <listitem> <para> - Dump data as proper <command>INSERT</command> commands (not - <command>COPY</command>). This will make restoration very - slow. + Dump data as proper <command>INSERT</command> commands (rather + than <command>COPY</command>). This will make restoration very + slow, but it makes the archives more portable to other RDBMS + packages. </para> </listitem> </varlistentry> @@ -189,7 +203,8 @@ Postgres documentation <term>--file=<replaceable class="parameter">file</replaceable></term> <listitem> <para> - Send output to the specified file. + Send output to the specified file. If this is omitted, the + standard output is used. </para> </listitem> </varlistentry> @@ -199,7 +214,8 @@ Postgres documentation <term>--format=<replaceable class="parameter">format</replaceable></term> <listitem> <para> - Format can be one of the following: + Selects the format of the output. + <replaceable>format</replaceable> can be one of the following: <variablelist> <varlistentry> @@ -289,7 +305,10 @@ Postgres documentation <term>--oids</term> <listitem> <para> - Dump object identifiers (<acronym>OID</acronym>s) for every table. + Dump object identifiers (<acronym>OID</acronym>s) for every + table. Use this option if your application references the oid + columns in some way (e.g., in a foreign key constraint). + Otherwise, this option should not be used. </para> </listitem> </varlistentry> @@ -299,11 +318,22 @@ Postgres documentation <term>--no-owner</term> <listitem> <para> - In plain text output mode, do not set object ownership to - match the original database. Typically, - <command>pg_dump</command> issues - (<command>psql</command>-specific) <command>\connect</command> - 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, + <command>pg_dump</command> issues + (<command>psql</command>-specific) <command>\connect</command> + statements to set ownership of schema elements. See also + under <option>-R</option> and <option>-X + use-set-session-authorization</option>. Note that + <option>-O</option> does not prevent all reconnections to the + database, only the ones that are exclusively used for + ownership adjustments. + </para> + + <para> + This option is only meaningful for the plain text format. For + the other formats, you need to specify the option when you + call <command>pg_restore</command>. </para> </listitem> </varlistentry> @@ -313,8 +343,27 @@ Postgres documentation <term>--no-reconnect</term> <listitem> <para> - In plain text output mode, prohibit <command>pg_dump</command> - from issuing any <command>\connect</command> statements. + In plain text output mode, prohibit <command>pg_dump</command> + 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 + <command>pg_dump</command> lose this ownership information, + <emphasis>unless</emphasis> you use the <option>-X + use-set-session-authorization</option> option. + </para> + + <para> + One possible reason why reconnections during restore might not + be desired is if the access to the database requires manual + interaction (e.g., passwords). + </para> + + <para> + This option is only meaningful for the plain text format. For + the other formats, you need to specify the option when you + call <command>pg_restore</command>. </para> </listitem> </varlistentry> @@ -334,8 +383,10 @@ Postgres documentation <term>--superuser=<replaceable class="parameter">username</replaceable></term> <listitem> <para> - Specify the superuser user name to use when disabling triggers and/or - setting ownership of schema elements. + The scripts or archives created by <command>pg_dump</command> + 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. </para> </listitem> </varlistentry> @@ -366,8 +417,42 @@ Postgres documentation <term>--no-acl</term> <listitem> <para> - Prevent dumping of access privileges (grant/revoke commands) - and table ownership information. + Prevent dumping of access privileges (grant/revoke commands). + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>-X use-set-session-authorization</term> + <term>--use-set-session-authorization</term> + <listitem> + <para> + Normally, if a (plain text mode) script generated by + <command>pg_dump</command> must alter the current database + user (e.g., to set correct object ownerships), it uses the + <xref linkend="app-psql"> <command>\connect</command> command. + This command actually opens a new connection, which might + require manual interaction (e.g., passwords). If you use the + <option>-X use-set-session-authorization</option>, then + <command>pg_dump</command> will instead output <xref + linkend="sql-set-session-authorization"> 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>-R</option> + option. + </para> + + <para> + Since <xref linkend="sql-set-session-authorization"> is a + standard SQL command, whereas <command>\connect</command> only + works in <xref linkend="app-psql">, this option also enhances + the theoretical portability of the output script. + </para> + + <para> + This option is only meaningful for the plain text format. For + the other formats, you need to specify the option when you + call <command>pg_restore</command>. </para> </listitem> </varlistentry> @@ -442,7 +527,6 @@ Postgres documentation </refsect1> - <refsect1 id="app-pgdump-diagnostics"> <title>Diagnostics</title> @@ -551,6 +635,17 @@ connectDBStart() -- connect() failed: No such file or directory </refsect1> + <refsect1> + <title>History</title> + + <para> + The <command>pg_dump</command> utility first appeared in + <application>Postgres95 release 0.02</application>. The + non-plain-text output formats were introduced in + <application>PostgreSQL 7.1</application>. + </para> + </refsect1> + <refsect1> <title>See Also</title> diff --git a/doc/src/sgml/ref/pg_restore.sgml b/doc/src/sgml/ref/pg_restore.sgml index 0acb3fb1512503e970a7505c5ea354f1009b5f43..22f264ceac18a60a638c60519c9459def725f12e 100644 --- a/doc/src/sgml/ref/pg_restore.sgml +++ b/doc/src/sgml/ref/pg_restore.sgml @@ -1,4 +1,4 @@ -<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_restore.sgml,v 1.13 2001/08/12 19:02:39 petere Exp $ --> +<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/pg_restore.sgml,v 1.14 2001/08/22 20:23:23 petere Exp $ --> <refentry id="APP-PGRESTORE"> <docinfo> @@ -44,6 +44,7 @@ <arg> -T <replaceable class="parameter">trigger</replaceable> </arg> <arg> -v </arg> <arg> -x </arg> + <arg> -X <replaceable>keyword</replaceable></arg> <arg> -h <replaceable class="parameter">host</replaceable> </arg> <arg> -p <replaceable class="parameter">port</replaceable> </arg> <arg> -U <replaceable>username</replaceable> </arg> @@ -60,38 +61,54 @@ <para> <command>pg_restore</command> is a utility for restoring a - <productname>Postgres</productname> database dumped by - <xref linkend="app-pgdump"> in one of the non-plain-text formats. + <productname>Postgres</productname> database from an archive + created by <xref linkend="app-pgdump"> in one of the non-plain-text + formats. </para> <para> - The archive files, new with the 7.1 release, contain enough information for - <command>pg_restore</command> to rebuild the database, but also allow - <command>pg_restore</command> 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. <command>pg_dump</command> 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 + <command>pg_restore</command> to rebuild the database, but also + allow <command>pg_restore</command> 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. </para> <para> - <command>pg_restore</command> 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 - <quote>dump data as <command>INSERT</command>s</quote> option, <command>pg_restore</command> will not be able to - load the data using <command>COPY</command> statements. + <command>pg_restore</command> 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 + <command>pg_dump</command> plain text format. Some of the options + controlling the script output are therefore analogous to + <command>pg_dump</command>. </para> <para> - The most flexible output file format is the <quote>custom</quote> format (<option>-Fc</option>). It allows for - selection and reordering of all archived items, and is compressed by default. The <filename>tar</filename> - format (<option>-Ft</option>) is not compressed and it is not possible to reorder - data when loading, but it is otherwise quite flexible. + Obviously, <command>pg_restore</command> cannot restore information + that is not present in the archive file; for instance, if the + archive was made using the <quote>dump data as + <command>INSERT</command>s</quote> option, + <command>pg_restore</command> will not be able to load the data + using <command>COPY</command> statements. </para> <para> - To reorder the items, it is first necessary to dump the contents of the archive: + The most flexible output file format is the <quote>custom</quote> + format (<option>-Fc</option>). It allows for selection and + reordering of all archived items, and is compressed by default. The + <filename>tar</filename> format (<option>-Ft</option>) is not + compressed and it is not possible to reorder data when loading, but + it is otherwise quite flexible. + </para> + + <para> + To reorder the items, it is first necessary to dump the table of + contents of the archive: <screen> <prompt>$</prompt> <userinput>pg_restore archive.file -l > archive.list</userinput> </screen> @@ -346,8 +363,20 @@ <term>--no-reconnect</term> <listitem> <para> - Prohibit <COMMAND>pg_restore</COMMAND> from issuing any <PROGRAMLISTING>\connect</PROGRAMLISTING> - statements or reconnecting to the database if directly connected. + While restoring an archive, <command>pg_restore</command> + 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 + <command>pg_restore</command> from issuing any reconnection + requests. (A connection request while in plain text mode, not + connected to a database, is made by putting out a <xref + linkend="app-psql"> <command>\connect</command> command.) + However, this option is a rather blunt instrument because it + makes <command>pg_restore</command> lose all object ownership + information, <emphasis>unless</emphasis> you use the + <option>-X use-set-session-authorization</option> option. </para> </listitem> </varlistentry> @@ -414,6 +443,25 @@ </listitem> </varlistentry> + <varlistentry> + <term>-X use-set-session-authorization</term> + <term>--use-set-session-authorization</term> + <listitem> + <para> + 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 <option>-X use-set-session-authorization</option>, + then <command>pg_restore</command> will instead use the <xref + linkend="sql-set-session-authorization"> 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>-R</option> option. + </para> + </listitem> + </varlistentry> + </variablelist> </para> @@ -592,6 +640,14 @@ connectDBStart() -- connect() failed: No such file or directory </refsect1> + <refsect1> + <title>History</title> + + <para> + The <command>pg_restore</command> utility first appeared in + PostgreSQL 7.1. + </para> + </refsect1> <refsect1> <title>See Also</title> diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index 7e555957eb082c9e05b2050a68e9222ed80d9657..282738d882d17077ba23e34e5a73bebec9d843b4 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 982cabbcf2cdf160653470a0a07665005e0297ab..4ada30994f2e73793febf00399b3003e646a69b9 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; } + +/* + * 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, char *user) +_reconnectAsUser(ArchiveHandle *AH, const char *dbname, const char *user) { - if (AH->ropt && AH->ropt->noReconnect) - return; + if (!user || strlen(user) == 0 + || (strcmp(AH->currUser, user) == 0 && !dbname)) + return; /* no need to do anything */ - if (user && strlen(user) != 0 - && ((strcmp(AH->currUser, user) != 0) || (strcmp(dbname, "-") != 0))) + /* 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; + + 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)); - AH->currUser = strdup(user); + 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 16a1c06dfe6ebea7b0e93c3248f3f64de97479a7..fee94d83b0fd39d8c9985086b97dc9939081ef2b 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 f08a0d3085fb591084a89e02d75693f239926a0d..3bc49e44358537a5602dc38f6f46d39a2fdb8cb9 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 (!dbname) + newdbname = PQdb(AH->connection); + else + newdbname = dbname; - if (!newdbname || (strcmp(newdbname, "-") == 0)) - dbname = PQdb(AH->connection); + if (!username) + newusername = PQuser(AH->connection); else - dbname = (char *) newdbname; + 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 56067a34ee597d0a215f8cf414ca62dc4fcc4e94..f81439e2036e46619940262fb2b3cdaef9aa1627 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 4580f268b0288af3e68ae3c659d2befd6daed634..aff3bc7ea00aaae19cd3a1d6cbc5219c443f95e6 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 3ba07e848b2bf421fe38aeee6c416dde5f4f2119..0bff04903cb0e9fc6f4239159bd57ab475c5031f 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"));