Revert "Handle better implicit transaction state of pipeline mode"
authorMichael Paquier <michael@paquier.xyz>
Thu, 28 Nov 2024 00:43:22 +0000 (09:43 +0900)
committerMichael Paquier <michael@paquier.xyz>
Thu, 28 Nov 2024 00:43:22 +0000 (09:43 +0900)
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
src/backend/access/transam/xact.c
src/backend/tcop/postgres.c
src/bin/pgbench/t/001_pgbench_with_server.pl

index 84eec5da7e372a6363666c6eb87a652b97893267..59dbd13d6f6c84f17144368aff8db54e49946abc 100644 (file)
@@ -1070,17 +1070,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>
index cb8bedc46df6ecfbe5d73027d9fbc734da7c496d..4a2ea4adbaf0cd69126138b6e9ea69dfd99066c8 100644 (file)
@@ -3500,6 +3500,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?
     */
@@ -3611,6 +3621,9 @@ IsInTransactionBlock(bool isTopLevel)
    if (IsSubTransaction())
        return true;
 
+   if (MyXactFlags & XACT_FLAGS_PIPELINING)
+       return true;
+
    if (!isTopLevel)
        return true;
 
index 26aaaf19e19d08646b5f6a61424851e5168f2b05..3f427f1b47f3e187b624f5290a0d26ab45ffe34c 100644 (file)
@@ -2780,17 +2780,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
@@ -4929,13 +4918,6 @@ PostgresMain(const char *dbname, const char *username)
 
            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();
                valgrind_report_error_query("SYNC message");
                send_ready_for_query = true;
index 44a98b4d5dfaabebec0f3de0e7a8be66120657f1..afc9ecfaf77fed51fffeaf857d9f17587e44e76f 100644 (file)
@@ -897,161 +897,6 @@ $node->pgbench(
 }
    });
 
-# Try SET LOCAL as first pipeline command.  This succeeds and the first
-# command is not executed inside an implicit transaction block, causing
-# a WARNING.
-$node->pgbench(
-   '-t 1 -n -M extended',
-   0,
-   [],
-   [qr{WARNING:  SET LOCAL can only be used in transaction blocks}],
-   'SET LOCAL outside implicit transaction block of pipeline',
-   {
-       '001_pgbench_pipeline_set_local_1' => q{
-\startpipeline
-SET LOCAL statement_timeout='1h';
-\endpipeline
-}
-   });
-
-# Try SET LOCAL as second pipeline command.  This succeeds and the second
-# command does not cause a WARNING to be generated.
-$node->pgbench(
-   '-t 1 -n -M extended',
-   0,
-   [],
-   [qr{^$}],
-   'SET LOCAL inside implicit transaction block of pipeline',
-   {
-       '001_pgbench_pipeline_set_local_2' => q{
-\startpipeline
-SELECT 1;
-SET LOCAL statement_timeout='1h';
-\endpipeline
-}
-   });
-
-# Try REINDEX CONCURRENTLY as first pipeline command.  This succeeds
-# as the first command is outside the implicit transaction block of
-# a pipeline.
-$node->pgbench(
-   '-t 1 -n -M extended',
-   0,
-   [],
-   [],
-   'REINDEX CONCURRENTLY outside implicit transaction block of pipeline',
-   {
-       '001_pgbench_pipeline_reindex_1' => q{
-\startpipeline
-REINDEX TABLE CONCURRENTLY pgbench_accounts;
-SELECT 1;
-\endpipeline
-}
-   });
-
-# Try REINDEX CONCURRENTLY as second pipeline command.  This fails
-# as the second command is inside an implicit transaction block.
-$node->pgbench(
-   '-t 1 -n -M extended',
-   2,
-   [],
-   [],
-   'error: REINDEX CONCURRENTLY inside implicit transaction block of pipeline',
-   {
-       '001_pgbench_pipeline_reindex_2' => q{
-\startpipeline
-SELECT 1;
-REINDEX TABLE CONCURRENTLY pgbench_accounts;
-\endpipeline
-}
-   });
-
-# Try VACUUM as first pipeline command.  Like REINDEX CONCURRENTLY, this
-# succeeds as this is outside the implicit transaction block of a pipeline.
-$node->pgbench(
-   '-t 1 -n -M extended',
-   0,
-   [],
-   [],
-   'VACUUM outside implicit transaction block of pipeline',
-   {
-       '001_pgbench_pipeline_vacuum_1' => q{
-\startpipeline
-VACUUM pgbench_accounts;
-\endpipeline
-}
-   });
-
-# Try VACUUM as second pipeline command.  This fails, as the second command
-# of a pipeline is inside an implicit transaction block.
-$node->pgbench(
-   '-t 1 -n -M extended',
-   2,
-   [],
-   [],
-   'error: VACUUM inside implicit transaction block of pipeline',
-   {
-       '001_pgbench_pipeline_vacuum_2' => q{
-\startpipeline
-SELECT 1;
-VACUUM pgbench_accounts;
-\endpipeline
-}
-   });
-
-# Try subtransactions in a pipeline.  These are forbidden in implicit
-# transaction blocks.
-$node->pgbench(
-   '-t 1 -n -M extended',
-   2,
-   [],
-   [],
-   'error: subtransactions not allowed in pipeline',
-   {
-       '001_pgbench_pipeline_subtrans' => q{
-\startpipeline
-SAVEPOINT a;
-SELECT 1;
-ROLLBACK TO SAVEPOINT a;
-SELECT 2;
-\endpipeline
-}
-   });
-
-# Try LOCK TABLE as first pipeline command.  This fails as LOCK is outside
-# an implicit transaction block.
-$node->pgbench(
-   '-t 1 -n -M extended',
-   2,
-   [],
-   [],
-   'error: LOCK TABLE outside implicit transaction block of pipeline',
-   {
-       '001_pgbench_pipeline_lock_1' => q{
-\startpipeline
-LOCK pgbench_accounts;
-SELECT 1;
-\endpipeline
-}
-   });
-
-# Try LOCK TABLE as second pipeline command.  This succeeds as LOCK is inside
-# an implicit transaction block.
-$node->pgbench(
-   '-t 1 -n -M extended',
-   0,
-   [],
-   [],
-   'LOCK TABLE inside implicit transaction block of pipeline',
-   {
-       '001_pgbench_pipeline_lock_2' => q{
-\startpipeline
-SELECT 1;
-LOCK pgbench_accounts;
-\endpipeline
-}
-   });
-
 # Working \startpipeline in prepared query mode with serializable
 $node->pgbench(
    '-c4 -t 10 -n -M prepared',