diff --git a/doc/src/sgml/ref/pg_dumpall.sgml b/doc/src/sgml/ref/pg_dumpall.sgml index efc35f751464a790a8843b7d87021655e9002600..9a891cd1fb34ede32d53118fee2bfdb8831634ca 100644 --- a/doc/src/sgml/ref/pg_dumpall.sgml +++ b/doc/src/sgml/ref/pg_dumpall.sgml @@ -1,5 +1,5 @@ <!-- -$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 --> @@ -280,11 +280,14 @@ PostgreSQL documentation <term><option>--use-set-session-authorization</></term> <listitem> <para> - This option is obsolete but still accepted for backwards - compatibility with <application>pg_dump</application>. + Output SQL standard SET SESSION AUTHORIZATION commands instead + 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> </listitem> </varlistentry> + </variablelist> </para> diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 1ef19bb47c2e01cec8046ee40742acf4d4f9e58a..bc723e19606ef7107eccf861e28a6c0aa7ab24d5 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut <peter_e@gmx.net>. * * 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[] = * 6. Add it to src/bin/psql/tab-complete.c, if it's a USERSET 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. */ diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 5515f98db396095db1ff47e64cfec7484297b37f..939baf86ec9d942fc62e51a401b072f95b2e8cad 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -15,7 +15,7 @@ * * * 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 strcmp(te->desc, "TABLE") == 0 || strcmp(te->desc, "TYPE") == 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); @@ -2376,15 +2377,18 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat /* * Really crude hack for suppressing AUTHORIZATION clause of CREATE SCHEMA * 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) - { - ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", te->tag); - } - else - { - ahprintf(AH, "%s\n\n", te->defn); + 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); + } + else + { + ahprintf(AH, "%s\n\n", te->defn); + } } } else if (isData) { diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 9e38b0d43a3e6a98084ca90c064dfa171d0c795e..f1b89791e62ed4a958aee0da4f10f4d49809365c 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -12,7 +12,7 @@ * by PostgreSQL * * 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) nsinfo[0].dobj.catId.tableoid = 0; nsinfo[0].dobj.catId.oid = 0; AssignDumpId(&nsinfo[0].dobj); - nsinfo[0].dobj.name = strdup(""); + nsinfo[0].dobj.name = strdup("public"); nsinfo[0].usename = strdup(""); nsinfo[0].nspacl = strdup(""); nsinfo[0].nsptablespace = strdup(""); @@ -4381,11 +4381,6 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo) 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, * while the archive entry is listed with empty owner (causing * it to be emitted with SET SESSION AUTHORIZATION DEFAULT). @@ -4393,27 +4388,24 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo) * users without CREATE SCHEMA privilege. Further hacking has * 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", - qnspname, fmtId(nspinfo->usename)); + appendPQExpBuffer(q, "CREATE SCHEMA %s AUTHORIZATION %s", + qnspname, fmtId(nspinfo->usename)); - /* Add tablespace qualifier, if not default */ - if (strlen(nspinfo->nsptablespace) != 0) - appendPQExpBuffer(q, " TABLESPACE %s", - fmtId(nspinfo->nsptablespace)); + /* Add tablespace qualifier, if not default */ + if (strlen(nspinfo->nsptablespace) != 0) + appendPQExpBuffer(q, " TABLESPACE %s", + fmtId(nspinfo->nsptablespace)); - appendPQExpBuffer(q, ";\n"); + appendPQExpBuffer(q, ";\n"); - ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, - nspinfo->dobj.name, - NULL, "", - false, "SCHEMA", q->data, delq->data, NULL, - nspinfo->dobj.dependencies, nspinfo->dobj.nDeps, - NULL, NULL); - } + ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, + nspinfo->dobj.name, + NULL, strcmp(nspinfo->dobj.name, "public") == 0 ? nspinfo->usename : "", + false, "SCHEMA", q->data, delq->data, NULL, + nspinfo->dobj.dependencies, nspinfo->dobj.nDeps, + NULL, NULL); /* Dump Schema Comments */ resetPQExpBuffer(q); diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index d24d6dbeec745667a07493c3525d775fc67e9d16..0d9392122c5a6472bb40ec4d1fa0f7bf733c9bef 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -6,7 +6,7 @@ * 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; static void help(void); -static void dumpUsers(PGconn *conn); +static void dumpUsers(PGconn *conn, bool initdbonly); static void dumpGroups(PGconn *conn); static void dumpTablespaces(PGconn *conn); static void dumpCreateDB(PGconn *conn); @@ -257,7 +257,7 @@ main(int argc, char *argv[]) if (disable_triggers) appendPQExpBuffer(pgdumpopts, " -X disable-triggers"); if (use_setsessauth) - /* no-op, still allowed for compatibility */ ; + appendPQExpBuffer(pgdumpopts, " -X use-set-session-authorization"); if (optind < argc) { @@ -279,18 +279,19 @@ main(int argc, char *argv[]) if (!data_only) { - dumpUsers(conn); + /* Dump all users excluding the initdb user */ + dumpUsers(conn, false); dumpGroups(conn); if (server_version >= 70500) dumpTablespaces(conn); + if (!globals_only) + dumpCreateDB(conn); + /* Dump alter command for initdb user */ + dumpUsers(conn, true); } if (!globals_only) - { - if (!data_only) - dumpCreateDB(conn); dumpDatabases(conn); - } PQfinish(conn); @@ -310,26 +311,29 @@ help(void) printf(_("Usage:\n")); 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(_(" -c, --clean clean (drop) databases prior to create\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(_(" -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, --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 disable-dollar-quoting, --disable-dollar-quoting\n" " disable dollar quoting, use SQL standard quoting\n")); printf(_(" -X disable-triggers, --disable-triggers\n" - " disable triggers during data-only restore\n")); - printf(_(" --help show this help, then exit\n")); - printf(_(" --version output version information, then exit\n")); + " disable triggers during data-only restore\n")); + printf(_(" -X use-set-session-authorization, --use-set-session-authorization\n" + " use SESSION AUTHORIZATION commands instead of\n" + " OWNER TO commands\n")); printf(_("\nConnection options:\n")); printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); @@ -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 -dumpUsers(PGconn *conn) +dumpUsers(PGconn *conn, bool initdbonly) { PGresult *res; 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) res = executeQuery(conn, "SELECT usename, usesysid, passwd, usecreatedb, " - "usesuper, valuntil " - "FROM pg_shadow " - "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0')"); + "usesuper, valuntil, " + "(usesysid = (SELECT datdba FROM pg_database WHERE datname = 'template0')) AS clusterowner " + "FROM pg_shadow"); else res = executeQuery(conn, "SELECT usename, usesysid, passwd, usecreatedb, " - "usesuper, valuntil " - "FROM pg_shadow " - "WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template1')"); + "usesuper, valuntil, " + "(usesysid = (SELECT datdba FROM pg_database WHERE datname = 'template1')) AS clusterowner " + "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++) { - PQExpBuffer buf = createPQExpBuffer(); const char *username; - + bool clusterowner; + PQExpBuffer buf = createPQExpBuffer(); username = PQgetvalue(res, i, 0); - appendPQExpBuffer(buf, "CREATE USER %s WITH SYSID %s", - fmtId(username), - PQgetvalue(res, i, 1)); + clusterowner = (strcmp(PQgetvalue(res, i, 6), "t") == 0); + + /* 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)) { @@ -422,11 +439,13 @@ dumpGroups(PGconn *conn) PGresult *res; 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"); + 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++) { PQExpBuffer buf = createPQExpBuffer(); @@ -478,8 +497,6 @@ dumpTablespaces(PGconn *conn) PGresult *res; int i; - printf("--\n-- Tablespaces\n--\n\n"); - /* * Get all tablespaces except built-in ones (which we assume are named * pg_xxx) @@ -489,6 +506,9 @@ dumpTablespaces(PGconn *conn) "spclocation, spcacl " "FROM pg_catalog.pg_tablespace " "WHERE spcname NOT LIKE 'pg\\_%'"); + + if (PQntuples(res) > 0) + printf("--\n-- Tablespaces\n--\n\n"); for (i = 0; i < PQntuples(res); i++) { @@ -758,7 +778,12 @@ makeAlterConfigCommand(const char *arrayitem, const char *type, const char *name *pos = 0; appendPQExpBuffer(buf, "ALTER %s %s ", type, fmtId(name)); 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"); printf("%s", buf->data);