/* Fixed-size state that workers must restore. */
    Oid         database_id;
    Oid         authenticated_user_id;
-   Oid         current_user_id;
+   Oid         session_user_id;
    Oid         outer_user_id;
+   Oid         current_user_id;
    Oid         temp_namespace_id;
    Oid         temp_toast_namespace_id;
    int         sec_context;
-   bool        is_superuser;
+   bool        authenticated_user_is_superuser;
+   bool        session_user_is_superuser;
+   bool        role_is_superuser;
    PGPROC     *parallel_leader_pgproc;
    pid_t       parallel_leader_pid;
    BackendId   parallel_leader_backend_id;
        shm_toc_allocate(pcxt->toc, sizeof(FixedParallelState));
    fps->database_id = MyDatabaseId;
    fps->authenticated_user_id = GetAuthenticatedUserId();
+   fps->session_user_id = GetSessionUserId();
    fps->outer_user_id = GetCurrentRoleId();
-   fps->is_superuser = session_auth_is_superuser;
    GetUserIdAndSecContext(&fps->current_user_id, &fps->sec_context);
+   fps->authenticated_user_is_superuser = GetAuthenticatedUserIsSuperuser();
+   fps->session_user_is_superuser = GetSessionUserIsSuperuser();
+   fps->role_is_superuser = session_auth_is_superuser;
    GetTempNamespaceState(&fps->temp_namespace_id,
                          &fps->temp_toast_namespace_id);
    fps->parallel_leader_pgproc = MyProc;
 
    entrypt = LookupParallelWorkerFunction(library_name, function_name);
 
+   /*
+    * Restore current session authorization and role id.  No verification
+    * happens here, we just blindly adopt the leader's state.  Note that this
+    * has to happen before InitPostgres, since InitializeSessionUserId will
+    * not set these variables.
+    */
+   SetAuthenticatedUserId(fps->authenticated_user_id,
+                          fps->authenticated_user_is_superuser);
+   SetSessionAuthorization(fps->session_user_id,
+                           fps->session_user_is_superuser);
+   SetCurrentRoleId(fps->outer_user_id, fps->role_is_superuser);
+
    /* Restore database connection. */
    BackgroundWorkerInitializeConnectionByOid(fps->database_id,
                                              fps->authenticated_user_id,
    InvalidateSystemCaches();
 
    /*
-    * Restore current role id.  Skip verifying whether session user is
-    * allowed to become this role and blindly restore the leader's state for
-    * current role.
+    * Restore current user ID and security context.  No verification happens
+    * here, we just blindly adopt the leader's state.  We can't do this till
+    * after restoring GUCs, else we'll get complaints about restoring
+    * session_authorization and role.  (In effect, we're assuming that all
+    * the restored values are okay to set, even if we are now inside a
+    * restricted context.)
     */
-   SetCurrentRoleId(fps->outer_user_id, fps->is_superuser);
-
-   /* Restore user ID and security context. */
    SetUserIdAndSecContext(fps->current_user_id, fps->sec_context);
 
    /* Restore temp-namespace state to ensure search path matches leader's. */
 
    if (*newval == NULL)
        return true;
 
-   if (!IsTransactionState())
+   if (InitializingParallelWorker)
    {
        /*
-        * Can't do catalog lookups, so fail.  The result of this is that
-        * session_authorization cannot be set in postgresql.conf, which seems
-        * like a good thing anyway, so we don't work hard to avoid it.
+        * In parallel worker initialization, we want to copy the leader's
+        * state even if it no longer matches the catalogs. ParallelWorkerMain
+        * already installed the correct role OID and superuser state.
         */
-       return false;
+       roleid = GetSessionUserId();
+       is_superuser = GetSessionUserIsSuperuser();
    }
-
-   /* Look up the username */
-   roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
-   if (!HeapTupleIsValid(roleTup))
+   else
    {
+       if (!IsTransactionState())
+       {
+           /*
+            * Can't do catalog lookups, so fail.  The result of this is that
+            * session_authorization cannot be set in postgresql.conf, which
+            * seems like a good thing anyway, so we don't work hard to avoid
+            * it.
+            */
+           return false;
+       }
+
        /*
         * When source == PGC_S_TEST, we don't throw a hard error for a
-        * nonexistent user name, only a NOTICE.  See comments in guc.h.
+        * nonexistent user name or insufficient privileges, only a NOTICE.
+        * See comments in guc.h.
         */
-       if (source == PGC_S_TEST)
+
+       /* Look up the username */
+       roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(*newval));
+       if (!HeapTupleIsValid(roleTup))
        {
-           ereport(NOTICE,
-                   (errcode(ERRCODE_UNDEFINED_OBJECT),
-                    errmsg("role \"%s\" does not exist", *newval)));
-           return true;
+           if (source == PGC_S_TEST)
+           {
+               ereport(NOTICE,
+                       (errcode(ERRCODE_UNDEFINED_OBJECT),
+                        errmsg("role \"%s\" does not exist", *newval)));
+               return true;
+           }
+           GUC_check_errmsg("role \"%s\" does not exist", *newval);
+           return false;
        }
-       GUC_check_errmsg("role \"%s\" does not exist", *newval);
-       return false;
-   }
 
