Re: [IndexedDB] IDBCursor.update for cursors returned from IDBIndex.openCursor

On Thu, Sep 16, 2010 at 4:08 AM, Jeremy Orlow <jorlow@chromium.org> wrote:
> On Thu, Sep 16, 2010 at 10:15 AM, Jeremy Orlow <jorlow@chromium.org> wrote:
>>
>> On Wed, Sep 15, 2010 at 10:45 PM, Jonas Sicking <jonas@sicking.cc> wrote:
>>>
>>> Heh, I've also been thinking about this exact issue lately. There is a
>>> similar question for IDBCursor.delete.
>>>
>>> On Wed, Sep 15, 2010 at 8:55 AM, Jeremy Orlow <jorlow@chromium.org>
>>> wrote:
>>> > I think it's clear what IDBCursor does when created from
>>> > IDBObjectStore.openCursor or IDBIndex.openObjectCursor: it modifies the
>>> > objectStore's value and updates all indexes (or does nothing and
>>> > returns an
>>> > error if all of that can't be done while satisfying the constraints).
>>>
>>> Agreed.
>>>
>>> > But what about IDBCursor.update when created from IDBIndex.openCursor?
>>> >  I
>>> > see two options: we could modify the value within the objectStore's
>>> > value
>>> > that corresponds to the objectStore's key path or we could do like
>>> > above and
>>> > simply modify the objectStore's value.
>>>
>>> There's also a third option: Throw an exception. Maybe that's what
>>> you're referring to by "make this unsupported" below?
>>>
>>> > More concretely, if we have an object store with a "id" key path and an
>>> > index with a "fname" key path, and our index.openCursor() created
>>> > cursor is
>>> > currently on the {id: 22, fname: "Fred"} value (and thus cursor.key ==
>>> > "Fred" and cursor.value == 22), let's say I wanted to change the object
>>> > to
>>> > be {id: 23, fname: "Fred"}.  In other words, I want id to change from
>>> > 22 to
>>> > 23.  Which of the following should I write?
>>> > 1) calling cursor.update(23)   or
>>> > 2) calling cursor.update({id: 23, fname: "Fred"})
>>> > The former seems to match the behavior of the IDBObjectStore.openCursor
>>> > and
>>> > IDBIndex.openObjectCursor better (i.e. it modifies the cursor.value).
>>> >  The
>>> > latter intuitively seems like it'd be more useful.  But to be honest, I
>>> > can't think of any use cases for either.  Can anyone else?  If not,
>>> > maybe we
>>> > should just make this unsupported for now?
>>>
>>> The only use case I have thought of is wanting to update some set of
>>> entries, where the best way to find these entries is through an index.
>>> For example updating every entry with a specific shipping-id. You can
>>> use IDBIndex.openObjectCursor for this, but that's slower than
>>> IDBIndex.openCursor. So in the rare instance when you can make the
>>> modification without inspecting the existing value (i.e. you only need
>>> to write, read-modify-write), then IDBIndex.openCursor +
>>> IDBCursor.update() would be a perf optimization.
>>>
>>> On the other hand, it might be just as quick to call
>>> IDBObjectStore.put().
>>>
>>> Since the use case if pretty weak (when would you be able to update an
>>> entry without first reading the entry), and that you can seemingly get
>>> the same performance using IDBObjectStore.put(), I would be fine with
>>> making this unsupported.
>>>
>>> As for IDBCursor.delete(), I can see a somewhat stronger use case
>>> there. For example removing all entries with a specific shipping-id or
>>> some such. If you can determine which entries should be removed purely
>>> on the information in the index, then using IDBIndex.openCursor is
>>> definitely faster than IDBIndex.openObjectCursor. So on one hand it
>>> would be nice to allow people to use that. On the other hand, I
>>> suspect you can get the same performance using IDBObjectStore.delete()
>>> and we might want to be consistent with IDBCursor.update().
>>>
>>> In this case I'm actually leaning towards allowing IDBCursor.delete(),
>>> but I could go either way.
>>
>> Wait a sec.  What are the use cases for non-object cursors anyway?  They
>> made perfect sense back when we allowed explicit index management, but now
>> they kind of seem like a premature optimization or possibly even dead
>> weight.  Maybe we should just remove them altogether?
>
> Actually, for that matter, are remove and update needed at all?  I think
> they may just be more cruft left over from the explicit index days.  As far
> as I can tell, any .delete or .remove should be doable via an objectCursor +
> .puts/.removes on the objectStore.

They are not strictly needed, but they are a decent convinence
feature, and with a proper implementation they can even be a
performance optimization. With a cursor iterating a b-tree you can let
the cursor keep a pointer to the b-tree entry. They way .delete and
.update doesn't have to do a b-tree lookup at all.

We're currently not able to do this since our backend (sqlite) doesn't
have good enough cursor support, but I suspect that this will change
at some point in the future. In the mean time it seems like a good
thing to allow people to use API that will be faster in the future.

/ Jonas

Received on Thursday, 16 September 2010 19:58:20 UTC