aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/variable.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2024-07-31 18:54:10 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2024-07-31 18:54:10 -0400
commitf5f30c22ed69fb37b896c4d4546b2ab823c3fd61 (patch)
treec9e42ffc096404be7f008b9355e3634aa41c546e /src/backend/commands/variable.c
parentbd15b7db489deadb2d9af7f21d16a6ed4a09465b (diff)
downloadpostgresql-f5f30c22ed69fb37b896c4d4546b2ab823c3fd61.tar.gz
postgresql-f5f30c22ed69fb37b896c4d4546b2ab823c3fd61.zip
Allow parallel workers to cope with a newly-created session user ID.
Parallel workers failed after a sequence like BEGIN; CREATE USER foo; SET SESSION AUTHORIZATION foo; because check_session_authorization could not see the uncommitted pg_authid row for "foo". This is because we ran RestoreGUCState() in a separate transaction using an ordinary just-created snapshot. The same disease afflicts any other GUC that requires catalog lookups and isn't forgiving about the lookups failing. To fix, postpone RestoreGUCState() into the worker's main transaction after we've set up a snapshot duplicating the leader's. This affects check_transaction_isolation and check_transaction_deferrable, which think they should only run during transaction start. Make them act like check_transaction_read_only, which already knows it should silently accept the value when InitializingParallelWorker. Per bug #18545 from Andrey Rachitskiy. Back-patch to all supported branches, because this has been wrong for awhile. Discussion: https://postgr.es/m/18545-feba138862f19aaa@postgresql.org
Diffstat (limited to 'src/backend/commands/variable.c')
-rw-r--r--src/backend/commands/variable.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index f44d942aa4d..e3f9f110d87 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -577,14 +577,16 @@ check_transaction_read_only(bool *newval, void **extra, GucSource source)
* We allow idempotent changes at any time, but otherwise this can only be
* changed in a toplevel transaction that has not yet taken a snapshot.
*
- * As in check_transaction_read_only, allow it if not inside a transaction.
+ * As in check_transaction_read_only, allow it if not inside a transaction,
+ * or if restoring state in a parallel worker.
*/
bool
check_transaction_isolation(int *newval, void **extra, GucSource source)
{
int newXactIsoLevel = *newval;
- if (newXactIsoLevel != XactIsoLevel && IsTransactionState())
+ if (newXactIsoLevel != XactIsoLevel &&
+ IsTransactionState() && !InitializingParallelWorker)
{
if (FirstSnapshotSet)
{
@@ -619,6 +621,10 @@ check_transaction_isolation(int *newval, void **extra, GucSource source)
bool
check_transaction_deferrable(bool *newval, void **extra, GucSource source)
{
+ /* Just accept the value when restoring state in a parallel worker */
+ if (InitializingParallelWorker)
+ return true;
+
if (IsSubTransaction())
{
GUC_check_errcode(ERRCODE_ACTIVE_SQL_TRANSACTION);