From 82b37765c76b8b2daf6cad3dfb5e5b4a2776d56f Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Fri, 16 Oct 2015 11:37:19 -0400
Subject: [PATCH] Fix a problem with parallel workers being unable to restore
 role.

check_role() tries to verify that the user has permission to become the
requested role, but this is inappropriate in a parallel worker, which
needs to exactly recreate the master's authorization settings.  So skip
the check in that case.

This fixes a bug in commit 924bcf4f16d54c55310b28f77686608684734f42.
---
 src/backend/access/transam/parallel.c | 7 +++++++
 src/backend/commands/variable.c       | 8 ++++++--
 src/include/access/parallel.h         | 1 +
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index e09bdb20b0d..9c7428f5d6c 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -96,6 +96,9 @@ int			ParallelWorkerNumber = -1;
 /* Is there a parallel message pending which we need to receive? */
 bool		ParallelMessagePending = false;
 
+/* Are we initializing a parallel worker? */
+bool		InitializingParallelWorker = false;
+
 /* Pointer to our fixed parallel state. */
 static FixedParallelState *MyFixedParallelState;
 
@@ -815,6 +818,9 @@ ParallelWorkerMain(Datum main_arg)
 	char	   *tstatespace;
 	StringInfoData msgbuf;
 
+	/* Set flag to indicate that we're initializing a parallel worker. */
+	InitializingParallelWorker = true;
+
 	/* Establish signal handlers. */
 	pqsignal(SIGTERM, die);
 	BackgroundWorkerUnblockSignals();
@@ -942,6 +948,7 @@ ParallelWorkerMain(Datum main_arg)
 	 * We've initialized all of our state now; nothing should change
 	 * hereafter.
 	 */
+	InitializingParallelWorker = false;
 	EnterParallelMode();
 
 	/*
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 2d0a44effe7..16c122a22bc 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -19,6 +19,7 @@
 #include <ctype.h>
 
 #include "access/htup_details.h"
+#include "access/parallel.h"
 #include "access/xact.h"
 #include "access/xlog.h"
 #include "catalog/pg_authid.h"
@@ -877,9 +878,12 @@ check_role(char **newval, void **extra, GucSource source)
 		ReleaseSysCache(roleTup);
 
 		/*
-		 * Verify that session user is allowed to become this role
+		 * Verify that session user is allowed to become this role, but
+		 * skip this in parallel mode, where we must blindly recreate the
+		 * parallel leader's state.
 		 */
-		if (!is_member_of_role(GetSessionUserId(), roleid))
+		if (!InitializingParallelWorker &&
+			!is_member_of_role(GetSessionUserId(), roleid))
 		{
 			GUC_check_errcode(ERRCODE_INSUFFICIENT_PRIVILEGE);
 			GUC_check_errmsg("permission denied to set role \"%s\"",
diff --git a/src/include/access/parallel.h b/src/include/access/parallel.h
index b029c1e8831..44f0616cb86 100644
--- a/src/include/access/parallel.h
+++ b/src/include/access/parallel.h
@@ -48,6 +48,7 @@ typedef struct ParallelContext
 
 extern bool ParallelMessagePending;
 extern int	ParallelWorkerNumber;
+extern bool InitializingParallelWorker;
 
 #define		IsParallelWorker()		(ParallelWorkerNumber >= 0)
 
-- 
GitLab