As written in the Safari Client-Side Storage and Offline Applications Programming Guide, rolling back a HTML 5 Web SQL Database transaction is done by returning true in the callback function provided as an error callback to a transaction the executeSql
method:
The per-query error-handling callback is rather straightforward. If the callback returns true, the entire transaction is rolled back. If the callback returns false, the transaction continues as if nothing had gone wrong. Thus, if you are executing a query that is optional—if a failure of that particular query should not cause the transaction to fail—you should pass in a callback that returns false. If a failure of the query should cause the entire transaction to fail, you should pass in a callback that returns true.
For example if I have the following transaction (suppose the 'users' table has a UNIQUE constraint on the 'username' field and username 'test' already exists - which I'm trying to insert again, which should result in a constraint error):
database.transaction(function(transaction) {
transaction.executeSql(
"INSERT INTO users (username) VALUES('test')",
null,
dataCallback,
errorCallback
);
});
function errorCallback() {
return true; //this causes the rollback
}
I have two questions:
If I have to include many operations inside a transaction (for example I have to send some data using ajax to a server and wait for the response, etc.) and the user reloads the page before the response had arrived (which means that the errorCallback won't be called), will the transaction be commited or will it fail ?
Does anyone know how to rollback a Web SQL transaction manually ? For example if I want to rollback a transaction based on the result of an ajax call, how can it be done ? Should I run a query which contains an error to make sure that the error callback is called ?
Thanks.
The COMMIT statement lets a user save any changes or alterations on the current transaction. These changes then remain permanent. The ROLLBACK statement lets a user undo all the alterations and changes that occurred on the current transaction after the last COMMIT.
I have confirmed that after rollback we cannot commit the same transaction. Make sure another transaction is not in waiting, else it will be committed. Also don't do anything with transaction in finally block. Always use finally block to close connection , data reader etc.
A transaction ends when it is committed or rolled back, either explicitly (with a COMMIT or ROLLBACK statement) or implicitly (when a DDL statement is issued). To illustrate the concept of a transaction, consider a banking database.
The rollback SQL statement is used to manually rollback transactions in MS SQL Server.
abort
method.Regarding AJAX, be ready all data, before you start a write transaction. You won't have any problem as you described. Use database constraint (UNIQUE, FOREIGNKEY) as much possible.
Have you found a way to do AJAX calls during the transaction? I haven't finished reading the whole spec, but so far it looks like once your SQLTransactionCallback
or SQLTransactionSyncCallback
returns, you can’t add any more stuff to the transaction — or can you? Maybe from the results callback?
Edit: Now that I look again, the spec (which contains many fewer errors than the Apple document you linked to, but is not as easy to read) says this:
- If the method [
executeSql
] was not invoked during the execution of aSQLTransactionCallback
,SQLStatementCallback
, orSQLStatementErrorCallback
then raise anINVALID_STATE_ERR
exception.
So I think that means there's no way to do it.
Further edit: No, wait! As long as the SQLStatementCallback
takes some time to get called, you could busy-wait doing select 3 + 4
over and over again, each time from the statement callback of the previous select 3 + 4
, until your AJAX call sets a flag somewhere that has the data you want. This is terrible programming (it'll eat lots of CPU for no good reason, might block lower-priority tasks like redisplaying the page) but I think it's probably the only way to keep a transaction open for an arbitrary period of time. Too bad you can't select 3 + 4, sleep(1)
in SQLite.
In general SQLite (the underlying storage engine here) rolls back uncompleted transactions. I haven’t yet tested the page-reload error case you're asking about. I would be very surprised if it was committed.
By the way, thank you very much for posting this question. I had been trying to figure out how to get the transaction to rollback, even though it is meticulously documented in the original spec.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With