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);