Title: [92950] trunk
Revision
92950
Author
[email protected]
Date
2011-08-12 01:51:14 -0700 (Fri, 12 Aug 2011)

Log Message

IndexedDB: Overwriting key in unique index should be possible
https://bugs.webkit.org/show_bug.cgi?id=65993

Reviewed by Tony Chang.

Source/WebCore:

It should be possible to overwrite an object store record even if
there is a derived key for that record in an index with the unique flag set.

* storage/IDBBackingStore.h:
* storage/IDBIndexBackendImpl.cpp:
(WebCore::IDBIndexBackendImpl::addingKeyAllowed):
* storage/IDBIndexBackendImpl.h:
* storage/IDBLevelDBBackingStore.cpp:
(WebCore::IDBLevelDBBackingStore::keyExistsInIndex):
* storage/IDBLevelDBBackingStore.h:
* storage/IDBObjectStoreBackendImpl.cpp:
(WebCore::IDBObjectStoreBackendImpl::putInternal):
* storage/IDBSQLiteBackingStore.cpp:
(WebCore::IDBSQLiteBackingStore::keyExistsInIndex):
* storage/IDBSQLiteBackingStore.h:

LayoutTests:

Test that it's possible to overwrite an object store record even if there
is a derived key for that record in an index with the unique flag set.

* storage/indexeddb/index-unique-expected.txt:
* storage/indexeddb/index-unique.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (92949 => 92950)


--- trunk/LayoutTests/ChangeLog	2011-08-12 07:52:24 UTC (rev 92949)
+++ trunk/LayoutTests/ChangeLog	2011-08-12 08:51:14 UTC (rev 92950)
@@ -1,3 +1,16 @@
+2011-08-10  Hans Wennborg  <[email protected]>
+
+        IndexedDB: Overwriting key in unique index should be possible
+        https://bugs.webkit.org/show_bug.cgi?id=65993
+
+        Reviewed by Tony Chang.
+
+        Test that it's possible to overwrite an object store record even if there
+        is a derived key for that record in an index with the unique flag set.
+
+        * storage/indexeddb/index-unique-expected.txt:
+        * storage/indexeddb/index-unique.html:
+
 2011-08-11  Yuta Kitamura  <[email protected]>
 
         WebSocket: Implement "protocol" attribute

Modified: trunk/LayoutTests/storage/indexeddb/index-unique-expected.txt (92949 => 92950)


--- trunk/LayoutTests/storage/indexeddb/index-unique-expected.txt	2011-08-12 07:52:24 UTC (rev 92949)
+++ trunk/LayoutTests/storage/indexeddb/index-unique-expected.txt	2011-08-12 08:51:14 UTC (rev 92950)
@@ -34,6 +34,7 @@
 deleteSuccess():
 transaction.objectStore('store').put({x: 1}, 'baz')
 finalAddSuccess():
+transaction.objectStore('store').put({x: 1}, 'baz')
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/storage/indexeddb/index-unique.html (92949 => 92950)


--- trunk/LayoutTests/storage/indexeddb/index-unique.html	2011-08-12 07:52:24 UTC (rev 92949)
+++ trunk/LayoutTests/storage/indexeddb/index-unique.html	2011-08-12 08:51:14 UTC (rev 92950)
@@ -134,7 +134,11 @@
 
 function finalAddSuccess() {
     debug("finalAddSuccess():");
-    done();
+
+    // An overwrite should be ok.
+    request = evalAndLog("transaction.objectStore('store').put({x: 1}, 'baz')");
+    request._onerror_ = unexpectedErrorCallback;
+    request._onsuccess_ = done;
 }
 
 test();

Modified: trunk/Source/WebCore/ChangeLog (92949 => 92950)


--- trunk/Source/WebCore/ChangeLog	2011-08-12 07:52:24 UTC (rev 92949)
+++ trunk/Source/WebCore/ChangeLog	2011-08-12 08:51:14 UTC (rev 92950)
@@ -1,3 +1,26 @@
+2011-08-10  Hans Wennborg  <[email protected]>
+
+        IndexedDB: Overwriting key in unique index should be possible
+        https://bugs.webkit.org/show_bug.cgi?id=65993
+
+        Reviewed by Tony Chang.
+
+        It should be possible to overwrite an object store record even if
+        there is a derived key for that record in an index with the unique flag set.
+
+        * storage/IDBBackingStore.h:
+        * storage/IDBIndexBackendImpl.cpp:
+        (WebCore::IDBIndexBackendImpl::addingKeyAllowed):
+        * storage/IDBIndexBackendImpl.h:
+        * storage/IDBLevelDBBackingStore.cpp:
+        (WebCore::IDBLevelDBBackingStore::keyExistsInIndex):
+        * storage/IDBLevelDBBackingStore.h:
+        * storage/IDBObjectStoreBackendImpl.cpp:
+        (WebCore::IDBObjectStoreBackendImpl::putInternal):
+        * storage/IDBSQLiteBackingStore.cpp:
+        (WebCore::IDBSQLiteBackingStore::keyExistsInIndex):
+        * storage/IDBSQLiteBackingStore.h:
+
 2011-08-11  Yuta Kitamura  <[email protected]>
 
         WebSocket: Implement "protocol" attribute

