The BEGIN TRANSACTION statement marks the start of a new transaction.
COMMIT / ROLLBACK
A transaction is a group of updates that must either be performed in their entirety or not at all. The BEGIN TRANSACTION statement starts a new transaction. All updates until a corresponding END TRANSACTION are cached and only applied to the database when a COMMIT statement is executed. Execution of the program then continues at the statement following the END TRANSACTION.
The ROLLBACK statement discards any cached updates and continues at the statement following the END TRANSACTION. A roll-back is implied if the program executes the END TRANSACTION directly.
Testing the value of the STATUS() function immediately after the END TRANSACTION statement will return 0 if the transaction committed successfully, ER_COMMIT_FAIL if an error occurred during the commit action, or ER_ROLLBACK if the transaction was rolled back.
Deletes and writes inside a transaction will fail unless the program holds an update lock on the record or the file. All locks obtained inside the transaction are retained until the transaction terminates and are then released. Locks already owned when the transaction begins will still be present after the transaction terminates, even if the record is updated or deleted within the transaction.
Closing a file inside a transaction appears to work in that the file variable is destroyed though the actual close is deferred until the transaction terminates and any updates have been applied to the file. Rolling back the transaction will not reinstate the file variable.
Updates to sequential records opened using OPENSEQ are not affected by transactions.
Transactions may be nested. If the BEGIN TRANSACTION statement is executed inside an active transaction, the active transaction is stacked and a new transaction commences. Termination of the new transaction reverts to the stacked transaction. The default behaviour of QM is that transactions are durable such that updates in a child transaction are applied to the data files on use of COMMIT. The NON.DURABLE.TXN setting of the QMBasic $MODE compiler directive, makes transactions non-durable such that updates in a child transaction are inherited by the parent transaction on COMMIT.
The following operations are banned inside transactions:
READU CUST1.REC FROM CUST.F, CUST1.ID ELSE ROLLBACK
CUST1.REC<C.BALANCE> -= TRANSFER.VALUE
WRITE CUST1.REC TO CUST.F, CUST1.ID
READU CUST2.REC FROM CUST.F, CUST2.ID ELSE ROLLBACK
CUST2.REC<C.BALANCE> += TRANSFER.VALUE
WRITE CUST2.REC TO CUST.F, CUST2.ID
The above program fragment transfers money between two customer accounts. The updates are only committed if the entire transaction is successful.