-   roleform = (Form_pg_authid) GETSTRUCT(roleTup);
-   roleid = roleform->oid;
-   is_superuser = roleform->rolsuper;
+       roleform = (Form_pg_authid) GETSTRUCT(roleTup);
+       roleid = roleform->oid;
+       is_superuser = roleform->rolsuper;
 
-   ReleaseSysCache(roleTup);
+       ReleaseSysCache(roleTup);
+
+       /*
+        * Only superusers may SET SESSION AUTHORIZATION a role other than
+        * itself. Note that in case of multiple SETs in a single session, the
+        * original authenticated user's superuserness is what matters.
+        */
+       if (roleid != GetAuthenticatedUserId() &&
+           !GetAuthenticatedUserIsSuperuser())
+       {
+           if (source == PGC_S_TEST)
+           {
+               ereport(NOTICE,
+                       (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                        errmsg("permission will be denied to set session authorization \"%s\"",
+                               *newval)));
+               return true;
+           }
+           GUC_check_errcode(ERRCODE_INSUFFICIENT_PRIVILEGE);
+           GUC_check_errmsg("permission denied to set session authorization \"%s\"",
+                            *newval);
+           return false;
+       }
+   }
 
    /* Set up "extra" struct for assign_session_authorization to use */
    myextra = (role_auth_extra *) malloc(sizeof(role_auth_extra));
        roleid = InvalidOid;
        is_superuser = false;
    }