Modified: trunk/Source/WebCore/storage/IDBBackingStore.h (92949 => 92950)


--- trunk/Source/WebCore/storage/IDBBackingStore.h	2011-08-12 07:52:24 UTC (rev 92949)
+++ trunk/Source/WebCore/storage/IDBBackingStore.h	2011-08-12 08:51:14 UTC (rev 92950)
@@ -81,7 +81,7 @@
     virtual bool deleteIndexDataForRecord(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const ObjectStoreRecordIdentifier*) = 0;
     virtual String getObjectViaIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&) = 0;
     virtual PassRefPtr<IDBKey> getPrimaryKeyViaIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&) = 0;
-    virtual bool keyExistsInIndex(int64_t databaseid, int64_t objectStoreId, int64_t indexId, const IDBKey&) = 0;
+    virtual bool keyExistsInIndex(int64_t databaseid, int64_t objectStoreId, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey) = 0;
 
     class Cursor : public RefCounted<Cursor> {
     public:

Modified: trunk/Source/WebCore/storage/IDBIndexBackendImpl.cpp (92949 => 92950)


--- trunk/Source/WebCore/storage/IDBIndexBackendImpl.cpp	2011-08-12 07:52:24 UTC (rev 92949)
+++ trunk/Source/WebCore/storage/IDBIndexBackendImpl.cpp	2011-08-12 08:51:14 UTC (rev 92950)
@@ -158,12 +158,18 @@
         ec = IDBDatabaseException::NOT_ALLOWED_ERR;
 }
 
-bool IDBIndexBackendImpl::addingKeyAllowed(IDBKey* key)
+bool IDBIndexBackendImpl::addingKeyAllowed(const IDBKey* indexKey, const IDBKey* primaryKey)
 {
     if (!m_unique)
         return true;
 
-    return !m_backingStore->keyExistsInIndex(m_databaseId, m_objectStoreBackend->id(), m_id, *key);
+    RefPtr<IDBKey> foundPrimaryKey;
+    bool found = m_backingStore->keyExistsInIndex(m_databaseId, m_objectStoreBackend->id(), m_id, *indexKey, foundPrimaryKey);
+    if (!found)
+        return true;
+    if (foundPrimaryKey->isEqual(primaryKey))
+        return true;
+    return false;
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/storage/IDBIndexBackendImpl.h (92949 => 92950)


--- trunk/Source/WebCore/storage/IDBIndexBackendImpl.h	2011-08-12 07:52:24 UTC (rev 92949)
+++ trunk/Source/WebCore/storage/IDBIndexBackendImpl.h	2011-08-12 08:51:14 UTC (rev 92950)
@@ -58,7 +58,7 @@
     void setId(int64_t id) { m_id = id; }
     bool hasValidId() const { return m_id != InvalidId; };
 
-    bool addingKeyAllowed(IDBKey*);
+    bool addingKeyAllowed(const IDBKey* indexKey, const IDBKey* primaryKey);
 
     // Implements IDBIndexBackendInterface.
     virtual String name() { return m_name; }

Modified: trunk/Source/WebCore/storage/IDBLevelDBBackingStore.cpp (92949 => 92950)


--- trunk/Source/WebCore/storage/IDBLevelDBBackingStore.cpp	2011-08-12 07:52:24 UTC (rev 92949)
+++ trunk/Source/WebCore/storage/IDBLevelDBBackingStore.cpp	2011-08-12 08:51:14 UTC (rev 92950)
@@ -791,15 +791,16 @@
     return 0;
 }
 
-bool IDBLevelDBBackingStore::keyExistsInIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& key)
+bool IDBLevelDBBackingStore::keyExistsInIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey)
 {
     ASSERT(m_currentTransaction);
 
     Vector<char> foundEncodedPrimaryKey;
-    if (findKeyInIndex(m_currentTransaction.get(), databaseId, objectStoreId, indexId, key, foundEncodedPrimaryKey))
-        return true;
+    if (!findKeyInIndex(m_currentTransaction.get(), databaseId, objectStoreId, indexId, indexKey, foundEncodedPrimaryKey))
+        return false;
 
-    return false;
+    decodeIDBKey(foundEncodedPrimaryKey.begin(), foundEncodedPrimaryKey.end(), foundPrimaryKey);
+    return true;
 }
 
 namespace {

Modified: trunk/Source/WebCore/storage/IDBLevelDBBackingStore.h (92949 => 92950)


--- trunk/Source/WebCore/storage/IDBLevelDBBackingStore.h	2011-08-12 07:52:24 UTC (rev 92949)
+++ trunk/Source/WebCore/storage/IDBLevelDBBackingStore.h	2011-08-12 08:51:14 UTC (rev 92950)
@@ -67,7 +67,7 @@
     virtual bool deleteIndexDataForRecord(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const ObjectStoreRecordIdentifier*);
     virtual String getObjectViaIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&);
     virtual PassRefPtr<IDBKey> getPrimaryKeyViaIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&);
