Transaction management
Against databases that use logging, a UDR inherits the transaction state that is started by the SQL statement that invoked the UDR.
All statements in a UDR occur inside a transaction because the UDR is called from within an SQL statement. An SQL statement is always part of a transaction. The type of transaction that the SQL statement is part of is based on the type of database and whether it uses transaction logging, as the following table shows.
Status of database | Status of SQL statement | ANSI-compliant | Description |
---|---|---|---|
Database does not use transaction logging. | No transactions exist. | Yes | The database server does not log changes to the database that SQL statements might make. Any UDRs that are part of the SQL statement are not logged and their actions cannot be rolled back. |
Database uses transaction logging. | Explicit transaction | Yes | The client application begins an explicit transaction with
the BEGIN WORK statement and ends it with either the COMMIT WORK statement
(transaction successful) or the ROLLBACK WORK statement (transaction
not successful). Operations within a single cursor (from OPEN to CLOSE)
constitute a transaction as well. SQL statements between the BEGIN WORK and COMMIT WORK or ROLLBACK WORK statements (or within a cursor) execute within the explicit transaction. If these SQL statements contain any UDRs, each of the UDRs executes within the explicit transaction. |
Database uses transaction logging. | Single-statement transaction | Yes | The client application begins a single-statement transaction for any SQL statement that is not contained within a BEGIN WORK statement and a COMMIT WORK or ROLLBACK WORK statement. Any UDRs that are part of the SQL statement are within this single-statement transaction. The only exception to this rule is the EXECUTE FUNCTION statement; it does not execute within a transaction. |
Database logging is always in effect. | Each SQL statement executes within an implicit transaction, which is always in effect. | No | The client application invokes an SQL statement, which begins the implicit transaction, and the transaction ends explicitly with COMMIT WORK or ROLLBACK WORK. Any UDRs within the SQL statement that began the implicit transaction are automatically part of the transaction. In addition, any SQL statements that execute before the COMMIT WORK or ROLLBACK WORK statement ends the transaction are also part of the implicit transaction. |
You can obtain the transaction ID of the current transaction with the mi_get_transaction_id() function.
- BEGIN WORK
- COMMIT WORK
- ROLLBACK WORK
In all databases that use logging, an SQL statement is within a transaction. In such databases, a DML statement (SELECT, INSERT, UPDATE, DELETE) implicitly starts a transaction, if a transaction is not already in effect. If a UDR that executes one of these SQL transaction statements is called from a DML statement, the database server raises an error (-535).
However, the EXECUTE PROCEDURE and EXECUTE FUNCTION statements do not implicitly start another transaction, if they are not already in a transaction. If a UDR is called from an EXECUTE PROCEDURE or EXECUTE FUNCTION statement, the database server only raises an error if the UDR interferes with the current transaction boundaries.
void udr1(...)
{
mi_exec(...DML statement 1...);
mi_exec(...DML statement 2...);
}
EXECUTE PROCEDURE udr1();
If a transaction has not already been started, this UDR would have two transactions, one for each call to mi_exec().
void udr2(...)
{
mi_exec(...'begin work'..);
mi_exec(...DML statement 1...);
mi_exec(...DML statement 2...);
mi_exec(...'commit work'...);
}
- You must invoke the UDR with the EXECUTE PROCEDURE or EXECUTE
FUNCTION statement. Because udr2() is a user-defined procedure, you must use EXECUTE PROCEDURE to invoke it, as follows:
EXECUTE PROCEDURE udr2();
Suppose you tried to invoke udr2() with the following SELECT statement:SELECT udr2() FROM tab WHERE x=y;
If a transaction had not started, the SELECT operation starts its own implicit transaction. The database server raises an error when execution reaches the first call to mi_exec() in udr2():mi_exec(...'begin work'..);
- The UDR calling context must not have already started a transaction. The following code fragment fails because the EXECUTE PROCEDURE statement is already within a transaction block and udr2() attempts to start another transaction:
BEGIN WORK; ... EXECUTE PROCEDURE udr2(); /* This statement fails. */ ... COMMIT WORK:
The database server raises an error when execution reaches the first call to mi_exec() in udr2():mi_exec(...'begin work'..);
You can execute an SQL transaction statement in a UDR that you call directly from a DataBlade API module (not from within an SQL statement). You can also choose whether to commit or rollback the current transaction from within an end-of-statement or end-of-transaction callback function. For more information, see State transitions in a C UDR (Server).