Bug 65547 - IndexedDB: Fix index data invalidation bugs.
Summary: IndexedDB: Fix index data invalidation bugs.
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Hans Wennborg
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-08-02 09:48 PDT by Hans Wennborg
Modified: 2011-08-04 02:32 PDT (History)
2 users (show)

See Also:


Attachments
Patch (11.23 KB, patch)
2011-08-02 09:57 PDT, Hans Wennborg
no flags Details | Formatted Diff | Diff
Patch (12.91 KB, patch)
2011-08-02 10:11 PDT, Hans Wennborg
no flags Details | Formatted Diff | Diff
Patch (15.34 KB, patch)
2011-08-03 02:43 PDT, Hans Wennborg
tony: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Hans Wennborg 2011-08-02 09:48:21 PDT
IndexedDB: Fix index data invalidation bugs.
Comment 1 Hans Wennborg 2011-08-02 09:57:24 PDT
Created attachment 102662 [details]
Patch
Comment 2 Hans Wennborg 2011-08-02 10:01:27 PDT
Comment on attachment 102662 [details]
Patch

Oops, forgot to upload the expectations.
Comment 3 Hans Wennborg 2011-08-02 10:11:10 PDT
Created attachment 102665 [details]
Patch
Comment 4 Hans Wennborg 2011-08-02 10:12:32 PDT
David: would you like to do an informal review, and then I'll find someone who can properly review it?
Comment 5 David Grogan 2011-08-02 23:44:24 PDT
Comment on attachment 102665 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=102665&action=review

> LayoutTests/storage/indexeddb/index-unique.html:76
> +    shouldBe("event.target.errorCode", "webkitIDBDatabaseException.UNKNOWN_ERR");

We throw UNKNOWN_ERR?  Is that to spec or just what we currently throw?

> LayoutTests/storage/indexeddb/index-unique.html:111
> +    request = evalAndLog("transaction.objectStore('store').put({x: 1}, 'bar')");

This is the first operation whose behavior is altered by this patch, correct?

> LayoutTests/storage/indexeddb/index-unique.html:130
> +    request = evalAndLog("transaction.objectStore('store').put({x: 1}, 'baz')");

Should this should test with 'bar' instead of 'baz'?  It was the primary key whose ExistsEntryKey was erroneously left around, wasn't it?

> Source/WebCore/storage/IDBLevelDBBackingStore.cpp:-804
> -PassRefPtr<IDBKey> IDBLevelDBBackingStore::getPrimaryKeyViaIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key)

It seems that nothing was wrong with this function, it was just refactored so that keyExistsInIndex could use most of its functionality.  Accurate?

> Source/WebCore/storage/IDBLevelDBBackingStore.cpp:824
>          if (!p)

Is this expected to be triggered, or does it indicate corruption?

> Source/WebCore/storage/IDBLevelDBBackingStore.cpp:830
> +            transaction->remove(it->key());

We end up with stale index data when a (primary key, value) pair is overwritten?
Comment 6 Hans Wennborg 2011-08-03 02:39:55 PDT
(In reply to comment #5)
> (From update of attachment 102665 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=102665&action=review
> 
> > LayoutTests/storage/indexeddb/index-unique.html:76
> > +    shouldBe("event.target.errorCode", "webkitIDBDatabaseException.UNKNOWN_ERR");
> 
> We throw UNKNOWN_ERR?  Is that to spec or just what we currently throw?
It's what we currently throw. I now see that the specc says it should be CONSTRAINT_ERR, so let's fix that while we're at it.

> > LayoutTests/storage/indexeddb/index-unique.html:111
> > +    request = evalAndLog("transaction.objectStore('store').put({x: 1}, 'bar')");
> 
> This is the first operation whose behavior is altered by this patch, correct?
Exactly.

> 
> > LayoutTests/storage/indexeddb/index-unique.html:130
> > +    request = evalAndLog("transaction.objectStore('store').put({x: 1}, 'baz')");
> 
> Should this should test with 'bar' instead of 'baz'?  It was the primary key whose ExistsEntryKey was erroneously left around, wasn't it?
The ExistsEntryKey was erroneously left around, which meant that the x=1 key in the index, which pointed to that primary key, was considered "active".

The point is that we can add a value with x = 1 again.. the primary key of the new entry is not important.

> 
> > Source/WebCore/storage/IDBLevelDBBackingStore.cpp:-804
> > -PassRefPtr<IDBKey> IDBLevelDBBackingStore::getPrimaryKeyViaIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key)
> 
> It seems that nothing was wrong with this function, it was just refactored so that keyExistsInIndex could use most of its functionality.  Accurate?
Yes, I just factored out all the stuff except the decoding of the primary key into a new function. The diff makes it harder to read than it really is.


> 
> > Source/WebCore/storage/IDBLevelDBBackingStore.cpp:824
> >          if (!p)
> 
> Is this expected to be triggered, or does it indicate corruption?
Right, this is not expected to be triggered.

> 
> > Source/WebCore/storage/IDBLevelDBBackingStore.cpp:830
> > +            transaction->remove(it->key());
> 
> We end up with stale index data when a (primary key, value) pair is overwritten?

Yes, either (primary key, value) is overwritten (and thus gets a new version number), or the (primary key, value) is removed.
Comment 7 Hans Wennborg 2011-08-03 02:43:21 PDT
Created attachment 102758 [details]
Patch

Use CONSTRAINT_ERR for uniqueness constraint violation.
Comment 8 Hans Wennborg 2011-08-03 03:06:11 PDT
Tony, would you like to take a look?
Comment 9 David Grogan 2011-08-03 09:23:37 PDT
LGTM


(In reply to comment #6)
> (In reply to comment #5)
> > (From update of attachment 102665 [details] [details])
> > View in context: https://bugs.webkit.org/attachment.cgi?id=102665&action=review
> > > LayoutTests/storage/indexeddb/index-unique.html:130
> > > +    request = evalAndLog("transaction.objectStore('store').put({x: 1}, 'baz')");
> > 
> > Should this should test with 'bar' instead of 'baz'?  It was the primary key whose ExistsEntryKey was erroneously left around, wasn't it?
> The ExistsEntryKey was erroneously left around, which meant that the x=1 key in the index, which pointed to that primary key, was considered "active".
> 
> The point is that we can add a value with x = 1 again.. the primary key of the new entry is not important.

Ah, ok.  I can see that.
Comment 10 Tony Chang 2011-08-03 11:11:10 PDT
Comment on attachment 102758 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=102758&action=review

> Source/WebCore/storage/IDBLevelDBBackingStore.cpp:808
> +static bool findKeyInIndex(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key, Vector<char>* foundEncodedPrimaryKey)

Nit: In WebKit, it's more common to use pass by reference for out variables.  I would change |foundEncodedPrimaryKey| to be consistent with the rest of the file.
Comment 11 Hans Wennborg 2011-08-04 02:27:58 PDT
(In reply to comment #10)
> (From update of attachment 102758 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=102758&action=review

Thanks Tony!

> 
> > Source/WebCore/storage/IDBLevelDBBackingStore.cpp:808
> > +static bool findKeyInIndex(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key, Vector<char>* foundEncodedPrimaryKey)
> 
> Nit: In WebKit, it's more common to use pass by reference for out variables.  I would change |foundEncodedPrimaryKey| to be consistent with the rest of the file.
Fixed.
Comment 12 Hans Wennborg 2011-08-04 02:32:44 PDT
Committed r92364: <http://trac.webkit.org/changeset/92364>