diff options
Diffstat (limited to 'src/backend/access/transam/xact.c')
-rw-r--r-- | src/backend/access/transam/xact.c | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 4711c091c78..607a47f1246 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.138 2002/11/13 03:12:05 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.139 2002/11/18 01:17:39 tgl Exp $ * * NOTES * Transaction aborts can now occur two ways: @@ -1488,6 +1488,50 @@ PreventTransactionChain(void *stmtNode, const char *stmtType) } } +/* -------------------------------- + * RequireTransactionChain + * + * This routine is to be called by statements that must run inside + * a transaction block, because they have no effects that persist past + * transaction end (and so calling them outside a transaction block + * 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 + * use of the current statement's results. Thus this is an inverse for + * PreventTransactionChain. + * + * stmtNode: pointer to parameter block for statement; this is used in + * a very klugy way to determine whether we are inside a function. + * stmtType: statement type name for error messages. + * -------------------------------- + */ +void +RequireTransactionChain(void *stmtNode, const char *stmtType) +{ + /* + * xact block already started? + */ + if (IsTransactionBlock()) + return; + /* + * Are we inside a function call? If the statement's parameter block + * was allocated in QueryContext, assume it is an interactive command. + * Otherwise assume it is coming from a function. + */ + if (!MemoryContextContains(QueryContext, stmtNode)) + return; + /* + * If we are in autocommit-off mode then it's okay, because this + * statement will itself start a transaction block. + */ + if (!autocommit && !suppressChain) + return; + /* translator: %s represents an SQL statement name */ + elog(ERROR, "%s may only be used in begin/end transaction blocks", + stmtType); +} + /* ---------------------------------------------------------------- * transaction block support |