diff options
Diffstat (limited to 'src/backend/access/transam/xact.c')
-rw-r--r-- | src/backend/access/transam/xact.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 0591f3fd562..bab048d38a1 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -265,6 +265,8 @@ static void CallSubXactCallbacks(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid); static void CleanupTransaction(void); +static void CheckTransactionChain(bool isTopLevel, bool throwError, + const char *stmtType); static void CommitTransaction(void); static TransactionId RecordTransactionAbort(bool isSubXact); static void StartTransaction(void); @@ -2949,6 +2951,26 @@ PreventTransactionChain(bool isTopLevel, const char *stmtType) } /* + * These two functions allow for warnings or errors if a command is + * executed outside of a transaction block. + * + * While top-level transaction control commands (BEGIN/COMMIT/ABORT) and + * SET that have no effect issue warnings, all other no-effect commands + * generate errors. + */ +void +WarnNoTransactionChain(bool isTopLevel, const char *stmtType) +{ + CheckTransactionChain(isTopLevel, false, stmtType); +} + +void +RequireTransactionChain(bool isTopLevel, const char *stmtType) +{ + CheckTransactionChain(isTopLevel, true, stmtType); +} + +/* * RequireTransactionChain * * This routine is to be called by statements that must run inside @@ -2957,16 +2979,16 @@ PreventTransactionChain(bool isTopLevel, const char *stmtType) * is presumably an error). DECLARE CURSOR is an example. * * If we appear to be running inside a user-defined function, we do not - * issue an error, since the function could issue more commands that make + * issue anything, since the function could issue more commands that make * use of the current statement's results. Likewise subtransactions. * Thus this is an inverse for PreventTransactionChain. * * isTopLevel: passed down from ProcessUtility to determine whether we are * inside a function. - * stmtType: statement type name, for error messages. + * stmtType: statement type name, for warning or error messages. */ -void -RequireTransactionChain(bool isTopLevel, const char *stmtType) +static void +CheckTransactionChain(bool isTopLevel, bool throwError, const char *stmtType) { /* * xact block already started? @@ -2986,11 +3008,12 @@ RequireTransactionChain(bool isTopLevel, const char *stmtType) if (!isTopLevel) return; - ereport(ERROR, + ereport(throwError ? ERROR : WARNING, (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION), /* translator: %s represents an SQL statement name */ errmsg("%s can only be used in transaction blocks", stmtType))); + return; } /* @@ -3425,12 +3448,12 @@ UserAbortTransactionBlock(void) /* * The user issued ABORT when not inside a transaction. Issue a - * NOTICE and go to abort state. The upcoming call to + * WARNING and go to abort state. The upcoming call to * CommitTransactionCommand() will then put us back into the * default state. */ case TBLOCK_STARTED: - ereport(NOTICE, + ereport(WARNING, (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION), errmsg("there is no transaction in progress"))); s->blockState = TBLOCK_ABORT_PENDING; |