diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/xact.c | 28 | ||||
-rw-r--r-- | src/backend/tcop/postgres.c | 12 | ||||
-rw-r--r-- | src/include/access/xact.h | 7 |
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 |