Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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',