@ -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 ) ;
@ -2948,6 +2950,26 @@ PreventTransactionChain(bool isTopLevel, const char *stmtType)
/* all okay */
}
/*
* 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
*
@ -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
Require TransactionChain( bool isTopLevel , const char * stmtType )
static void
Check TransactionChain( 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 ;