From 24da0e761837fc0c0ef5733519595c848e5fe280 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Thu, 28 Nov 2024 09:43:28 +0900
Subject: [PATCH] Revert "Handle better implicit transaction state of pipeline
 mode"

This reverts commit d77f91214fb7 on all stable branches, due to concerns
regarding the compatility side effects this could create in a minor
release.  The change still exists on HEAD.

Discussion: https://postgr.es/m/CA+TgmoZqRgeFTg4+Yf_CMRRXiHuNz1u6ZC4FvVk+rxw0RmOPnw@mail.gmail.com
Backpatch-through: 13
---
 doc/src/sgml/protocol.sgml        | 21 ++++++++++-----------
 src/backend/access/transam/xact.c | 13 +++++++++++++
 src/backend/tcop/postgres.c       | 18 ------------------
 3 files changed, 23 insertions(+), 29 deletions(-)

diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 9a5b7eeb4a8..812c07e500f 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -1088,17 +1088,16 @@ SELCT 1/0;<!-- this typo is intentional -->
 
    <para>
     If the client has not issued an explicit <command>BEGIN</command>,
-    then an implicit transaction block is started and each Sync ordinarily
-    causes an implicit <command>COMMIT</command> if the preceding step(s)
-    succeeded, or an implicit <command>ROLLBACK</command> if they failed.
-    This implicit transaction block will only be detected by the server
-    when the first command ends without a sync.  There are a few DDL
-    commands (such as <command>CREATE DATABASE</command>) that cannot be
-    executed inside a transaction block. If one of these is executed in a
-    pipeline, it will fail unless it is the first command after a Sync.
-    Furthermore, upon success it will force an immediate commit to preserve
-    database consistency. Thus a Sync immediately following one of these
-    commands has no effect except to respond with ReadyForQuery.
+    then each Sync ordinarily causes an implicit <command>COMMIT</command>
+    if the preceding step(s) succeeded, or an
+    implicit <command>ROLLBACK</command> if they failed.  However, there
+    are a few DDL commands (such as <command>CREATE DATABASE</command>)
+    that cannot be executed inside a transaction block.  If one of
+    these is executed in a pipeline, it will fail unless it is the first
+    command in the pipeline.  Furthermore, upon success it will force an
+    immediate commit to preserve database consistency.  Thus a Sync
+    immediately following one of these commands has no effect except to
+    respond with ReadyForQuery.
    </para>
 
    <para>
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 423545e6038..ffe26e26f66 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -3405,6 +3405,16 @@ PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
 				 errmsg("%s cannot run inside a subtransaction",
 						stmtType)));
 
+	/*
+	 * inside a pipeline that has started an implicit transaction?
+	 */
+	if (MyXactFlags & XACT_FLAGS_PIPELINING)
+		ereport(ERROR,
+				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
+		/* translator: %s represents an SQL statement name */
+				 errmsg("%s cannot be executed within a pipeline",
+						stmtType)));
+
 	/*
 	 * inside a function call?
 	 */
@@ -3516,6 +3526,9 @@ IsInTransactionBlock(bool isTopLevel)
 	if (IsSubTransaction())
 		return true;
 
+	if (MyXactFlags & XACT_FLAGS_PIPELINING)
+		return true;
+
 	if (!isTopLevel)
 		return true;
 
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index d375d845b97..ec630b44916 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -2656,17 +2656,6 @@ start_xact_command(void)
 
 		xact_started = true;
 	}
-	else if (MyXactFlags & XACT_FLAGS_PIPELINING)
-	{
-		/*
-		 * When the first Execute message is completed, following commands
-		 * will be done in an implicit transaction block created via
-		 * pipelining. The transaction state needs to be updated to an
-		 * implicit block if we're not already in a transaction block (like
-		 * one started by an explicit BEGIN).
-		 */
-		BeginImplicitTransactionBlock();
-	}
 
 	/*
 	 * Start statement timeout if necessary.  Note that this'll intentionally
@@ -4616,13 +4605,6 @@ PostgresMain(int argc, char *argv[],
 
 			case 'S':			/* sync */
 				pq_getmsgend(&input_message);
-
-				/*
-				 * If pipelining was used, we may be in an implicit
-				 * transaction block. Close it before calling
-				 * finish_xact_command.
-				 */
-				EndImplicitTransactionBlock();
 				finish_xact_command();
 				send_ready_for_query = true;
 				break;
-- 
2.39.5