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

Re: [indexeddb] Do we need to support keyPaths with an empty string?

From: Jonas Sicking <jonas@sicking.cc>
Date: Tue, 24 Jan 2012 02:46:03 -0800
Message-ID: <CA+c2ei_JYanjeG8FufXCDF9QML-oks8HM1DWfjaPLdbhZqXPRA@mail.gmail.com>
To: Israel Hilerio <israelh@microsoft.com>
Cc: ben turner <bent.mozilla@gmail.com>, Joshua Bell <jsbell@chromium.org>, Odin HÝrthe Omdal <odinho@opera.com>, Adam Herchenroether <aherchen@microsoft.com>, David Sheldon <dsheldon@microsoft.com>, "public-webapps@w3.org" <public-webapps@w3.org>
On Fri, Jan 20, 2012 at 3:38 PM, Israel Hilerio <israelh@microsoft.com> wrote:
> On Friday, January 20, 2012 2:31 PM, Jonas Sicking wrote:
>> On Fri, Jan 20, 2012 at 12:23 PM, ben turner <bent.mozilla@gmail.com> wrote:
>> > Mozilla is fine with removing the special |keyPath:""| behavior.
>> > Please note that this will also mean that step 1 of the algorithm here
>> >
>> >
>> > http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#dfn-steps-f
>> > or-extracting-a-key-from-a-value-using-a-key-path
>> >
>> > will need to change.
>> >
>> > We do want to continue to allow set behavior without specifying the
>> > key twice, though, so we would propose adding an additional option to
>> > createObjectStore to accomplish this:
>> >
>> > †// Old way:
>> > †var set = db.createObjectStore("mySet", { keyPath:"" });
>> > †set.put(keyValue);
>> >
>> > †// New way:
>> > †var set = db.createObjectStore("mySet", { isSet: true });
>> > †set.put(keyValue);
>> >
>> > (We are not in love with "isSet", better names are highly encouraged!)
>> >
>> > What do you all think? This would allow us to continue to support nice
>> > set behavior without making the empty string "magic".
>> I actually think that the current behavior that we have is pretty consistent. Any
>> time you give the keyPath property a string we create an objectStore with a
>> keyPath. And any time you have an objectStore with a keyPath you are not
>> allowed to pass an explicit key since the key is gotten from the keyPath. There's
>> no special handling of empty strings happening.
>> But I do agree that it can be somewhat confusing to tell ""/null/undefined apart
>> since they are all falsy. In particular, an expression like
>> if (myObjectStore.keyPath) {
>>†† ...
>> }
>> doesn't work to test if an objectStore has a keyPath or not. You instead need to
>> check
>> if (myObjectStore.keyPath != null) {
>>†† ...
>> }
>> or
>> if (typeof myObjectStore.keyPath == "string") {
>>†† ...
>> }
>> Hence the "isSet" suggestion.
>> Though I also realized after talking to Ben that empty keyPaths show up in
>> indexes too. Consider creating a objectStore which maps peoples names to
>> email addresses. Then you can create an index when does the opposite
>> mapping, or which ensures that email addresses are unique:
>> var store = db.createObjectStore("people"); var index =
>> store.createIndex("reverse", "", { unique: true });
>> store.add("john.doe@email.com", "John Doe"); store.add("mike@smith.org",
>> "Mike Smith");
>> store.get("John Doe").onsuccess = function(e) {
>>†† alert("John's email is " + e.target.result); }
>> index.getKey("mike@smith.org").onsuccess = function(e) {
>>†† alert("mike@smith.org is owned by " + e.target.result); }
>> Are people proposing we remove empty keyPaths here too?
>> / Jonas
> Yes, I'm proposing removing empty string KeyPaths all together to avoid confusion.
> I would like to know how often you expect developers to follow this pattern
> instead of using objects. †Our believe is that objects will be the main value stored in object stores
> instead of single values.
> Supporting keyPath with empty strings brings up all kinds of side effects. For example:
> var store = db.createObjectStore("people");
> var index = store.createIndex("reverse", "", { unique: true });
> store.add({email: "john.doe@email.com"}, "John Doe");
> store.add({email: "mike@smith.org"},"Mike Smith");
> What should happen in this case, do we throw an exception?

This doesn't seem any different from

var store = db.createObjectStore("people");
var index = store.createIndex("reverse", "x", { unique: true });
store.add({ x: {email: "john.doe@email.com"} }, "John Doe");
store.add({ x: {email: "mike@smith.org"} },"Mike Smith");

IIRC we decided a while ago that indexes do not add constraints. I.e.
that if the keyPath for an index doesn't yield a valid key, then the
index simply doesn't get an entry pointing to newly stored value.

So I don't really see that empty keyPaths bring up any special cases.
The only special case we have in Firefox for empty keyPaths (apart
from the keyPath evaluation code itself) is the code that throws an
exception if you try to create an objectStore with an empty keyPath
and a key generator.

> Having some type of flag seems more promising for object stores.† However, we still need to figure out how to deal with
> Indexes on sets, do we pass another flag to support the indexes on sets? †If we do that, then what do we do with the keyPath parameter to an index.
> It seems we're overloading the functionality of these methods to support different patterns.

Indeed, supporting the same use cases but using something other than
empty key paths gets pretty messy for indexes. If we want to keep
supporting these use cases (which I personally do), then I think using
empty key paths is the cleanest solution.

Really the only downside that I see is the somewhat non-intuitive
"objectStore.keyPath != null" check. But I'm not convinced that this
is something that people will run in to a lot given that the main
use-case that I can think of is generic code which visualize a
indexedDB database for developers.

/ Jonas
Received on Tuesday, 24 January 2012 10:47:27 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 18:49:50 GMT