How Transaction Control is Implemented in CacheRDD
CachéRDD supports TRANSACTION control. This means either a transaction will be posted in its entirity or nothing will be changed in the database. CachéRDD also supports nested transactions, but it need to be investigated deeply. Theoretically there should not be a problem, but...
The structure of a transaction control is simple one. Let me illustrate this with an example:
//----------------------------------------------------------------------//
Function TestTransactions()
Local n,x,y, nSel,
Local nUpdate := 0
Local getlist := {}
CLS
@ 1,2 get nUpdate
read
select( 'mytable' )
dbgotop()
TRY
CachéBeginTransaction()
n := 1.3
do while .t.
dbskip()
? 'Before Update =', mytable->code, mytable->salary
n++
if rLock()
replace mytable->salary with nUpdate/n
DbUnlock()
endif
nSel := alert( 'Action ?',{ 'Update More','Error - Rollback','Exit - Commit' } )
if nSel == 3
exit
endif
if nSel = 2
x := y / 200 // Here it will jump to CATCH
endif
? 'After Update = ', mytable->code, mytable->salary
enddo
DbUnlock()
CachéEndTransaction()
CATCH
DbUnlock()
? 'About to rollback...press a key'
inkey( 0 )
CachéRollbackTransaction()
FINALLY
END
Return nil
//----------------------------------------------------------------------//
During a transaction you are free to open any DML commands. The only exception to this rule is DbCreate(). You can obtain any number of locks and you may use DbCommit*() at any point. Your transaction is secure even with all those functions which otherwise physically commit to database in xbase specific RDD's. This way you can always feel secure even if you do not change a single line of your code. Just guard your table updation sections of your application with CachéBeginTransaction() / CachéEndTransaction() construct.
If a r/t error is raised during updation of the tables, you will have to control rollback yourself, e.g., as above. You will have to explicitily call CachéRollbackTransaction(). If your application terminated abruptly without raising a run-time error, you can be sure that your transaction is not posted at all. Caché server automatically rolls back in case a transaction is in progress after CachéBeginTransaction() and does not receive CachéEndTransaction() message. This unfortunate scenario can occur in case of electicity failures, network failure, etc.