aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xact.c28
-rw-r--r--src/backend/tcop/postgres.c12
-rw-r--r--src/include/access/xact.h7
3 files changed, 37 insertions, 10 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 2cfd3c9b552..bf551b0395f 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -3427,6 +3427,16 @@ PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
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?
*/
if (!isTopLevel)
@@ -3515,9 +3525,11 @@ CheckTransactionBlock(bool isTopLevel, bool throwError, const char *stmtType)
* a transaction block than when running as single commands. ANALYZE is
* currently the only example.
*
- * If this routine returns "false", then the calling statement is
- * guaranteed that if it completes without error, its results will be
- * committed immediately.
+ * If this routine returns "false", then the calling statement is allowed
+ * to perform internal transaction-commit-and-start cycles; there is not a
+ * risk of messing up any transaction already in progress. (Note that this
+ * is not the identical guarantee provided by PreventInTransactionBlock,
+ * since we will not force a post-statement commit.)
*
* isTopLevel: passed down from ProcessUtility to determine whether we are
* inside a function.
@@ -3535,6 +3547,9 @@ IsInTransactionBlock(bool isTopLevel)
if (IsSubTransaction())
return true;
+ if (MyXactFlags & XACT_FLAGS_PIPELINING)
+ return true;
+
if (!isTopLevel)
return true;
@@ -3542,13 +3557,6 @@ IsInTransactionBlock(bool isTopLevel)
CurrentTransactionState->blockState != TBLOCK_STARTED)
return true;
- /*
- * If we tell the caller we're not in a transaction block, then inform
- * postgres.c that it had better commit when the statement is done.
- * Otherwise our report could be a lie.
- */
- MyXactFlags |= XACT_FLAGS_NEEDIMMEDIATECOMMIT;
-
return false;
}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2278d8569ed..65083a75741 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -2227,6 +2227,12 @@ exec_execute_message(const char *portal_name, long max_rows)
CommandCounterIncrement();
/*
+ * Set XACT_FLAGS_PIPELINING whenever we complete an Execute
+ * message without immediately committing the transaction.
+ */
+ MyXactFlags |= XACT_FLAGS_PIPELINING;
+
+ /*
* Disable statement timeout whenever we complete an Execute
* message. The next protocol message will start a fresh timeout.
*/
@@ -2241,6 +2247,12 @@ exec_execute_message(const char *portal_name, long max_rows)
/* Portal run not complete, so send PortalSuspended */
if (whereToSendOutput == DestRemote)
pq_putemptymessage('s');
+
+ /*
+ * Set XACT_FLAGS_PIPELINING whenever we suspend an Execute message,
+ * too.
+ */
+ MyXactFlags |= XACT_FLAGS_PIPELINING;
}
/*
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index c538758de1b..5af78bd0dc7 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -114,6 +114,13 @@ extern int MyXactFlags;
#define XACT_FLAGS_NEEDIMMEDIATECOMMIT (1U << 2)
/*
+ * XACT_FLAGS_PIPELINING - set when we complete an extended-query-protocol
+ * Execute message. This is useful for detecting that an implicit transaction
+ * block has been created via pipelining.
+ */
+#define XACT_FLAGS_PIPELINING (1U << 3)
+
+/*
* start- and end-of-transaction callbacks for dynamically loaded modules
*/
typedef enum