-    virtual bool keyExistsInIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&);
+    virtual bool keyExistsInIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey);
 
     virtual PassRefPtr<Cursor> openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction);
     virtual PassRefPtr<Cursor> openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange*, IDBCursor::Direction);

Modified: trunk/Source/WebCore/storage/IDBObjectStoreBackendImpl.cpp (92949 => 92950)


--- trunk/Source/WebCore/storage/IDBObjectStoreBackendImpl.cpp	2011-08-12 07:52:24 UTC (rev 92949)
+++ trunk/Source/WebCore/storage/IDBObjectStoreBackendImpl.cpp	2011-08-12 08:51:14 UTC (rev 92950)
@@ -226,20 +226,22 @@
 
     Vector<RefPtr<IDBKey> > indexKeys;
     for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it) {
-        RefPtr<IDBKey> key = fetchKeyFromKeyPath(value.get(), it->second->keyPath());
-        if (!key) {
+        const RefPtr<IDBIndexBackendImpl>& index = it->second;
+
+        RefPtr<IDBKey> indexKey = fetchKeyFromKeyPath(value.get(), index->keyPath());
+        if (!indexKey) {
             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "The key could not be fetched from an index's keyPath."));
             return;
         }
-        if (key->type() == IDBKey::NullType) {
+        if (indexKey->type() == IDBKey::NullType) {
             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "One of the derived (from a keyPath) keys for an index is NULL."));
             return;
         }
-        if (!it->second->addingKeyAllowed(key.get())) {
+        if (!index->addingKeyAllowed(indexKey.get(), key.get())) { // So problem is that if key() is the same as the old key for this record in this index, then we're not really *adding it*, just updating it...
             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "One of the derived (from a keyPath) keys for an index does not satisfy its uniqueness requirements."));
             return;
         }
-        indexKeys.append(key.release());
+        indexKeys.append(indexKey.release());
     }
 
     RefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> recordIdentifier = objectStore->m_backingStore->createInvalidRecordIdentifier();

Modified: trunk/Source/WebCore/storage/IDBSQLiteBackingStore.cpp (92949 => 92950)


--- trunk/Source/WebCore/storage/IDBSQLiteBackingStore.cpp	2011-08-12 07:52:24 UTC (rev 92949)
+++ trunk/Source/WebCore/storage/IDBSQLiteBackingStore.cpp	2011-08-12 08:51:14 UTC (rev 92950)
@@ -675,17 +675,22 @@
     return foundKey.release();
 }
 
-bool IDBSQLiteBackingStore::keyExistsInIndex(int64_t, int64_t, int64_t indexId, const IDBKey& key)
+bool IDBSQLiteBackingStore::keyExistsInIndex(int64_t, int64_t, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey)
 {
-    String sql = String("SELECT id FROM IndexData WHERE indexId = ? AND ") + whereSyntaxForKey(key);
+    String sql = String("SELECT id FROM IndexData WHERE indexId = ? AND ") + whereSyntaxForKey(indexKey);
     SQLiteStatement query(m_db, sql);
     bool ok = query.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
 
     query.bindInt64(1, indexId);
-    bindKeyToQuery(query, 2, key);
+    bindKeyToQuery(query, 2, indexKey);
 
-    return query.step() == SQLResultRow;
+    if (query.step() != SQLResultRow)
+        return false;
+
+    foundPrimaryKey = getPrimaryKeyViaIndex(0, 0, indexId, indexKey);
+    ASSERT(foundPrimaryKey);
+    return true;
 }
 
 namespace {

Modified: trunk/Source/WebCore/storage/IDBSQLiteBackingStore.h (92949 => 92950)


--- trunk/Source/WebCore/storage/IDBSQLiteBackingStore.h	2011-08-12 07:52:24 UTC (rev 92949)
+++ trunk/Source/WebCore/storage/IDBSQLiteBackingStore.h	2011-08-12 08:51:14 UTC (rev 92950)
@@ -62,7 +62,7 @@
     virtual bool deleteIndexDataForRecord(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const ObjectStoreRecordIdentifier*);
     virtual String getObjectViaIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&);
     virtual PassRefPtr<IDBKey> getPrimaryKeyViaIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&);
-    virtual bool keyExistsInIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey&);
+    virtual bool keyExistsInIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey);
 
     virtual PassRefPtr<Cursor> openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction);
     virtual PassRefPtr<Cursor> openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange*, IDBCursor::Direction);
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to