Commit 45995219 authored by Bruce Momjian's avatar Bruce Momjian

Here is another patch that fixes a stack of pg_dump bugs:

* Fix help text ordering

* Add back --set-session-authorization to pg_dumpall.  Updated the docs
for that.  Updated help for that.

* Dump ALTER USER commands for the cluster owner ("pgsql").  These are
dumped AFTER the create user and create database commands in case the
permissions to do these have been revoked.

* Dump ALTER OWNER for public schema (because it's possible to change
it).  This was done by adding TOC entries for the public schema, and
filtering them out at archiver time.  I also save the owner in the TOC
entry just for the public schema.

* Suppress dumping single quotes around schema_path and DateStyle
options when they are set using ALTER USER or ALTER DATABASE.  Added a
comment to the steps in guc.c to remind people to update that list.

* Fix dumping in --clean mode against a pre-7.3 server.  It just sets
all drop statements to assume the public schema, allowing it to restore
without error.

* Cleaned up text output.  eg. Don't output -- Tablespaces comment if
there are none.  Same for groups and users.

* Make the commands to DELETE FROM pg_shadow and DELETE FROM pg_group
only be output when -c mode is enabled.  I'm not sure why that hasn't
been done before?!?!

This should be good for application asap, after which I will start on
regression dumping 7.0-7.4 databases.

