]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Revert "Handle better implicit transaction state of pipeline mode"
authorMichael Paquier <michael@paquier.xyz>
Thu, 28 Nov 2024 00:43:21 +0000 (09:43 +0900)
committerMichael Paquier <michael@paquier.xyz>
Thu, 28 Nov 2024 00:43:21 +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 b0fea8f5d5d8f9ce89dded8ed7416ea74ba099a8..5a3d6fdb5a34ac277b22ef264b7081ceef223ff9 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 ed83cc493b84c3591a71dab6a0d03ac83d368c24..4cecf63006043bbc9ad35633f24173e2961bfceb 100644 (file)
@@ -3603,6 +3603,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?
         */
@@ -3714,6 +3724,9 @@ IsInTransactionBlock(bool isTopLevel)
        if (IsSubTransaction())
                return true;
 
+       if (MyXactFlags & XACT_FLAGS_PIPELINING)
+               return true;
+
        if (!isTopLevel)
                return true;
 
index 147baaa054cb20950f94cd5a4e8d430c9f336cf6..a750dc800b6afcf4d1682723a545d3d8cfd08954 100644 (file)
@@ -2775,17 +2775,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
@@ -4971,13 +4960,6 @@ PostgresMain(const char *dbname, const char *username)
 
                        case PqMsg_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 0bc5c0042ebd5b10d981f65d333a548f427df044..956e290f3efab9877ac575a0d74b3c3ee6661f1a 100644 (file)
@@ -968,180 +968,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 SET LOCAL with \syncpipeline.  This succeeds and the command
-# launched after the sync is outside the implicit transaction block
-# of the pipeline, causing a WARNING.
-$node->pgbench(
-       '-t 1 -n -M extended',
-       0,
-       [],
-       [qr{WARNING:  SET LOCAL can only be used in transaction blocks}],
-       'SET LOCAL and \syncpipeline',
-       {
-               '001_pgbench_pipeline_set_local_3' => q{
-\startpipeline
-SELECT 1;
-\syncpipeline
-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',