+   else if (InitializingParallelWorker)
+   {
+       /*
+        * In parallel worker initialization, we want to copy the leader's
+        * state even if it no longer matches the catalogs. ParallelWorkerMain
+        * already installed the correct role OID and superuser state.
+        */
+       roleid = GetCurrentRoleId();
+       is_superuser = session_auth_is_superuser;
+   }
    else
    {
        if (!IsTransactionState())
 
        ReleaseSysCache(roleTup);
 
-       /*
-        * 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 (!InitializingParallelWorker &&
-           !is_member_of_role(GetSessionUserId(), roleid))
+       /* Verify that session user is allowed to become this role */
+       if (!is_member_of_role(GetSessionUserId(), roleid))
        {
            if (source == PGC_S_TEST)
            {
 
 #include <utime.h>
 
 #include "access/htup_details.h"
+#include "access/parallel.h"
 #include "catalog/pg_authid.h"
 #include "common/file_perm.h"
 #include "libpq/libpq.h"
 
 
 static void
-SetOuterUserId(Oid userid)
+SetOuterUserId(Oid userid, bool is_superuser)
 {
    AssertState(SecurityRestrictionContext == 0);
    AssertArg(OidIsValid(userid));
 
    /* We force the effective user ID to match, too */
    CurrentUserId = userid;
+
+   /* Also update the is_superuser GUC to match OuterUserId's property */
+   SetConfigOption("is_superuser",
+                   is_superuser ? "on" : "off",
+                   PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
 }
 
 
    return SessionUserId;
 }
 
+bool
+GetSessionUserIsSuperuser(void)
+{
+   Assert(OidIsValid(SessionUserId));
+   return SessionUserIsSuperuser;
+}
 
 static void
 SetSessionUserId(Oid userid, bool is_superuser)
    AssertArg(OidIsValid(userid));
    SessionUserId = userid;
    SessionUserIsSuperuser = is_superuser;
-   SetRoleIsActive = false;
-
-   /* We force the effective user IDs to match, too */
-   OuterUserId = userid;
-   CurrentUserId = userid;
 }
 
 /*
- * GetAuthenticatedUserId - get the authenticated user ID
+ * GetAuthenticatedUserId/SetAuthenticatedUserId - get/set the authenticated
+ * user ID
  */
 Oid
 GetAuthenticatedUserId(void)
    return AuthenticatedUserId;
 }
 
+/*
+ * Return whether the authenticated user was superuser at connection start.
+ */
+bool
+GetAuthenticatedUserIsSuperuser(void)
+{
+   Assert(OidIsValid(AuthenticatedUserId));
+   return AuthenticatedUserIsSuperuser;
+}
+
+void
+SetAuthenticatedUserId(Oid userid, bool is_superuser)
+{
+   Assert(OidIsValid(userid));
+
+   /* call only once */
+   Assert(!OidIsValid(AuthenticatedUserId));
+
+   AuthenticatedUserId = userid;
+   AuthenticatedUserIsSuperuser = is_superuser;
+
+   /* Also mark our PGPROC entry with the authenticated user id */
+   /* (We assume this is an atomic store so no lock is needed) */
+   MyProc->roleId = userid;
+}
+
 
 /*
  * GetUserIdAndSecContext/SetUserIdAndSecContext - get/set the current user ID
    HeapTuple   roleTup;
    Form_pg_authid rform;
    char       *rname;
+   bool        is_superuser;
 
    /*
     * Don't do scans if we're bootstrapping, none of the system catalogs
     */
    AssertState(!IsBootstrapProcessingMode());
 
-   /* call only once */
-   AssertState(!OidIsValid(AuthenticatedUserId));
-
    /*
     * Make sure syscache entries are flushed for recent catalog changes. This
     * allows us to find roles that were created on-the-fly during
     */
    AcceptInvalidationMessages();
 
+   /*
+    * Look up the role, either by name if that's given or by OID if not.
+    * Normally we have to fail if we don't find it, but in parallel workers
+    * just return without doing anything: all the critical work has been done
+    * already.  The upshot of that is that if the role has been deleted, we
+    * will not enforce its rolconnlimit against parallel workers anymore.
+    */
    if (rolename != NULL)
    {
        roleTup = SearchSysCache1(AUTHNAME, PointerGetDatum(rolename));
        if (!HeapTupleIsValid(roleTup))
+       {
+           if (InitializingParallelWorker)
+               return;
            ereport(FATAL,
                    (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                     errmsg("role \"%s\" does not exist", rolename)));
+       }
    }
    else
    {
        roleTup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
        if (!HeapTupleIsValid(roleTup))
+       {
+           if (InitializingParallelWorker)
+               return;
            ereport(FATAL,
                    (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                     errmsg("role with OID %u does not exist", roleid)));
+       }
    }
 
    rform = (Form_pg_authid) GETSTRUCT(roleTup);
    roleid = rform->oid;
    rname = NameStr(rform->rolname);
+   is_superuser = rform->rolsuper;
 
-   AuthenticatedUserId = roleid;
-   AuthenticatedUserIsSuperuser = rform->rolsuper;
-
-   /* This sets OuterUserId/CurrentUserId too */
-   SetSessionUserId(roleid, AuthenticatedUserIsSuperuser);
+   /* In a parallel worker, ParallelWorkerMain already set these variables */
+   if (!InitializingParallelWorker)
+   {
+       SetAuthenticatedUserId(roleid, is_superuser);
 
-   /* Also mark our PGPROC entry with the authenticated user id */
-   /* (We assume this is an atomic store so no lock is needed) */
-   MyProc->roleId = roleid;
+       /* Set SessionUserId and related variables via the GUC mechanisms */
+       SetConfigOption("session_authorization", rname,
+                       PGC_BACKEND, PGC_S_OVERRIDE);
+   }
 
    /*
     * These next checks are not enforced when in standalone mode, so that
         * just document that the connection limit is approximate.
         */
        if (rform->rolconnlimit >= 0 &&
-           !AuthenticatedUserIsSuperuser &&
+           !is_superuser &&
            CountUserBackends(roleid) > rform->rolconnlimit)
            ereport(FATAL,
                    (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
                            rname)));
    }
 
-   /* Record username and superuser status as GUC settings too */
-   SetConfigOption("session_authorization", rname,
-                   PGC_BACKEND, PGC_S_OVERRIDE);
-   SetConfigOption("is_superuser",
-                   AuthenticatedUserIsSuperuser ? "on" : "off",
-                   PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
-
    ReleaseSysCache(roleTup);
 }
 
    AuthenticatedUserId = BOOTSTRAP_SUPERUSERID;
    AuthenticatedUserIsSuperuser = true;
 
-   SetSessionUserId(BOOTSTRAP_SUPERUSERID, true);
-
    /*
-    * XXX This should set SetConfigOption("session_authorization"), too.
-    * Since we don't, C code will get NULL, and current_setting() will get an
-    * empty string.
+    * XXX Ideally we'd do this via SetConfigOption("session_authorization"),
+    * but we lack the role name needed to do that, and we can't fetch it
+    * because one reason for this special case is to be able to start up even
+    * if something's happened to the BOOTSTRAP_SUPERUSERID's pg_authid row.
+    * Since we don't set the GUC itself, C code will see the value as NULL,
+    * and current_setting() will report an empty string within this session.
     */
-   SetConfigOption("is_superuser", "on",
-                   PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
+   SetSessionAuthorization(BOOTSTRAP_SUPERUSERID, true);
+
+   /* We could do SetConfigOption("role"), but let's be consistent */
+   SetCurrentRoleId(InvalidOid, false);
 }
 
 
 /*
  * Change session auth ID while running
  *
- * Only a superuser may set auth ID to something other than himself.  Note
- * that in case of multiple SETs in a single session, the original userid's
- * superuserness is what matters.  But we set the GUC variable is_superuser
- * to indicate whether the *current* session userid is a superuser.
- *
- * Note: this is not an especially clean place to do the permission check.
- * It's OK because the check does not require catalog access and can't
- * fail during an end-of-transaction GUC reversion, but we may someday
- * have to push it up into assign_session_authorization.
+ * The SQL standard says that SET SESSION AUTHORIZATION implies SET ROLE NONE.
+ * We mechanize that at higher levels not here, because this is the GUC
+ * assign hook for "session_authorization", and it must be commutative with
+ * SetCurrentRoleId (the hook for "role") because guc.c provides no guarantees
+ * which will run first during cases such as transaction rollback.  Therefore,
+ * we update derived state (OuterUserId/CurrentUserId/is_superuser) only if
+ * !SetRoleIsActive.
  */
 void
 SetSessionAuthorization(Oid userid, bool is_superuser)
 {
-   /* Must have authenticated already, else can't make permission check */
-   AssertState(OidIsValid(AuthenticatedUserId));
-
-   if (userid != AuthenticatedUserId &&
-       !AuthenticatedUserIsSuperuser)
-       ereport(ERROR,
-               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-                errmsg("permission denied to set session authorization")));
-
    SetSessionUserId(userid, is_superuser);
 
-   SetConfigOption("is_superuser",
-                   is_superuser ? "on" : "off",
-                   PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
+   if (!SetRoleIsActive)
+       SetOuterUserId(userid, is_superuser);
 }
 
 /*
    /*
     * Get correct info if it's SET ROLE NONE
     *
-    * If SessionUserId hasn't been set yet, just do nothing --- the eventual
-    * SetSessionUserId call will fix everything.  This is needed since we
-    * will get called during GUC initialization.
+    * If SessionUserId hasn't been set yet, do nothing beyond updating
+    * SetRoleIsActive --- the eventual SetSessionAuthorization call will
+    * update the derived state.  This is needed since we will get called
+    * during GUC initialization.
     */
    if (!OidIsValid(roleid))
    {
+       SetRoleIsActive = false;
+
        if (!OidIsValid(SessionUserId))
            return;
 
        roleid = SessionUserId;
        is_superuser = SessionUserIsSuperuser;
-
-       SetRoleIsActive = false;
    }
    else
        SetRoleIsActive = true;
 
-   SetOuterUserId(roleid);
-
-   SetConfigOption("is_superuser",
-                   is_superuser ? "on" : "off",
-                   PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
+   SetOuterUserId(roleid, is_superuser);
 }
 
 
 
        case PGC_STRING:
            {
                struct config_string *conf = (struct config_string *) record;
+               GucContext  orig_context = context;
+               GucSource   orig_source = source;
+               Oid         orig_srole = srole;
 
 #define newval (newval_union.stringval)
 
                    conf->gen.source = source;
                    conf->gen.scontext = context;
                    conf->gen.srole = srole;
+
+                   /*
+                    * Ugly hack: during SET session_authorization, forcibly
+                    * do SET ROLE NONE with the same context/source/etc, so
+                    * that the effects will have identical lifespan.  This is
+                    * required by the SQL spec, and it's not possible to do
+                    * it within the variable's check hook or assign hook
+                    * because our APIs for those don't pass enough info.
+                    * However, don't do it if is_reload: in that case we
+                    * expect that if "role" isn't supposed to be default, it
+                    * has been or will be set by a separate reload action.
+                    *
+                    * A fine point: for RESET session_authorization, we do
+                    * "RESET role" not "SET ROLE NONE" (by passing down NULL
+                    * rather than "none" for the value).  This would have the
+                    * same effects in typical cases, but if the reset value
+                    * of "role" is not "none" it seems better to revert to
+                    * that.
+                    */
+                   if (!is_reload &&
+                       strcmp(conf->gen.name, "session_authorization") == 0)
+                       (void) set_config_option_ext("role",
+                                                    value ? "none" : NULL,
+                                                    orig_context,
+                                                    orig_source,
+                                                    orig_srole,
+                                                    action,
+                                                    true,
+                                                    elevel,
+                                                    false);
                }
 
                if (makeDefault)
     * mechanisms (if indeed they aren't compile-time constants).  So we may
     * always skip these.
     *
-    * Role must be handled specially because its current value can be an
-    * invalid value (for instance, if someone dropped the role since we set
-    * it).  So if we tried to serialize it normally, we might get a failure.
-    * We skip it here, and use another mechanism to ensure the worker has the
-    * right value.
-    *
     * For all other GUCs, we skip if the GUC has its compiled-in default
     * value (i.e., source == PGC_S_DEFAULT).  On the leader side, this means
     * we don't send GUCs that have their default values, which typically
     * comments in RestoreGUCState for more info.
     */
    return gconf->context == PGC_POSTMASTER ||
-       gconf->context == PGC_INTERNAL || gconf->source == PGC_S_DEFAULT ||
-       strcmp(gconf->name, "role") == 0;
+       gconf->context == PGC_INTERNAL ||
+       gconf->source == PGC_S_DEFAULT;
 }
 
 /*
 
 extern Oid GetUserId(void);
 extern Oid GetOuterUserId(void);
 extern Oid GetSessionUserId(void);
+extern bool GetSessionUserIsSuperuser(void);
 extern Oid GetAuthenticatedUserId(void);
+extern bool GetAuthenticatedUserIsSuperuser(void);
+extern void SetAuthenticatedUserId(Oid userid, bool is_superuser);
 extern void GetUserIdAndSecContext(Oid *userid, int *sec_context);
 extern void SetUserIdAndSecContext(Oid userid, int sec_context);
 extern bool InLocalUserIdChange(void);
 
 SET ROLE pg_read_all_settings;
 RESET ROLE;
 RESET SESSION AUTHORIZATION;
+-- test interaction of SET SESSION AUTHORIZATION and SET ROLE,
+-- as well as propagation of these settings to parallel workers
+GRANT regress_priv_user9 TO regress_priv_user8;
+SET SESSION AUTHORIZATION regress_priv_user8;
+SET ROLE regress_priv_user9;
+SET force_parallel_mode = 0;
+SELECT session_user, current_role, current_user, current_setting('role') as role;
+    session_user    |    current_role    |    current_user    |        role        
+--------------------+--------------------+--------------------+--------------------
+ regress_priv_user8 | regress_priv_user9 | regress_priv_user9 | regress_priv_user9
+(1 row)
+
+SET force_parallel_mode = 1;
+SELECT session_user, current_role, current_user, current_setting('role') as role;
+    session_user    |    current_role    |    current_user    |        role        
+--------------------+--------------------+--------------------+--------------------
+ regress_priv_user8 | regress_priv_user9 | regress_priv_user9 | regress_priv_user9
+(1 row)
+
+BEGIN;
+SET SESSION AUTHORIZATION regress_priv_user10;
+SET force_parallel_mode = 0;
+SELECT session_user, current_role, current_user, current_setting('role') as role;
+    session_user     |    current_role     |    current_user     | role 
+---------------------+---------------------+---------------------+------
+ regress_priv_user10 | regress_priv_user10 | regress_priv_user10 | none
+(1 row)
+
+SET force_parallel_mode = 1;
+SELECT session_user, current_role, current_user, current_setting('role') as role;
+    session_user     |    current_role     |    current_user     | role 
+---------------------+---------------------+---------------------+------
+ regress_priv_user10 | regress_priv_user10 | regress_priv_user10 | none
+(1 row)
+
+ROLLBACK;
+SET force_parallel_mode = 0;
+SELECT session_user, current_role, current_user, current_setting('role') as role;
+    session_user    |    current_role    |    current_user    |        role        
+--------------------+--------------------+--------------------+--------------------
+ regress_priv_user8 | regress_priv_user9 | regress_priv_user9 | regress_priv_user9
+(1 row)
+
+SET force_parallel_mode = 1;
+SELECT session_user, current_role, current_user, current_setting('role') as role;
+    session_user    |    current_role    |    current_user    |        role        
+--------------------+--------------------+--------------------+--------------------
+ regress_priv_user8 | regress_priv_user9 | regress_priv_user9 | regress_priv_user9
+(1 row)
+
+RESET SESSION AUTHORIZATION;
+-- session_user at this point is installation-dependent
+SET force_parallel_mode = 0;
+SELECT session_user = current_role as c_r_ok, session_user = current_user as c_u_ok, current_setting('role') as role;
+ c_r_ok | c_u_ok | role 
+--------+--------+------
+ t      | t      | none
+(1 row)
+
+SET force_parallel_mode = 1;
+SELECT session_user = current_role as c_r_ok, session_user = current_user as c_u_ok, current_setting('role') as role;
+ c_r_ok | c_u_ok | role 
+--------+--------+------
+ t      | t      | none
+(1 row)
+
+RESET force_parallel_mode;
 REVOKE pg_read_all_settings FROM regress_priv_user8;
 DROP USER regress_priv_user10;
 DROP USER regress_priv_user9;
 
 RESET ROLE;
 
 RESET SESSION AUTHORIZATION;
+
+-- test interaction of SET SESSION AUTHORIZATION and SET ROLE,
+-- as well as propagation of these settings to parallel workers
+GRANT regress_priv_user9 TO regress_priv_user8;
+
+SET SESSION AUTHORIZATION regress_priv_user8;
+SET ROLE regress_priv_user9;
+SET force_parallel_mode = 0;
+SELECT session_user, current_role, current_user, current_setting('role') as role;
+SET force_parallel_mode = 1;
+SELECT session_user, current_role, current_user, current_setting('role') as role;
+
+BEGIN;
+SET SESSION AUTHORIZATION regress_priv_user10;
+SET force_parallel_mode = 0;
+SELECT session_user, current_role, current_user, current_setting('role') as role;
+SET force_parallel_mode = 1;
+SELECT session_user, current_role, current_user, current_setting('role') as role;
+ROLLBACK;
+SET force_parallel_mode = 0;
+SELECT session_user, current_role, current_user, current_setting('role') as role;
+SET force_parallel_mode = 1;
+SELECT session_user, current_role, current_user, current_setting('role') as role;
+
+RESET SESSION AUTHORIZATION;
+-- session_user at this point is installation-dependent
+SET force_parallel_mode = 0;
+SELECT session_user = current_role as c_r_ok, session_user = current_user as c_u_ok, current_setting('role') as role;
+SET force_parallel_mode = 1;
+SELECT session_user = current_role as c_r_ok, session_user = current_user as c_u_ok, current_setting('role') as role;
+
+RESET force_parallel_mode;
+
 REVOKE pg_read_all_settings FROM regress_priv_user8;
 
 DROP USER regress_priv_user10;