Christopher Kings-Lynne
parent 465edca3
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/pg_dumpall.sgml,v 1.45 2004/07/12 14:35:43 momjian Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/pg_dumpall.sgml,v 1.46 2004/07/19 21:39:46 momjian Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -280,11 +280,14 @@ PostgreSQL documentation ...@@ -280,11 +280,14 @@ PostgreSQL documentation
<term><option>--use-set-session-authorization</></term> <term><option>--use-set-session-authorization</></term>
<listitem> <listitem>
<para> <para>
This option is obsolete but still accepted for backwards Output SQL standard SET SESSION AUTHORIZATION commands instead
compatibility with <application>pg_dump</application>. of OWNER TO commands. This makes the dump more standards compatible,
but depending on the history of the objects in the dump, may not
restore properly.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
</para> </para>
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.220 2004/07/19 02:47:10 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.221 2004/07/19 21:39:47 momjian Exp $
* *
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
...@@ -335,6 +335,9 @@ const char *const config_type_names[] = ...@@ -335,6 +335,9 @@ const char *const config_type_names[] =
* 6. Add it to src/bin/psql/tab-complete.c, if it's a USERSET option. * 6. Add it to src/bin/psql/tab-complete.c, if it's a USERSET option.
* *
* 7. Don't forget to document the option. * 7. Don't forget to document the option.
*
* 8. If it's a new GUC_LIST option you must edit pg_dumpall.c to ensure
* it is not single quoted at dump time.
*/ */
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.89 2004/07/19 21:02:17 tgl Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.90 2004/07/19 21:39:47 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2356,7 +2356,8 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat ...@@ -2356,7 +2356,8 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
strcmp(te->desc, "TABLE") == 0 || strcmp(te->desc, "TABLE") == 0 ||
strcmp(te->desc, "TYPE") == 0 || strcmp(te->desc, "TYPE") == 0 ||
strcmp(te->desc, "VIEW") == 0 || strcmp(te->desc, "VIEW") == 0 ||
strcmp(te->desc, "SEQUENCE") == 0 strcmp(te->desc, "SEQUENCE") == 0 ||
(strcmp(te->desc, "SCHEMA") == 0 && strcmp(te->tag, "public") == 0) /* Only public schema */
)) ))
{ {
char *temp = _getObjectFromDropStmt(te->dropStmt, te->desc); char *temp = _getObjectFromDropStmt(te->dropStmt, te->desc);
...@@ -2376,15 +2377,18 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat ...@@ -2376,15 +2377,18 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
/* /*
* Really crude hack for suppressing AUTHORIZATION clause of CREATE SCHEMA * Really crude hack for suppressing AUTHORIZATION clause of CREATE SCHEMA
* when --no-owner mode is selected. This is ugly, but I see no other * when --no-owner mode is selected. This is ugly, but I see no other
* good way ... * good way ... Also, avoid dumping the public schema as it will already be
* created.
*/ */
if (AH->ropt && AH->ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0) if (strcmp(te->tag, "public") != 0) {
{ if (AH->ropt && AH->ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0)
ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", te->tag); {
} ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", te->tag);
else }
{ else
ahprintf(AH, "%s\n\n", te->defn); {
ahprintf(AH, "%s\n\n", te->defn);
}
} }
} }
else if (isData) { else if (isData) {
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* by PostgreSQL * by PostgreSQL
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.379 2004/07/13 03:00:17 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.380 2004/07/19 21:39:48 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1492,7 +1492,7 @@ getNamespaces(int *numNamespaces) ...@@ -1492,7 +1492,7 @@ getNamespaces(int *numNamespaces)
nsinfo[0].dobj.catId.tableoid = 0; nsinfo[0].dobj.catId.tableoid = 0;
nsinfo[0].dobj.catId.oid = 0; nsinfo[0].dobj.catId.oid = 0;
AssignDumpId(&nsinfo[0].dobj); AssignDumpId(&nsinfo[0].dobj);
nsinfo[0].dobj.name = strdup(""); nsinfo[0].dobj.name = strdup("public");
nsinfo[0].usename = strdup(""); nsinfo[0].usename = strdup("");
nsinfo[0].nspacl = strdup(""); nsinfo[0].nspacl = strdup("");
nsinfo[0].nsptablespace = strdup(""); nsinfo[0].nsptablespace = strdup("");
...@@ -4381,11 +4381,6 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo) ...@@ -4381,11 +4381,6 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
qnspname = strdup(fmtId(nspinfo->dobj.name)); qnspname = strdup(fmtId(nspinfo->dobj.name));
/* /*
* If it's the PUBLIC namespace, suppress the CREATE SCHEMA record
* for it, since we expect PUBLIC to exist already in the
* destination database. But do emit ACL in case it's not standard,
* likewise comment.
*
* Note that ownership is shown in the AUTHORIZATION clause, * Note that ownership is shown in the AUTHORIZATION clause,
* while the archive entry is listed with empty owner (causing * while the archive entry is listed with empty owner (causing
* it to be emitted with SET SESSION AUTHORIZATION DEFAULT). * it to be emitted with SET SESSION AUTHORIZATION DEFAULT).
...@@ -4393,27 +4388,24 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo) ...@@ -4393,27 +4388,24 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
* users without CREATE SCHEMA privilege. Further hacking has * users without CREATE SCHEMA privilege. Further hacking has
* to be applied for --no-owner mode, though! * to be applied for --no-owner mode, though!
*/ */
if (strcmp(nspinfo->dobj.name, "public") != 0) appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
{
appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
appendPQExpBuffer(q, "CREATE SCHEMA %s AUTHORIZATION %s", appendPQExpBuffer(q, "CREATE SCHEMA %s AUTHORIZATION %s",
qnspname, fmtId(nspinfo->usename)); qnspname, fmtId(nspinfo->usename));
/* Add tablespace qualifier, if not default */ /* Add tablespace qualifier, if not default */
if (strlen(nspinfo->nsptablespace) != 0) if (strlen(nspinfo->nsptablespace) != 0)
appendPQExpBuffer(q, " TABLESPACE %s", appendPQExpBuffer(q, " TABLESPACE %s",
fmtId(nspinfo->nsptablespace)); fmtId(nspinfo->nsptablespace));
appendPQExpBuffer(q, ";\n"); appendPQExpBuffer(q, ";\n");
ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
nspinfo->dobj.name, nspinfo->dobj.name,
NULL, "", NULL, strcmp(nspinfo->dobj.name, "public") == 0 ? nspinfo->usename : "",
false, "SCHEMA", q->data, delq->data, NULL, false, "SCHEMA", q->data, delq->data, NULL,
nspinfo->dobj.dependencies, nspinfo->dobj.nDeps, nspinfo->dobj.dependencies, nspinfo->dobj.nDeps,
NULL, NULL); NULL, NULL);
}
/* Dump Schema Comments */ /* Dump Schema Comments */
resetPQExpBuffer(q); resetPQExpBuffer(q);
......
...@@ -6,7 +6,7 @@ ...@@ -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.44 2004/07/12 14:35:45 momjian Exp $ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.45 2004/07/19 21:39:48 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -44,7 +44,7 @@ static const char *progname; ...@@ -44,7 +44,7 @@ static const char *progname;
static void help(void); static void help(void);
static void dumpUsers(PGconn *conn); static void dumpUsers(PGconn *conn, bool initdbonly);
static void dumpGroups(PGconn *conn); static void dumpGroups(PGconn *conn);
static void dumpTablespaces(PGconn *conn); static void dumpTablespaces(PGconn *conn);
static void dumpCreateDB(PGconn *conn); static void dumpCreateDB(PGconn *conn);
...@@ -257,7 +257,7 @@ main(int argc, char *argv[]) ...@@ -257,7 +257,7 @@ main(int argc, char *argv[])
if (disable_triggers) if (disable_triggers)
appendPQExpBuffer(pgdumpopts, " -X disable-triggers"); appendPQExpBuffer(pgdumpopts, " -X disable-triggers");
if (use_setsessauth) if (use_setsessauth)
/* no-op, still allowed for compatibility */ ; appendPQExpBuffer(pgdumpopts, " -X use-set-session-authorization");
if (optind < argc) if (optind < argc)
{ {
...@@ -279,18 +279,19 @@ main(int argc, char *argv[]) ...@@ -279,18 +279,19 @@ main(int argc, char *argv[])
if (!data_only) if (!data_only)
{ {
dumpUsers(conn); /* Dump all users excluding the initdb user */
dumpUsers(conn, false);
dumpGroups(conn); dumpGroups(conn);
if (server_version >= 70500) if (server_version >= 70500)
dumpTablespaces(conn); dumpTablespaces(conn);
if (!globals_only)
dumpCreateDB(conn);
/* Dump alter command for initdb user */
dumpUsers(conn, true);
} }
if (!globals_only) if (!globals_only)
{
if (!data_only)
dumpCreateDB(conn);
dumpDatabases(conn); dumpDatabases(conn);
}
PQfinish(conn); PQfinish(conn);
...@@ -310,26 +311,29 @@ help(void) ...@@ -310,26 +311,29 @@ help(void)
printf(_("Usage:\n")); printf(_("Usage:\n"));
printf(_(" %s [OPTION]...\n"), progname); printf(_(" %s [OPTION]...\n"), progname);
printf(_("\nOptions:\n")); printf(_("\nGeneral options:\n"));
printf(_(" -i, --ignore-version proceed even when server version mismatches\n"
" pg_dumpall version\n"));
printf(_(" --help show this help, then exit\n"));
printf(_(" --version output version information, then exit\n"));
printf(_("\nOptions controlling the output content:\n"));
printf(_(" -a, --data-only dump only the data, not the schema\n")); printf(_(" -a, --data-only dump only the data, not the schema\n"));
printf(_(" -c, --clean clean (drop) databases prior to create\n")); printf(_(" -c, --clean clean (drop) databases prior to create\n"));
printf(_(" -d, --inserts dump data as INSERT, rather than COPY, commands\n")); printf(_(" -d, --inserts dump data as INSERT, rather than COPY, commands\n"));
printf(_(" -D, --column-inserts dump data as INSERT commands with column names\n")); printf(_(" -D, --column-inserts dump data as INSERT commands with column names\n"));
printf(_(" -g, --globals-only dump only global objects, no databases\n")); printf(_(" -g, --globals-only dump only global objects, no databases\n"));
printf(_(" -i, --ignore-version proceed even when server version mismatches\n"
" pg_dumpall version\n"));
printf(_(" -s, --schema-only dump only the schema, no data\n"));
printf(_(" -S, --superuser=NAME specify the superuser user name to use in the dump\n"));
printf(_(" -o, --oids include OIDs in dump\n")); printf(_(" -o, --oids include OIDs in dump\n"));
printf(_(" -O, --no-owner do not output commands to set object ownership\n")); printf(_(" -O, --no-owner do not output commands to set object ownership\n"));
printf(_(" -v, --verbose verbose mode\n")); printf(_(" -s, --schema-only dump only the schema, no data\n"));
printf(_(" -S, --superuser=NAME specify the superuser user name to use in the dump\n"));
printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n")); printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
printf(_(" -X disable-dollar-quoting, --disable-dollar-quoting\n" printf(_(" -X disable-dollar-quoting, --disable-dollar-quoting\n"
" disable dollar quoting, use SQL standard quoting\n")); " disable dollar quoting, use SQL standard quoting\n"));
printf(_(" -X disable-triggers, --disable-triggers\n" printf(_(" -X disable-triggers, --disable-triggers\n"
" disable triggers during data-only restore\n")); " disable triggers during data-only restore\n"));
printf(_(" --help show this help, then exit\n")); printf(_(" -X use-set-session-authorization, --use-set-session-authorization\n"
printf(_(" --version output version information, then exit\n")); " use SESSION AUTHORIZATION commands instead of\n"
" OWNER TO commands\n"));
printf(_("\nConnection options:\n")); printf(_("\nConnection options:\n"));
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
...@@ -344,39 +348,52 @@ help(void) ...@@ -344,39 +348,52 @@ help(void)
/* /*
* Dump users (but not the user created by initdb). * Dump users
* Is able to dump all non initdb users or just the initdb user.
*/ */
static void static void
dumpUsers(PGconn *conn) dumpUsers(PGconn *conn, bool initdbonly)
{ {
PGresult *res; PGresult *res;
int i; int i;
printf("--\n-- Users\n--\n\n");
printf("DELETE FROM pg_shadow WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');\n\n");
if (server_version >= 70100) if (server_version >= 70100)
res = executeQuery(conn, res = executeQuery(conn,
"SELECT usename, usesysid, passwd, usecreatedb, " "SELECT usename, usesysid, passwd, usecreatedb, "
"usesuper, valuntil " "usesuper, valuntil, "
"FROM pg_shadow " "(usesysid = (SELECT datdba FROM pg_database WHERE datname = 'template0')) AS clusterowner "
"WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0')"); "FROM pg_shadow");
else else
res = executeQuery(conn, res = executeQuery(conn,
"SELECT usename, usesysid, passwd, usecreatedb, " "SELECT usename, usesysid, passwd, usecreatedb, "
"usesuper, valuntil " "usesuper, valuntil, "
"FROM pg_shadow " "(usesysid = (SELECT datdba FROM pg_database WHERE datname = 'template1')) AS clusterowner "
"WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template1')"); "FROM pg_shadow");
if (PQntuples(res) > 0 || (!initdbonly && output_clean))
printf("--\n-- Users\n--\n\n");
if (!initdbonly && output_clean)
printf("DELETE FROM pg_shadow WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');\n\n");
for (i = 0; i < PQntuples(res); i++) for (i = 0; i < PQntuples(res); i++)
{ {
PQExpBuffer buf = createPQExpBuffer();
const char *username; const char *username;
bool clusterowner;
PQExpBuffer buf = createPQExpBuffer();
username = PQgetvalue(res, i, 0); username = PQgetvalue(res, i, 0);
appendPQExpBuffer(buf, "CREATE USER %s WITH SYSID %s", clusterowner = (strcmp(PQgetvalue(res, i, 6), "t") == 0);
fmtId(username),
PQgetvalue(res, i, 1)); /* Check which pass we're on */
if ((initdbonly && !clusterowner) || (!initdbonly && clusterowner)) continue;
/* Dump ALTER USER for the cluster owner and CREATE USER for all other users */
if (!clusterowner)
appendPQExpBuffer(buf, "CREATE USER %s WITH SYSID %s",
fmtId(username),
PQgetvalue(res, i, 1));
else
appendPQExpBuffer(buf, "ALTER USER %s WITH",
fmtId(username));
if (!PQgetisnull(res, i, 2)) if (!PQgetisnull(res, i, 2))
{ {
...@@ -422,11 +439,13 @@ dumpGroups(PGconn *conn) ...@@ -422,11 +439,13 @@ dumpGroups(PGconn *conn)
PGresult *res; PGresult *res;
int i; int i;
printf("--\n-- Groups\n--\n\n");
printf("DELETE FROM pg_group;\n\n");
res = executeQuery(conn, "SELECT groname, grosysid, grolist FROM pg_group"); res = executeQuery(conn, "SELECT groname, grosysid, grolist FROM pg_group");
if (PQntuples(res) > 0 || output_clean)
printf("--\n-- Groups\n--\n\n");
if (output_clean)
printf("DELETE FROM pg_group;\n\n");
for (i = 0; i < PQntuples(res); i++) for (i = 0; i < PQntuples(res); i++)
{ {
PQExpBuffer buf = createPQExpBuffer(); PQExpBuffer buf = createPQExpBuffer();
...@@ -478,8 +497,6 @@ dumpTablespaces(PGconn *conn) ...@@ -478,8 +497,6 @@ dumpTablespaces(PGconn *conn)
PGresult *res; PGresult *res;
int i; int i;
printf("--\n-- Tablespaces\n--\n\n");
/* /*
* Get all tablespaces except built-in ones (which we assume are named * Get all tablespaces except built-in ones (which we assume are named
* pg_xxx) * pg_xxx)
...@@ -489,6 +506,9 @@ dumpTablespaces(PGconn *conn) ...@@ -489,6 +506,9 @@ dumpTablespaces(PGconn *conn)
"spclocation, spcacl " "spclocation, spcacl "
"FROM pg_catalog.pg_tablespace " "FROM pg_catalog.pg_tablespace "
"WHERE spcname NOT LIKE 'pg\\_%'"); "WHERE spcname NOT LIKE 'pg\\_%'");
if (PQntuples(res) > 0)
printf("--\n-- Tablespaces\n--\n\n");
for (i = 0; i < PQntuples(res); i++) for (i = 0; i < PQntuples(res); i++)
{ {
...@@ -758,7 +778,12 @@ makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name ...@@ -758,7 +778,12 @@ makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name
*pos = 0; *pos = 0;
appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name)); appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name));
appendPQExpBuffer(buf, "SET %s TO ", fmtId(mine)); appendPQExpBuffer(buf, "SET %s TO ", fmtId(mine));
appendStringLiteral(buf, pos + 1, false); /* Some GUC variable names are 'LIST' type and hence must not be quoted. */
if (strcasecmp(mine, "DateStyle") == 0
|| strcasecmp(mine, "search_path") == 0)
appendPQExpBuffer(buf, "%s", pos + 1);
else
appendStringLiteral(buf, pos + 1, false);
appendPQExpBuffer(buf, ";\n"); appendPQExpBuffer(buf, ";\n");
printf("%s", buf->data); printf("%s", buf->data);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment