Hi Benedek. At 2008-11-06 15:08:14 +0100, l...@benedekl.tvnetwork.hu wrote: > > I created an updated patch according to your notices.
I had a look at your updated patch, and it looks fine. I fiddled with the documentation a little, and fixed up one place where the code had drifted and the patch didn't apply. -- ams
diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml index 2e30906..9395c0a 100644 --- a/doc/src/sgml/ref/pg_dump.sgml +++ b/doc/src/sgml/ref/pg_dump.sgml @@ -698,6 +698,23 @@ PostgreSQL documentation </para> </listitem> </varlistentry> + + <varlistentry> + <term><option>--role=<replaceable class="parameter">rolename</replaceable></option></term> + <listitem> + <para> + Specifies a role name to be used to create the dump. This causes + <application>pg_dump</> to issue a + <command>SET ROLE TO <replaceable class="parameter">rolename</></> + command after connecting to the database. It is useful when the + authenticated user (specified by <option>-U</>) lacks privileges + needed by <application>pg_dump</>, but can switch to a role with + the required rights. The SET ROLE command is repeated in the + resulting archive because it is usually also needed for the + restore to succeed. + </para> + </listitem> + </varlistentry> </variablelist> </para> </refsect1> diff --git a/doc/src/sgml/ref/pg_dumpall.sgml b/doc/src/sgml/ref/pg_dumpall.sgml index ec40890..5c9e6fa 100644 --- a/doc/src/sgml/ref/pg_dumpall.sgml +++ b/doc/src/sgml/ref/pg_dumpall.sgml @@ -417,6 +417,23 @@ PostgreSQL documentation </para> </listitem> </varlistentry> + + <varlistentry> + <term><option>--role=<replaceable class="parameter">rolename</replaceable></option></term> + <listitem> + <para> + Specifies a role name to be used to create the dump. This causes + <application>pg_dumpall</> to issue a + <command>SET ROLE TO <replaceable class="parameter">rolename</></> + command after connecting to the database. It is useful when the + authenticated user (specified by <option>-U</>) lacks privileges + needed by <application>pg_dumpall</>, but can switch to a role + with the required rights. This option is passed on to + <application>pg_dump</>, and the SET ROLE command is repeated in + the output archive as well. + </para> + </listitem> + </varlistentry> </variablelist> </para> </refsect1> diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index c57bb22..cbe4d46 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -70,6 +70,8 @@ typedef struct _Archive int encoding; /* libpq code for client_encoding */ bool std_strings; /* standard_conforming_strings */ + const char *rolename; /* role name */ + /* error handling */ bool exit_on_error; /* whether to exit on SQL errors... */ int n_errors; /* number of errors (if no die) */ diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 0bbba25..69a5d9a 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -56,6 +56,7 @@ static void _selectOutputSchema(ArchiveHandle *AH, const char *schemaName); static void _selectTablespace(ArchiveHandle *AH, const char *tablespace); static void processEncodingEntry(ArchiveHandle *AH, TocEntry *te); static void processStdStringsEntry(ArchiveHandle *AH, TocEntry *te); +static void processRolenameEntry(ArchiveHandle *AH, TocEntry *te); static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls); static void _disableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); static void _enableTriggersIfNecessary(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt); @@ -1979,6 +1980,8 @@ ReadToc(ArchiveHandle *AH) processEncodingEntry(AH, te); else if (strcmp(te->desc, "STDSTRINGS") == 0) processStdStringsEntry(AH, te); + else if (strcmp(te->desc, "ROLENAME") == 0) + processRolenameEntry(AH, te); } } @@ -2026,14 +2029,38 @@ processStdStringsEntry(ArchiveHandle *AH, TocEntry *te) te->defn); } +static void +processRolenameEntry(ArchiveHandle *AH, TocEntry *te) +{ + /* te->defn should have the form SET role = 'foo'; */ + char *defn = strdup(te->defn); + char *ptr1; + char *ptr2 = NULL; + + ptr1 = strchr(defn, '\''); + if (ptr1) + ptr2 = strchr(++ptr1, '\''); + if (ptr2) + { + *ptr2 = '\0'; + AH->public.rolename = strdup(ptr1); + } + else + die_horribly(AH, modulename, "invalid ROLENAME item: %s\n", + te->defn); + + free(defn); +} + static teReqs _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls) { teReqs res = REQ_ALL; - /* ENCODING and STDSTRINGS items are dumped specially, so always reject */ + /* ENCODING, STDSTRINGS and ROLENAME items are dumped specially, so always reject */ if (strcmp(te->desc, "ENCODING") == 0 || - strcmp(te->desc, "STDSTRINGS") == 0) + strcmp(te->desc, "STDSTRINGS") == 0 || + strcmp(te->desc, "ROLENAME") == 0) return 0; /* If it's an ACL, maybe ignore it */ @@ -2146,6 +2173,11 @@ _doSetFixedOutputState(ArchiveHandle *AH) ahprintf(AH, "SET standard_conforming_strings = %s;\n", AH->public.std_strings ? "on" : "off"); + /* Select the role to be used during restore */ + if (AH->public.rolename) + ahprintf(AH, "SET role = %s;\n", + fmtId(AH->public.rolename)); + /* Make sure function checking is disabled */ ahprintf(AH, "SET check_function_bodies = false;\n"); diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index b93eb85..eab4c0a 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -194,6 +194,7 @@ static int dumpBlobComments(Archive *AH, void *arg); static void dumpDatabase(Archive *AH); static void dumpEncoding(Archive *AH); static void dumpStdStrings(Archive *AH); +static void dumpRole(Archive *AH); static const char *getAttrName(int attrnum, TableInfo *tblInfo); static const char *fmtCopyColumnList(const TableInfo *ti); static void do_sql_command(PGconn *conn, const char *query); @@ -235,6 +236,10 @@ main(int argc, char **argv) static int outputNoTablespaces = 0; static int use_setsessauth = 0; + const char *pgrole = NULL; + PQExpBuffer roleQry; + PGresult *res; + static struct option long_options[] = { {"data-only", no_argument, NULL, 'a'}, {"blobs", no_argument, NULL, 'b'}, @@ -275,6 +280,7 @@ main(int argc, char **argv) {"lock-wait-timeout", required_argument, NULL, 2}, {"no-tablespaces", no_argument, &outputNoTablespaces, 1}, {"use-set-session-authorization", no_argument, &use_setsessauth, 1}, + {"role", required_argument, NULL, 3}, {NULL, 0, NULL, 0} }; @@ -452,6 +458,10 @@ main(int argc, char **argv) lockWaitTimeout = optarg; break; + case 3: /* role */ + pgrole = optarg; + break; + default: fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); @@ -561,6 +571,20 @@ main(int argc, char **argv) } } + /* Set the role if requested */ + if (pgrole) + { + roleQry = createPQExpBuffer(); + appendPQExpBuffer(roleQry, "SET ROLE TO %s;\n", fmtId(pgrole)); + res = PQexec(g_conn, roleQry->data); + check_sql_result(res, g_conn, roleQry->data, PGRES_COMMAND_OK); + PQclear(res); + destroyPQExpBuffer(roleQry); + g_fout->rolename = pgrole; + } + else + g_fout->rolename = NULL; + /* * Get the active encoding and the standard_conforming_strings setting, so * we know how to escape strings. @@ -725,6 +749,8 @@ main(int argc, char **argv) /* First the special ENCODING and STDSTRINGS entries. */ dumpEncoding(g_fout); dumpStdStrings(g_fout); + if (pgrole) + dumpRole(g_fout); /* The database item is always next, unless we don't want it at all */ if (include_everything && !dataOnly) @@ -810,6 +836,7 @@ help(const char *progname) printf(_(" --use-set-session-authorization\n" " use SESSION AUTHORIZATION commands instead of\n" " ALTER OWNER commands to set ownership\n")); + printf(_(" --role set role before dump\n")); printf(_("\nConnection options:\n")); printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); @@ -1810,6 +1837,32 @@ dumpStdStrings(Archive *AH) /* + * dumpRole: put the role change into the archive + */ +static void +dumpRole(Archive *AH) +{ + const char *rolename = AH->rolename; + PQExpBuffer qry = createPQExpBuffer(); + + if (g_verbose) + write_msg(NULL, "saving rolename = %s\n", rolename); + + appendPQExpBuffer(qry, "SET role = "); + appendStringLiteralAH(qry, rolename, AH); + appendPQExpBuffer(qry, ";\n"); + + ArchiveEntry(AH, nilCatalogId, createDumpId(), + "ROLENAME", NULL, NULL, "", + false, "ROLENAME", qry->data, "", NULL, + NULL, 0, + NULL, NULL); + + destroyPQExpBuffer(qry); +} + + +/* * hasBlobs: * Test whether database contains any large objects */ diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 647cc7c..0d6a98b 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -89,6 +89,9 @@ main(int argc, char *argv[]) int c, ret; + const char *pgrole = NULL; + PQExpBuffer roleQry; + static struct option long_options[] = { {"data-only", no_argument, NULL, 'a'}, {"clean", no_argument, NULL, 'c'}, @@ -121,6 +124,7 @@ main(int argc, char *argv[]) {"no-tablespaces", no_argument, &no_tablespaces, 1}, {"use-set-session-authorization", no_argument, &use_setsessauth, 1}, {"lock-wait-timeout", required_argument, NULL, 2}, + {"role", required_argument, NULL, 3}, {NULL, 0, NULL, 0} }; @@ -311,6 +315,15 @@ main(int argc, char *argv[]) appendPQExpBuffer(pgdumpopts, "%s", optarg); break; + case 3: + pgrole = optarg; +#ifndef WIN32 + appendPQExpBuffer(pgdumpopts, " --role '%s'", optarg); +#else + appendPQExpBuffer(pgdumpopts, " --role \"%s\"", optarg); +#endif + break; + default: fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); @@ -426,6 +439,15 @@ main(int argc, char *argv[]) if (!std_strings) std_strings = "off"; + /* Set the role if requested */ + if (pgrole) + { + roleQry = createPQExpBuffer(); + appendPQExpBuffer(roleQry, "SET ROLE TO %s;\n", fmtId(pgrole)); + executeCommand(conn, roleQry->data); + destroyPQExpBuffer(roleQry); + } + fprintf(OPF, "--\n-- PostgreSQL database cluster dump\n--\n\n"); if (verbose) dumpTimestamp("Started on"); @@ -516,6 +538,7 @@ help(void) printf(_(" --use-set-session-authorization\n" " use SESSION AUTHORIZATION commands instead of\n" " OWNER TO commands\n")); + printf(_(" --role set role before dump\n")); printf(_("\nConnection options:\n")); printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers