aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xact.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/transam/xact.c')
-rw-r--r--src/backend/access/transam/xact.c37
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;