[whatwg] Comments on updated SQL API

Timothy Hatcher timothy at apple.com
Sat Sep 22 09:45:03 PDT 2007

The callback syntax is nice but the implicit thread-global transaction  
is confusing and can lead to programmer error and unneeded database  

Commonly there is a implicit transaction per query if there is no  
explicit transaction created. I think this is what developers will  
expect, after using server side databases. In a complex web  
application, an implicit thread-global transaction will cause  
questions on when it began. The code can be spread all over, and will  
not always be written out using closures for the callbacks.

It doesn't look like you can rollback the implicit transaction (one of  
the big features of transactions.) Also what access locks does the  
implicit transaction take? What if you need exclusive access to the  
database temporarily? These cases would be solved by adding explicit  
transactions with control to access locks and rolling back.

If explicit transactions are not added developers will take advantage  
of what they have access to using the implicit transactions. (I assume  
each Database object will have it's own implicit thread-global  
transaction.) So you could open two Database objects for the same  
database and execute two simultaneous implicit transactions. But you  
would need to write your own rollback code if you need to  
programatically bail out of a transaction and restore any previous  

I propose that the implicit transaction be scoped to only one query at  
a time, like I mentioned earlier. Then add explicit transactions that  
you create from a Database object. Then you can start two simultaneous  
transactions on the same Database object, which is nicer than holding  
two Database objects for the same database just for concurrent access.

Here is an example:

     transation1 = db.beginTransation();
     transation1.executeQuery("SELECT * FROM document",  
function(result1) {
         if(...) {
             result1.transation.executeQuery("UPDATE document WITH ...  
WHERE document = ?", result1.namedItem("id"), function(result2) {

     transation2 =  
     transation2.executeQuery("UPDATE user WITH ... WHERE user = ?",  
"123", function(result1) {
         if(...) {
             result1.transation.executeQuery("UPDATE user WITH ...  
WHERE user = ?", result1.namedItem("id"), function(result2) {
         } else {

My example executes queries on the transaction object. The transaction  
object would internally keep track of the database connection it  
holds. Transactions can come in a couple of forms, shared and  
exclusive access locks (read http://www.sqlite.org/ 
lang_transaction.html for details on these.)

I think an explicit commit should be required for the transactions. So  
you can keep the transcript object around and add to it over time.

Above I have beginTransation taking a constant  
Database.ExclusiveTransactionLocks. Passing no argument would get  
shared access locks. Also in my example is an explicit rollback. Any  
query that fails will naturally rollback the transaction, but having  
progrmatic way to rollback is a necessity.

The closeTransaction Database object function should be remove if  
explicit transactions are added and the implicit transaction is  
limited to one query.

Some other comments:

You might notice that I have been using executeQuery() instead of  
executeSql(). I think it is weird and unneeded to say Sql in the  
function name. If anything, it should be executeSQL().

I think the ResultSet object should have a property to get the  
Database and the Transaction objects. As I mentioned earlier, not  
everyone will use closures and will need access to these to do  
anything else.

— Timothy Hatcher

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.whatwg.org/pipermail/whatwg-whatwg.org/attachments/20070922/088a0da9/attachment-0001.htm>

More information about the whatwg mailing list