This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 18551 - [IndexedDB] Ambiguity about operations preceding a failed createIndex.
Summary: [IndexedDB] Ambiguity about operations preceding a failed createIndex.
Status: RESOLVED FIXED
Alias: None
Product: WebAppsWG
Classification: Unclassified
Component: Indexed Database API (show other bugs)
Version: unspecified
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: This bug has no owner yet - up for the taking
QA Contact: public-webapps-bugzilla
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-08-13 20:36 UTC by Alec Flett
Modified: 2013-04-15 19:24 UTC (History)
5 users (show)

See Also:


Attachments

Description Alec Flett 2012-08-13 20:36:25 UTC
jsbell and I have been discussing a possible ambiguity in the IndexedDB spec w.r.t. error handling around createIndex calls.


In particular, createIndex() is supposed to behave somewhat synchronously in that calling:


the implementation must create a newindex and return an IDBIndex object representing it.

so that this is reasonable:
objectStore.createIndex('foo',...)
objectStore.put(...)
objectStore.index('foo').get(...)

But at the same time createIndex() behaves somewhat asynchrnously - while the metadata for the index needs to be there immediately, the actual indexing data doesn't have to:

> In some implementations it's possible for the implementation to asynchronously run into problems creating the index after the createIndex function has returned. For example in implementations where metadata about the newly created index is queued up to be inserted into the database asynchronously, or where the implementation might need to ask the user for permission for quota reasons. Such implementations must still create and return an IDBIndex object. Instead, once the implementation realizes that creating the index has failed, it must abort the transaction using thesteps for aborting a transaction using the appropriate error as error parameter. 

The issue in question is how to handle this:

objectStore.put({"foo": 1, "message": "hello"});
req = objectStore.put({"foo": 1, "message": "goodbye"});
objectStore.createIndex("foo", "foo", {unique: true});    // will fail asynchronously

The question is, should req's onerror fire or not? 

From discussion on the list, I think most folks agree that both put()'s should succeed, but the spec needs to be clear on this.


A suggested clarification, but I'm sure it could be worded better.

In some implementations it's possible for the implementation to asynchronously run into problems creating the index [data] after the createIndex function has returned. For example in implementations where [indexing data about existing objects in the database] is queued up to be inserted into the database asynchronously, or where the implementation might need to ask the user for permission for quota reasons. Instead, once the implementation realizes that creating the objectStore has failed, it must abort the transaction using the steps for aborting a transaction using the appropriate error as error parameter. [If asynchronous write operations within the same transaction precede the createIndex, and they are the cause of the failure to create the index, they should not fail for this reason.] For example if creating the index failed due to quota reasons, QuotaError must be used as error and if the index can't be created due to unique constraints, ConstraintError must be used as error [and preceding requests which created these constraint violations should not fail.]
Comment 1 Joshua Bell 2012-08-13 22:00:46 UTC
How precise do we need to be in terms of when the constraint enforcement will begin? Just to throw out one more example:

request1 = store.put({name: 'carol'}, 1);
store.createIndex('index', 'name', {unique: true});
request2 = store.put({name: 'carol'}, 2);

If the timing of the index population/constraint enforcement is not defined, what happens here remains ambiguous:

index metadata updated
process request1 -> success
index population here?? -> no abort
process request2 -> constraint error??
or index population here?? -> abort

Depending on when the index is populated / constraint is enforced, the second request could succeed or fail.

It sounds like at least some implementations (WebKit, Gecko) treat the index population like a request internally, and therefore in the third example the second request would indeed be processed after the population and fail with a (preventable) constraint error. We probably need to be precise, e.g. reference the "steps for asynchronously executing a request" so that the "Wait until all previously added requests in transaction have their done flag set to true" clause is invoked.

...

The timing of deleteIndex() may also need to be clarified. E.g. what is the behavior of:

store.createIndex('index', 'name', {unique: true});
request1 = store.put({name: 'bob'}, 1);
request2 = store.put({name: 'bob'}, 2);
store.deleteIndex('index');

One possible interpretation:

index metadata added
index metadata removed
index population (skipped)
process request1 -> success
process request2 -> success
Comment 2 Jonas Sicking (Not reading bugmail) 2012-08-15 17:00:13 UTC
I think both createIndex and deleteIndex should be treated as "asynchronous requests".

From a web developers point of view it means that things happen in the order that their function calls run. So I think the ending example should result in:


store.createIndex('index', 'name', {unique: true});
request1 = store.put({name: 'bob'}, 1);
request2 = store.put({name: 'bob'}, 2);
store.deleteIndex('index');

My interpretation:

index metadata added
process request1 -> success
process request2 -> fail
index metadata removed


As you can see, it makes the actions line up exactly with the order of the function calls of the webpage.
Comment 3 Odin Hørthe Omdal 2012-08-17 15:08:25 UTC
I agree with Jonas, and what I seem to be picking up is the preferred way by Joshua and Alec too(?).

I forgot a bit about this thread, but I made some tests exhibiting what I think it should work like. They might contain errors, but Firefox actually passed them when I was pleased with them anyway. So Gecko and the tests have to share the bug if so.

http://w3c-test.org/webapps/IndexedDB/tests/submissions/Opera/idbobjectstore_createIndex6-event_order.htm
http://w3c-test.org/webapps/IndexedDB/tests/submissions/Opera/idbobjectstore_createIndex7-event_order.htm
http://w3c-test.org/webapps/IndexedDB/tests/submissions/Opera/idbobjectstore_createIndex8-deleteIndex-event_order.htm

There is need for even more of tests like that.

I also think this should apply to createObjectStore, deleteObjectStore as well as createIndex and deleteIndex for symmetry.
Comment 4 Joshua Bell 2013-04-15 19:24:19 UTC
I took as stab at this - as minimally as possible - in https://dvcs.w3.org/hg/IndexedDB/rev/eeb7e443b582

I added an example to the createIndex case; a corresponding example for the deleteIndex case seemed too contrived.