W3C home > Mailing lists > Public > public-webapps@w3.org > January to March 2010

[WebSQLDatabase] openDatabase() creation callback

From: Dumitru Daniliuc <dumi@google.com>
Date: Tue, 23 Feb 2010 16:23:14 -0800
Message-ID: <e753f47f1002231623k71af2c78nd0a48012f467affa@mail.gmail.com>
To: public-webapps <public-webapps@w3.org>

I know that not many people on this list care about the WebSQLDatabase spec
anymore (especially when it comes to changing it), but Chromium extension
developers do. So I was hoping somebody could explain the idea behind having
openDatabase() take a creationCallback. As I understand it, the callback is
supposed to be a place where the user initiates the DB (changes version,
creates tables, etc.). However, if we follow the spec, then this callback
becomes quite useless.

*Example 1:*

function creationCallback(db) {
  db.transaction(...);   // change version, create tables, etc.

var db = openDatabase(..., creationCallback);

According to the spec, if the database doesn't exist, we must queue a task
to run creationCallback (4.1) and return from openDatabase(). Then we queue
up tasks for the 2 transactions (4.3.2). So our queue ends up looking like

1. invoke creationCallback
2. invoke the transaction callback for tx1
3. invoke the transaction callback for tx2

Now we invoke creationCallback, and find a transaction there, so we queue up
a task to invoke the transaction callback (4.3.2). Now our queue looks like

1. invoke transaction callback for tx1
2. invoke transaction callback for tx2
3. invoke transaction callback for the transaction defined inside

As you can see, if we follow the spec, we end up running the transaction(s)
in creationCallback AFTER all other transactions in the code. So what's the
point of having a creationCallback?

*Example 2:*

function creationCallback(db) {
  db.changeVersion(...); // change version to 1.0

var db1 = openDatabase("db", "1.0", "", 1, creationCallback);
var db2 = openDatabase("db", "1.0", "", 1);

According to the spec, if "db" doesn't exist, then the first openDatabase()
will set the version to "" (empty string) and queue up the creationCallback.
Now before we have a chance to invoke the creationCallback, the second call
to openDatabase() happens, and fails with a INVALID_STATE_ERR (as requested
by the spec), because a database with that name exists, it's version is "",
and we expect the version to be "1.0". So again, the creationCallback which
was supposed to change the version comes in after the rest of the code has
already failed.

So it seems to me that if we follow the spec, then the creationCallback
becomes nothing more than a flag that tells us whether or not the DB existed
(and a pretty poor implementation of such a flag too, since it's set only
after we're done executing the rest of the code). Is this really the
intended purpose of this callback? If not, assuming the purpose of this
callback was to initialize the database before running any transactions on
it, I propose the following changes to the spec:

1. If the database doesn't exist and a creationCallback is specified, *
invoke* the creation callback at the very end of openDatabase(). (This would
take care of the problem described in example 1.)
2. If the database doesn't exist, always set its version to the given one.
If a creation callback was specified, invoke it. If the creation callback
fails or raises an exception, reset the database version to "". (This would
take care of the problem in example 2. And in case creationCallback fails,
we will reset the DB version to "" before any other transaction gets a
chance to run.)

Received on Wednesday, 24 February 2010 00:23:44 UTC

This archive was generated by hypermail 2.3.1 : Wednesday, 11 February 2015 14:36:41 UTC