There are two things that get mixed up here. ApplyUpdates has nothing to do with transactions.
Cached updates and ApplyUpdates:
Zeos supports a kinda "transactions for the poor" mode which is called cached updates. If you enable this feature on a dataset, changes are not written to the database but are cached in memory. To apply the updates to the database ApplyUpdates has to be called. There should be a similar method called CancelUpdates to make Zeos revert to the original state. This only works on a single dataset. This feature probably is a legacy inherited by trying to copy the BDE. It helps faking a kinda transaction for file based databases that didn't support them at the time - like dbase.
Transactions and nested transactions
In Zeos transactions are managed through the connection object. Zeos supports only one transaction per connection. If one needs multiple transactions, he / she has to use multiple connections to the database. In Zeos transactions are managed by the methods StartTransaction, Commit and Rollback as well as the property AutoCommit.
In Zeos 7.2 it is possible to call StartTransaction several times - but every call to StartTransaction after the first call only increased an internal transaction counter. Commit and Rollback worked the same way - they decreased the transaction counter and did their work only when that counter reached zero.
This can lead to problems in a scenario like this:
Code: Select all
StartTransaction
try
{ do something here }
StartTransaction
try
{ do something here 2}
Commit
except
RollBack; // this RollBack didn't rollback anything
{ cleanupcode }
end;
{ do something here 3}
Commit;
except
RollBack;
end;
In code like this, error situations in the second code block didn't lead to a rollback as one would expect. This is why I created
ticket 238, "Zeos fakes support for nested transactions but does so wrongly". EgonHugeist decided to implement support for nested transactions. On Firebird and maybe other RDBMS these can be created using savepoints. Using savepoints we now can support a scenario like the above. The following code has comments to show what happens behind the scenes in the case of Firebird:
Code: Select all
StartTransaction // Start new transaction using the API
try
{ do something here }
StartTransaction // call "savepoint SP_1"
try
{ do something here 2}
Commit // call "release savepoint SP_1" - we cannot rollback to the state SP_1 after calling this, we only can rollback the whole transaction
except
RollBack; // call "rollback to savepoint SP_1" - restore the state as it was when we created SP_1, changes done afterwards get removed
{ cleanupcode }
end;
{ do something here 3}
Commit; // commit the transaction using the API
except
RollBack; // rollback the transaction using the API
end;
With Zeos 7.3 the internal rollback can now easily revert to the original state.
I hope this helps in understanding the situation
![Smile :)](./images/smilies/icon_smile.gif)
I am open to suggestions on how to improve this. I will make a wiki page of this and also include it in the Zeos 7.3 release notes
![Smile :)](./images/smilies/icon_smile.gif)