- From: Israel Hilerio <israelh@microsoft.com>
- Date: Wed, 25 Jan 2012 21:55:04 +0000
- To: Jonas Sicking <jonas@sicking.cc>
- CC: ben turner <bent.mozilla@gmail.com>, Joshua Bell <jsbell@chromium.org>, Odin Hørthe Omdal <odinho@opera.com>, Adam Herchenroether <aherchen@microsoft.com>, Victor Ngo <vicngo@microsoft.com>, "public-webapps@w3.org" <public-webapps@w3.org>
On Wednesday, January 25, 2012 1:47 AM, Jonas Sicking wrote:
> On Tue, Jan 24, 2012 at 12:07 PM, Israel Hilerio
> <israelh@microsoft.com>
> wrote:
> > On Tuesday, January 24, 2012 2:46 AM Jonas Sicking wrote:
> >> 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
> >> >> > -s tep s-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
> >
> > After going over your explanation, uses cases, and examples, I agree
> > with you that supporting an empty string keypath on indexes makes
> > sense and is less confusing than any alternatives :-)
> >
> > So the only thing left to do is to remove the support for empty
> > string keyPaths from the createObjectStore method and introduce some
> > type of flag to specify set behavior/ support. As I understand it,
> > the set pattern will
> constrains the put/add methods to only valid keys.
> > Those keys will be used as both values and keys. When specifying
> > this flag, no other keyValue can be specified as part of the put/add
> > method. Is
> this correct?
> >
> > What about changing the flag name to be {useValuesAsKeys: true}?
> > This seems to capture the essence of the behavior we want to prescribe.
>
> I would prefer to keep empty-string keyPaths supported on
> objectStores. I agree that it introduces some risk of confusion as
> discussed earlier. But it adds a nice feature (sets) while keeping
> keyPath syntax consistent between indexes and objectStores.
>
> But I can live with something like a useValuesAsKeys property if that
> is the solution that everyone else prefer. However what would
> IDBObjectStore.keyPath return for such an objectStore? I.e. are we
> really getting rid of the problem since objectStore.keyPath would
> presumably return something false-y, but the objectStore behaves as if
> it has a keyPath since you can't pass an explicit key to it.
>
> / Jonas
In many ways, I see the useValuesAsKeys as a shorthand notation for adding a record to the database whose value and key are the same.
Therefore, I believe the useValuesAsKeys scenario is similar to creating an objectStore without a keyPath and adding values with an out-of-line key. In IE, the value for IDBObjectStore.keyPath is null. Therefore, if a developer were to create an objectStore with the useValuesAsKeys property, I would expect the IDBObjectStore.keyPath value to also be null or undefined. I believe this would be easy to understand by developers.
Also, I imagine that if a developer were to use all the optionalParameter flags when creating an object store (ex. {keyPath: "foo", autoIncrement: true, useValuesAsKeys: true} and other matrixes) the system will throw an InvalidAccessError exception type.
Israel
Received on Wednesday, 25 January 2012 21:55:42 UTC