From fb4c5d2798730f60b102d775f22fb53c26a6445d Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Fri, 21 Jan 2011 21:49:19 -0500
Subject: [PATCH] Code cleanup for assign_XactIsoLevel.

The new coding avoids a spurious debug message when a transaction
that has changed the isolation level has been rolled back.  It also
allows the property to be freely changed to the current value within
a subtransaction.

Kevin Grittner, with one small change by me.
---
 src/backend/commands/variable.c | 30 +++++++++++++++---------------
 src/backend/utils/misc/guc.c    |  2 +-
 src/include/utils/guc.h         |  1 +
 3 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 848685f2e8a..1e9bdc3f218 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -546,27 +546,27 @@ show_log_timezone(void)
 /*
  * SET TRANSACTION ISOLATION LEVEL
  */
-
 const char *
 assign_XactIsoLevel(const char *value, bool doit, GucSource source)
 {
-	if (FirstSnapshotSet)
+	/* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
+	if (source != PGC_S_OVERRIDE)
 	{
-		ereport(GUC_complaint_elevel(source),
-				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
-				 errmsg("SET TRANSACTION ISOLATION LEVEL must be called before any query")));
-		/* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
-		if (source != PGC_S_OVERRIDE)
+		if (FirstSnapshotSet)
+		{
+			ereport(GUC_complaint_elevel(source),
+					(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
+					 errmsg("SET TRANSACTION ISOLATION LEVEL must be called before any query")));
 			return NULL;
-	}
-	else if (IsSubTransaction())
-	{
-		ereport(GUC_complaint_elevel(source),
-				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
-				 errmsg("SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction")));
-		/* source == PGC_S_OVERRIDE means do it anyway, eg at xact abort */
-		if (source != PGC_S_OVERRIDE)
+		}
+		/* We ignore a subtransaction setting it to the existing value. */
+		if (IsSubTransaction() && strcmp(value, XactIsoLevel_string) != 0)
+		{
+			ereport(GUC_complaint_elevel(source),
+					(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
+					 errmsg("SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction")));
 			return NULL;
+		}
 	}
 
 	if (strcmp(value, "serializable") == 0)
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index e4dea31e793..ffff6015596 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -425,7 +425,6 @@ static int	server_version_num;
 static char *timezone_string;
 static char *log_timezone_string;
 static char *timezone_abbreviations_string;
-static char *XactIsoLevel_string;
 static char *custom_variable_classes;
 static int	max_function_args;
 static int	max_index_keys;
@@ -440,6 +439,7 @@ static int	effective_io_concurrency;
 /* should be static, but commands/variable.c needs to get at these */
 char	   *role_string;
 char	   *session_authorization_string;
+char	   *XactIsoLevel_string;
 
 
 /*
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 91ad65e721f..c07f263ea07 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -201,6 +201,7 @@ extern char *ConfigFileName;
 extern char *HbaFileName;
 extern char *IdentFileName;
 extern char *external_pid_file;
+extern char *XactIsoLevel_string;
 
 extern char *application_name;
 
-- 
GitLab