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

Reply via email to