[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

jorlow at chromium.org jorlow at chromium.org
Wed Dec 22 13:02:53 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 645363bf60bf1c4a88ac04befb5430b5e2511e49
Author: jorlow at chromium.org <jorlow at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Mon Sep 6 10:33:31 2010 +0000

    2010-08-26  Jeremy Orlow  <jorlow at chromium.org>
    
            Reviewed by Steve Block.
    
            Add index insertion support to IndexedDB.
            https://bugs.webkit.org/show_bug.cgi?id=44695
    
            * storage/indexeddb/objectstore-basics-expected.txt:
            * storage/indexeddb/script-tests/objectstore-basics.js:
            (createSuccess):
            (addIndexSuccess):
            (getSuccess):
    2010-08-26  Jeremy Orlow  <jorlow at chromium.org>
    
            Reviewed by Steve Block.
    
            Add index insertion support to IndexedDB.
            https://bugs.webkit.org/show_bug.cgi?id=44695
    
            Whenever you insert an item into an ObjectStore, it should use all
            indexes' key paths to insert corresponding entries into each index.
            Also data should be deleted out of the index when it goes away.
    
            Not much testing yet since there's no way to directly observe indexes.
            More will be in next patch.
    
            * storage/IDBDatabaseBackendImpl.cpp:
            (WebCore::IDBDatabaseBackendImpl::removeObjectStore):
            * storage/IDBFactoryBackendImpl.cpp:
            (WebCore::createTables):
            * storage/IDBIndex.idl:
            * storage/IDBIndexBackendImpl.cpp:
            (WebCore::whereClause):
            (WebCore::bindWhereClause):
            (WebCore::IDBIndexBackendImpl::addingKeyAllowed):
            * storage/IDBIndexBackendImpl.h:
            (WebCore::IDBIndexBackendImpl::id):
            * storage/IDBKey.cpp:
            (WebCore::IDBKey::whereSyntax):
            (WebCore::IDBKey::bind):
            (WebCore::IDBKey::bindWithNulls):
            * storage/IDBKey.h:
            * storage/IDBObjectStore.idl:
            * storage/IDBObjectStoreBackendImpl.cpp:
            (WebCore::whereClause):
            (WebCore::bindWhereClause):
            (WebCore::IDBObjectStoreBackendImpl::get):
            (WebCore::fetchKeyFromKeyPath):
            (WebCore::putObjectStoreData):
            (WebCore::putIndexData):
            (WebCore::IDBObjectStoreBackendImpl::put):
            (WebCore::IDBObjectStoreBackendImpl::remove):
            (WebCore::IDBObjectStoreBackendImpl::createIndex):
            (WebCore::doDelete):
            (WebCore::IDBObjectStoreBackendImpl::removeIndex):
            (WebCore::IDBObjectStoreBackendImpl::openCursor):
            * storage/IDBObjectStoreBackendImpl.h:
    2010-08-26  Jeremy Orlow  <jorlow at chromium.org>
    
            Reviewed by Steve Block.
    
            Add index insertion support to IndexedDB.
            https://bugs.webkit.org/show_bug.cgi?id=44695
    
            Add asserts on the [] operator.
    
            * public/WebVector.h:
            (WebKit::WebVector::operator[]):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@66820 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index dd0b71b..2884307 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,16 @@
+2010-08-26  Jeremy Orlow  <jorlow at chromium.org>
+
+        Reviewed by Steve Block.
+
+        Add index insertion support to IndexedDB.
+        https://bugs.webkit.org/show_bug.cgi?id=44695
+
+        * storage/indexeddb/objectstore-basics-expected.txt:
+        * storage/indexeddb/script-tests/objectstore-basics.js:
+        (createSuccess):
+        (addIndexSuccess):
+        (getSuccess):
+
 2010-09-06  Philippe Normand  <pnormand at igalia.com>
 
         Unreviewed, skipping a crashing media test.
diff --git a/LayoutTests/storage/indexeddb/objectstore-basics-expected.txt b/LayoutTests/storage/indexeddb/objectstore-basics-expected.txt
index 105058d..a60e857 100644
--- a/LayoutTests/storage/indexeddb/objectstore-basics-expected.txt
+++ b/LayoutTests/storage/indexeddb/objectstore-basics-expected.txt
@@ -50,7 +50,28 @@ PASS store.name is "storeName"
 PASS store.keyPath is null
 PASS storeNames.contains('storeName') is true
 PASS storeNames.length is 1
-store.add('value', 'key')
+event.result.createIndex('indexName', 'x')
+PASS 'onsuccess' in result is true
+PASS 'onerror' in result is true
+PASS 'abort' in result is true
+PASS 'readyState' in result is true
+An event should fire shortly...
+
+addIndexSuccess():
+Success event fired:
+PASS 'result' in event is true
+PASS 'code' in event is false
+PASS 'message' in event is false
+PASS 'source' in event is true
+PASS event.source != null is true
+PASS 'onsuccess' in event.target is true
+PASS 'onerror' in event.target is true
+PASS 'abort' in event.target is true
+PASS 'readyState' in event.target is true
+PASS event.target.readyState is event.target.DONE
+
+PASS event.source.indexNames.contains('indexName') is true
+event.source.add({x: 'value'}, 'key')
 PASS 'onsuccess' in result is true
 PASS 'onerror' in result is true
 PASS 'abort' in result is true
@@ -92,7 +113,7 @@ PASS 'abort' in event.target is true
 PASS 'readyState' in event.target is true
 PASS event.target.readyState is event.target.DONE
 
-PASS event.result is "value"
+PASS event.result.x is "value"
 store = event.source
 store.remove('key')
 PASS 'onsuccess' in result is true
@@ -118,3 +139,4 @@ PASS event.result is null
 PASS successfullyParsed is true
 
 TEST COMPLETE
+
diff --git a/LayoutTests/storage/indexeddb/script-tests/objectstore-basics.js b/LayoutTests/storage/indexeddb/script-tests/objectstore-basics.js
index 63675ad..35ccb4a 100644
--- a/LayoutTests/storage/indexeddb/script-tests/objectstore-basics.js
+++ b/LayoutTests/storage/indexeddb/script-tests/objectstore-basics.js
@@ -35,9 +35,21 @@ function createSuccess()
     shouldBeNull("store.keyPath");
     shouldBe("storeNames.contains('storeName')", "true");
     shouldBe("storeNames.length", "1");
-    // FIXME: test store.indexNames, as well as all object store's methods.
+    // FIXME: test all of object store's methods.
 
-    result = evalAndLog("store.add('value', 'key')");
+    result = evalAndLog("event.result.createIndex('indexName', 'x')");
+    verifyResult(result);
+    result.onsuccess = addIndexSuccess;
+    result.onerror = unexpectedErrorCallback;
+}
+
+function addIndexSuccess()
+{
+    debug("addIndexSuccess():");
+    verifySuccessEvent(event);
+    shouldBeTrue("event.source.indexNames.contains('indexName')");
+
+    result = evalAndLog("event.source.add({x: 'value'}, 'key')");
     verifyResult(result);
     result.onsuccess = addSuccess;
     result.onerror = unexpectedErrorCallback;
@@ -60,7 +72,7 @@ function getSuccess()
 {
     debug("getSuccess():");
     verifySuccessEvent(event);
-    shouldBeEqualToString("event.result", "value");
+    shouldBeEqualToString("event.result.x", "value");
     var store = evalAndLog("store = event.source");
 
     result = evalAndLog("store.remove('key')");
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 11abfff..2a6f024 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,49 @@
+2010-08-26  Jeremy Orlow  <jorlow at chromium.org>
+
+        Reviewed by Steve Block.
+
+        Add index insertion support to IndexedDB.
+        https://bugs.webkit.org/show_bug.cgi?id=44695
+
+        Whenever you insert an item into an ObjectStore, it should use all
+        indexes' key paths to insert corresponding entries into each index.
+        Also data should be deleted out of the index when it goes away.
+
+        Not much testing yet since there's no way to directly observe indexes.
+        More will be in next patch.
+
+        * storage/IDBDatabaseBackendImpl.cpp:
+        (WebCore::IDBDatabaseBackendImpl::removeObjectStore):
+        * storage/IDBFactoryBackendImpl.cpp:
+        (WebCore::createTables):
+        * storage/IDBIndex.idl:
+        * storage/IDBIndexBackendImpl.cpp:
+        (WebCore::whereClause):
+        (WebCore::bindWhereClause):
+        (WebCore::IDBIndexBackendImpl::addingKeyAllowed):
+        * storage/IDBIndexBackendImpl.h:
+        (WebCore::IDBIndexBackendImpl::id):
+        * storage/IDBKey.cpp:
+        (WebCore::IDBKey::whereSyntax):
+        (WebCore::IDBKey::bind):
+        (WebCore::IDBKey::bindWithNulls):
+        * storage/IDBKey.h:
+        * storage/IDBObjectStore.idl:
+        * storage/IDBObjectStoreBackendImpl.cpp:
+        (WebCore::whereClause):
+        (WebCore::bindWhereClause):
+        (WebCore::IDBObjectStoreBackendImpl::get):
+        (WebCore::fetchKeyFromKeyPath):
+        (WebCore::putObjectStoreData):
+        (WebCore::putIndexData):
+        (WebCore::IDBObjectStoreBackendImpl::put):
+        (WebCore::IDBObjectStoreBackendImpl::remove):
+        (WebCore::IDBObjectStoreBackendImpl::createIndex):
+        (WebCore::doDelete):
+        (WebCore::IDBObjectStoreBackendImpl::removeIndex):
+        (WebCore::IDBObjectStoreBackendImpl::openCursor):
+        * storage/IDBObjectStoreBackendImpl.h:
+
 2010-09-06  Anton Muhin  <antonm at chromium.org>
 
         Reviewed by Adam Barth.
diff --git a/WebCore/storage/IDBDatabaseBackendImpl.cpp b/WebCore/storage/IDBDatabaseBackendImpl.cpp
index f4f2934..021f70a 100644
--- a/WebCore/storage/IDBDatabaseBackendImpl.cpp
+++ b/WebCore/storage/IDBDatabaseBackendImpl.cpp
@@ -177,8 +177,8 @@ void IDBDatabaseBackendImpl::removeObjectStore(const String& name, PassRefPtr<ID
     transaction.begin();
     doDelete(sqliteDatabase(), "DELETE FROM ObjectStores WHERE id = ?", objectStore->id());
     doDelete(sqliteDatabase(), "DELETE FROM ObjectStoreData WHERE objectStoreId = ?", objectStore->id());
+    doDelete(sqliteDatabase(), "DELETE FROM IndexData WHERE indexId IN (SELECT id FROM Indexes WHERE objectStoreId = ?)", objectStore->id());
     doDelete(sqliteDatabase(), "DELETE FROM Indexes WHERE objectStoreId = ?", objectStore->id());
-    // FIXME: Delete index data as well.
     transaction.commit();
 
     m_objectStores.remove(name);
diff --git a/WebCore/storage/IDBFactoryBackendImpl.cpp b/WebCore/storage/IDBFactoryBackendImpl.cpp
index d656128..50cf778 100644
--- a/WebCore/storage/IDBFactoryBackendImpl.cpp
+++ b/WebCore/storage/IDBFactoryBackendImpl.cpp
@@ -83,19 +83,28 @@ static bool createTables(SQLiteDatabase* sqliteDatabase)
         "CREATE TABLE IF NOT EXISTS MetaData (id INTEGER PRIMARY KEY, name TEXT NOT NULL, description TEXT NOT NULL, version TEXT NOT NULL)",
 
         "DROP TABLE IF EXISTS ObjectStores",
-        "CREATE TABLE IF NOT EXISTS ObjectStores (id INTEGER PRIMARY KEY, name TEXT NOT NULL, keyPath TEXT, doAutoIncrement INTEGER NOT NULL)",
+        "CREATE TABLE IF NOT EXISTS ObjectStores (id INTEGER PRIMARY KEY, name TEXT NOT NULL UNIQUE, keyPath TEXT, doAutoIncrement INTEGER NOT NULL)",
         "DROP INDEX IF EXISTS ObjectStores_name",
         "CREATE UNIQUE INDEX IF NOT EXISTS ObjectStores_name ON ObjectStores(name)",
 
         "DROP TABLE IF EXISTS Indexes",
-        "CREATE TABLE IF NOT EXISTS Indexes (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), name TEXT NOT NULL, keyPath TEXT, isUnique INTEGER NOT NULL)",
+        "CREATE TABLE IF NOT EXISTS Indexes (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), name TEXT NOT NULL UNIQUE, keyPath TEXT, isUnique INTEGER NOT NULL)",
         "DROP INDEX IF EXISTS Indexes_composit",
         "CREATE UNIQUE INDEX IF NOT EXISTS Indexes_composit ON Indexes(objectStoreId, name)",
 
         "DROP TABLE IF EXISTS ObjectStoreData",
-        "CREATE TABLE IF NOT EXISTS ObjectStoreData (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), keyString TEXT, keyDate INTEGER, keyNumber INTEGER, value TEXT NOT NULL)",
+        "CREATE TABLE IF NOT EXISTS ObjectStoreData (id INTEGER PRIMARY KEY, objectStoreId INTEGER NOT NULL REFERENCES ObjectStore(id), keyString TEXT UNIQUE, keyDate INTEGER UNIQUE, keyNumber INTEGER UNIQUE, value TEXT NOT NULL)",
         "DROP INDEX IF EXISTS ObjectStoreData_composit",
-        "CREATE UNIQUE INDEX IF NOT EXISTS ObjectStoreData_composit ON ObjectStoreData(keyString, keyDate, keyNumber, objectStoreId)"
+        "CREATE UNIQUE INDEX IF NOT EXISTS ObjectStoreData_composit ON ObjectStoreData(keyString, keyDate, keyNumber, objectStoreId)",
+
+        "DROP TABLE IF EXISTS IndexData",
+        "CREATE TABLE IF NOT EXISTS IndexData (id INTEGER PRIMARY KEY, indexId INTEGER NOT NULL REFERENCES Indexs(id), keyString TEXT, keyDate INTEGER, keyNumber INTEGER, objectStoreDataId INTEGER NOT NULL UNIQUE REFERENCES ObjectStoreData(id))",
+        "DROP INDEX IF EXISTS IndexData_composit",
+        "CREATE UNIQUE INDEX IF NOT EXISTS IndexData_composit ON IndexData(keyString, keyDate, keyNumber, indexId)",
+        "DROP INDEX IF EXISTS IndexData_objectStoreDataId",
+        "CREATE UNIQUE INDEX IF NOT EXISTS IndexData_objectStoreDataId ON IndexData(objectStoreDataId)",
+        "DROP INDEX IF EXISTS IndexData_indexId",
+        "CREATE UNIQUE INDEX IF NOT EXISTS IndexData_indexId ON IndexData(indexId)"
         };
 
     for (size_t i = 0; i < arraysize(commands); ++i) {
diff --git a/WebCore/storage/IDBIndex.idl b/WebCore/storage/IDBIndex.idl
index e796b03..629481e 100644
--- a/WebCore/storage/IDBIndex.idl
+++ b/WebCore/storage/IDBIndex.idl
@@ -28,11 +28,16 @@ module storage {
     interface [
         Conditional=INDEXED_DATABASE
     ] IDBIndex {
-        // FIXME: Complete this file.
-
         readonly attribute DOMString name;
+        // FIXME: Add "storeName".
         readonly attribute DOMString keyPath;
         readonly attribute boolean unique;
+
+        // FIXME: Implement.
+        //IDBRequest openObjectCursor(in [Optional] IDBKeyRange range, in [Optional] unsigned short direction) raises (DOMException);
+        //IDBRequest openCursor(in [Optional] IDBKeyRange range, in [Optional] unsigned short direction) raises (DOMException);
+        //IDBRequest getObject(in IDBKey key) raises (DOMException);
+        //IDBRequest get(in IDBKey key) raises (DOMException);
     };
 
 }
diff --git a/WebCore/storage/IDBIndexBackendImpl.cpp b/WebCore/storage/IDBIndexBackendImpl.cpp
index 180ff1d..42aa62b 100644
--- a/WebCore/storage/IDBIndexBackendImpl.cpp
+++ b/WebCore/storage/IDBIndexBackendImpl.cpp
@@ -30,7 +30,7 @@
 
 #include "IDBDatabaseBackendImpl.h"
 #include "IDBObjectStoreBackendImpl.h"
-#include "SQLiteDatabase.h"
+#include "SQLiteStatement.h"
 
 namespace WebCore {
 
@@ -47,6 +47,31 @@ IDBIndexBackendImpl::~IDBIndexBackendImpl()
 {
 }
 
+static String whereClause(IDBKey* key)
+{
+    return "WHERE indexId = ?  AND  " + key->whereSyntax();
+}
+
+static void bindWhereClause(SQLiteStatement& query, int64_t id, IDBKey* key)
+{
+    query.bindInt64(1, id);
+    key->bind(query, 2);
+}
+
+bool IDBIndexBackendImpl::addingKeyAllowed(IDBKey* key)
+{
+    if (!m_unique)
+        return true;
+
+    SQLiteStatement query(sqliteDatabase(), "SELECT id FROM IndexData " + whereClause(key));
+    bool ok = query.prepare() == SQLResultOk;
+    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
+    bindWhereClause(query, m_id, key);
+    bool existingValue = query.step() == SQLResultRow;
+
+    return !existingValue;
+}
+
 SQLiteDatabase& IDBIndexBackendImpl::sqliteDatabase() const
 {
     return m_objectStore->database()->sqliteDatabase();
diff --git a/WebCore/storage/IDBIndexBackendImpl.h b/WebCore/storage/IDBIndexBackendImpl.h
index acf6b1f..97c65f9 100644
--- a/WebCore/storage/IDBIndexBackendImpl.h
+++ b/WebCore/storage/IDBIndexBackendImpl.h
@@ -32,6 +32,7 @@
 
 namespace WebCore {
 
+class IDBKey;
 class IDBObjectStoreBackendImpl;
 class SQLiteDatabase;
 
@@ -43,6 +44,9 @@ public:
     }
     virtual ~IDBIndexBackendImpl();
 
+    int64_t id() { return m_id; }
+    bool addingKeyAllowed(IDBKey*);
+
     // Implements IDBIndexBackendInterface.
     virtual String name() { return m_name; }
     virtual String keyPath() { return m_keyPath; }
diff --git a/WebCore/storage/IDBKey.cpp b/WebCore/storage/IDBKey.cpp
index 50c4c46..6ae79ba 100644
--- a/WebCore/storage/IDBKey.cpp
+++ b/WebCore/storage/IDBKey.cpp
@@ -28,6 +28,7 @@
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "SQLiteStatement.h"
 #include "SerializedScriptValue.h"
 
 namespace WebCore {
@@ -72,6 +73,63 @@ bool IDBKey::isEqual(IDBKey* other)
     return false;
 }
 
+String IDBKey::whereSyntax() const
+{
+    switch (m_type) {
+    case IDBKey::StringType:
+        return "keyString = ?";
+    case IDBKey::NumberType:
+        return "keyNumber = ?";
+    // FIXME: Implement date.
+    case IDBKey::NullType:
+        return "keyString IS NULL  AND  keyDate IS NULL  AND  keyNumber IS NULL";
+    }
+
+    ASSERT_NOT_REACHED();
+    return "";
+}
+
+// Returns the number of items bound.
+int IDBKey::bind(SQLiteStatement& query, int column) const
+{
+    switch (m_type) {
+    case IDBKey::StringType:
+        query.bindText(column, m_string);
+        return 1;
+    case IDBKey::NumberType:
+        query.bindInt(column, m_number);
+        return 1;
+    case IDBKey::NullType:
+        return 0;
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+void IDBKey::bindWithNulls(SQLiteStatement& query, int baseColumn) const
+{
+    switch (m_type) {
+    case IDBKey::StringType:
+        query.bindText(baseColumn + 0, m_string);
+        query.bindNull(baseColumn + 1);
+        query.bindNull(baseColumn + 2);
+        break;
+    case IDBKey::NumberType:
+        query.bindNull(baseColumn + 0);
+        query.bindNull(baseColumn + 1);
+        query.bindInt(baseColumn + 2, m_number);
+        break;
+    case IDBKey::NullType:
+        query.bindNull(baseColumn + 0);
+        query.bindNull(baseColumn + 1);
+        query.bindNull(baseColumn + 2);
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+}
+
 } // namespace WebCore
 
 #endif
diff --git a/WebCore/storage/IDBKey.h b/WebCore/storage/IDBKey.h
index 228b4a4..b9a0be7 100644
--- a/WebCore/storage/IDBKey.h
+++ b/WebCore/storage/IDBKey.h
@@ -33,6 +33,8 @@
 
 namespace WebCore {
 
+class SQLiteStatement;
+
 // FIXME: Add dates.
 class IDBKey : public RefCounted<IDBKey> {
 public:
@@ -72,6 +74,9 @@ public:
     }
 
     bool isEqual(IDBKey* other);
+    String whereSyntax() const;
+    int bind(SQLiteStatement& query, int column) const;
+    void bindWithNulls(SQLiteStatement& query, int baseColumn) const;
 
 private:
     IDBKey();
diff --git a/WebCore/storage/IDBObjectStore.idl b/WebCore/storage/IDBObjectStore.idl
index 1649a1d..ccd0311 100644
--- a/WebCore/storage/IDBObjectStore.idl
+++ b/WebCore/storage/IDBObjectStore.idl
@@ -28,10 +28,8 @@ module storage {
     interface [
         Conditional=INDEXED_DATABASE
     ] IDBObjectStore {
+        // FIXME: Many of these should raise on certain errors.
         [CallWith=ScriptExecutionContext] IDBRequest get(in IDBKey key);        
-        // FIXME: Come to concensus re getAll.
-        // FIXME: SerializedScriptValue raises an exception if you pass in something that can't be serialized.
-        //        We need to instead "raise" this error via an error callback.
         [CallWith=ScriptExecutionContext] IDBRequest add(in SerializedScriptValue value, in [Optional] IDBKey key);
         [CallWith=ScriptExecutionContext] IDBRequest put(in SerializedScriptValue value, in [Optional] IDBKey key);
         [CallWith=ScriptExecutionContext] IDBRequest remove(in IDBKey key);
diff --git a/WebCore/storage/IDBObjectStoreBackendImpl.cpp b/WebCore/storage/IDBObjectStoreBackendImpl.cpp
index aeb3ced..86237de 100755
--- a/WebCore/storage/IDBObjectStoreBackendImpl.cpp
+++ b/WebCore/storage/IDBObjectStoreBackendImpl.cpp
@@ -38,6 +38,7 @@
 #include "IDBKeyRange.h"
 #include "SQLiteDatabase.h"
 #include "SQLiteStatement.h"
+#include "SQLiteTransaction.h"
 
 #if ENABLE(INDEXED_DATABASE)
 
@@ -65,50 +66,20 @@ PassRefPtr<DOMStringList> IDBObjectStoreBackendImpl::indexNames() const
     return indexNames.release();
 }
 
-static String whereClause(IDBKey::Type type)
+static String whereClause(IDBKey* key)
 {
-    switch (type) {
-    case IDBKey::StringType:
-        return "WHERE objectStoreId = ?  AND  keyString = ?";
-    case IDBKey::NumberType:
-        return "WHERE objectStoreId = ?  AND  keyNumber = ?";
-    // FIXME: Implement date.
-    case IDBKey::NullType:
-        return "WHERE objectStoreId = ?  AND  keyString IS NULL  AND  keyDate IS NULL  AND  keyNumber IS NULL";
-    }
-
-    ASSERT_NOT_REACHED();
-    return "";
-}
-
-// Returns number of items bound.
-static int bindKey(SQLiteStatement& query, int column, IDBKey* key)
-{
-    switch (key->type()) {
-    case IDBKey::StringType:
-        query.bindText(column, key->string());
-        return 1;
-    case IDBKey::NumberType:
-        query.bindInt(column, key->number());
-        return 1;
-    // FIXME: Implement date.
-    case IDBKey::NullType:
-        return 0;
-    }
-
-    ASSERT_NOT_REACHED();
-    return 0;
+    return "WHERE objectStoreId = ?  AND  " + key->whereSyntax();
 }
 
 static void bindWhereClause(SQLiteStatement& query, int64_t id, IDBKey* key)
 {
     query.bindInt64(1, id);
-    bindKey(query, 2, key);
+    key->bind(query, 2);
 }
 
 void IDBObjectStoreBackendImpl::get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
 {
-    SQLiteStatement query(sqliteDatabase(), "SELECT keyString, keyDate, keyNumber, value FROM ObjectStoreData " + whereClause(key->type()));
+    SQLiteStatement query(sqliteDatabase(), "SELECT keyString, keyDate, keyNumber, value FROM ObjectStoreData " + whereClause(key.get()));
     bool ok = query.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
 
@@ -126,6 +97,59 @@ void IDBObjectStoreBackendImpl::get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallba
     ASSERT(query.step() != SQLResultRow);
 }
 
+static PassRefPtr<IDBKey> fetchKeyFromKeyPath(SerializedScriptValue* value, const String& keyPath)
+{
+    Vector<RefPtr<SerializedScriptValue> > values;
+    values.append(value);
+    Vector<RefPtr<IDBKey> > keys;
+    IDBKeyPathBackendImpl::createIDBKeysFromSerializedValuesAndKeyPath(values, keyPath, keys);
+    if (keys.isEmpty())
+        return 0;
+    ASSERT(keys.size() == 1);
+    return keys[0].release();
+}
+
+static void putObjectStoreData(SQLiteDatabase& db, IDBKey* key, SerializedScriptValue* value, int64_t objectStoreId, int64_t* dataRowId)
+{
+    String sql = *dataRowId != -1 ? "UPDATE ObjectStoreData SET keyString = ?, keyDate = ?, keyNumber = ?, value = ? WHERE id = ?"
+                                  : "INSERT INTO ObjectStoreData (keyString, keyDate, keyNumber, value, objectStoreId) VALUES (?, ?, ?, ?, ?)";
+    SQLiteStatement query(db, sql);
+    bool ok = query.prepare() == SQLResultOk;
+    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
+    key->bindWithNulls(query, 1);
+    query.bindText(4, value->toWireString());
+    if (*dataRowId != -1)
+        query.bindInt(5, *dataRowId);
+    else
+        query.bindInt64(5, objectStoreId);
+
+    ok = query.step() == SQLResultDone;
+    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
+
+    if (*dataRowId == -1)
+        *dataRowId = db.lastInsertRowID();
+}
+
+static void putIndexData(SQLiteDatabase& db, IDBKey* key, int64_t indexId, int64_t objectStoreDataId)
+{
+    SQLiteStatement deleteQuery(db, "DELETE FROM IndexData WHERE objectStoreDataId = ?");
+    bool ok = deleteQuery.prepare() == SQLResultOk;
+    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
+    deleteQuery.bindInt64(1, objectStoreDataId);
+    ok = deleteQuery.step() == SQLResultDone;
+    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
+
+    SQLiteStatement putQuery(db, "INSERT INTO IndexData (keyString, keyDate, keyNumber, indexId, objectStoreDataId) VALUES (?, ?, ?, ?, ?)");
+    ok = putQuery.prepare() == SQLResultOk;
+    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
+    key->bindWithNulls(putQuery, 1);
+    putQuery.bindInt64(4, indexId);
+    putQuery.bindInt64(5, objectStoreDataId);
+
+    ok = putQuery.step() == SQLResultDone;
+    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
+}
+
 void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, bool addOnly, PassRefPtr<IDBCallbacks> callbacks)
 {
     RefPtr<SerializedScriptValue> value = prpValue;
@@ -136,73 +160,56 @@ void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue,
             callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "A key was supplied for an objectStore that has a keyPath."));
             return;
         }
-        Vector<RefPtr<SerializedScriptValue> > values;
-        values.append(value);
-        Vector<RefPtr<IDBKey> > idbKeys;
-        IDBKeyPathBackendImpl::createIDBKeysFromSerializedValuesAndKeyPath(values, m_keyPath, idbKeys);
-        if (idbKeys.isEmpty()) {
-            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "An invalid keyPath was supplied for an objectStore."));
+        key = fetchKeyFromKeyPath(value.get(), m_keyPath);
+        if (!key) {
+            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "The key could not be fetched from the keyPath."));
             return;
         }
-        key = idbKeys[0];
-    }
-
-    if (!key) {
+    } else if (!key) {
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "No key supplied."));
         return;
     }
 
-    SQLiteStatement getQuery(sqliteDatabase(), "SELECT id FROM ObjectStoreData " + whereClause(key->type()));
+    Vector<RefPtr<IDBKey> > indexKeys;
+    for (IndexMap::iterator it = m_indexes.begin(); it != m_indexes.end(); ++it) {
+        RefPtr<IDBKey> key = fetchKeyFromKeyPath(value.get(), it->second->keyPath());
+        if (!key) {
+            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "The key could not be fetched from an index's keyPath."));
+            return;
+        }
+        if (!it->second->addingKeyAllowed(key.get())) {
+            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "One of the derived (from a keyPath) keys for an index does not satisfy its uniqueness requirements."));
+            return;
+        }
+        indexKeys.append(key.release());
+    }
+
+    SQLiteStatement getQuery(sqliteDatabase(), "SELECT id FROM ObjectStoreData " + whereClause(key.get()));
     bool ok = getQuery.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
 
     bindWhereClause(getQuery, m_id, key.get());
-    bool existingValue = getQuery.step() == SQLResultRow;
-    if (addOnly && existingValue) {
+    bool isExistingValue = getQuery.step() == SQLResultRow;
+    if (addOnly && isExistingValue) {
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Key already exists in the object store."));
         return;
     }
 
-    String sql = existingValue ? "UPDATE ObjectStoreData SET keyString = ?, keyDate = ?, keyNumber = ?, value = ? WHERE id = ?"
-                               : "INSERT INTO ObjectStoreData (keyString, keyDate, keyNumber, value, objectStoreId) VALUES (?, ?, ?, ?, ?)";
-    SQLiteStatement putQuery(sqliteDatabase(), sql);
-    ok = putQuery.prepare() == SQLResultOk;
-    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
-    switch (key->type()) {
-    case IDBKey::StringType:
-        putQuery.bindText(1, key->string());
-        putQuery.bindNull(2);
-        putQuery.bindNull(3);
-        break;
-    // FIXME: Implement date.
-    case IDBKey::NumberType:
-        putQuery.bindNull(1);
-        putQuery.bindNull(2);
-        putQuery.bindInt(3, key->number());
-        break;
-    case IDBKey::NullType:
-        putQuery.bindNull(1);
-        putQuery.bindNull(2);
-        putQuery.bindNull(3);
-        break;
-    default:
-        ASSERT_NOT_REACHED();
-    }
-    putQuery.bindText(4, value->toWireString());
-    if (existingValue)
-        putQuery.bindInt(5, getQuery.getColumnInt(0));
-    else
-        putQuery.bindInt64(5, m_id);
+    // Before this point, don't do any mutation.  After this point, don't error out.
 
-    ok = putQuery.step() == SQLResultDone;
-    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
+    int64_t dataRowId = isExistingValue ? getQuery.getColumnInt(0) : -1;
+    putObjectStoreData(sqliteDatabase(), key.get(), value.get(), m_id, &dataRowId);
+
+    int i = 0;
+    for (IndexMap::iterator it = m_indexes.begin(); it != m_indexes.end(); ++it, ++i)
+        putIndexData(sqliteDatabase(), indexKeys[i].get(), it->second->id(), dataRowId);
 
     callbacks->onSuccess(key.get());
 }
 
 void IDBObjectStoreBackendImpl::remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
 {
-    SQLiteStatement query(sqliteDatabase(), "DELETE FROM ObjectStoreData " + whereClause(key->type()));
+    SQLiteStatement query(sqliteDatabase(), "DELETE FROM ObjectStoreData " + whereClause(key.get()));
     bool ok = query.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
 
@@ -233,10 +240,10 @@ void IDBObjectStoreBackendImpl::createIndex(const String& name, const String& ke
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
     int64_t id = sqliteDatabase().lastInsertRowID();
 
-    RefPtr<IDBIndexBackendInterface> index = IDBIndexBackendImpl::create(this, id, name, keyPath, unique);
+    RefPtr<IDBIndexBackendImpl> index = IDBIndexBackendImpl::create(this, id, name, keyPath, unique);
     ASSERT(index->name() == name);
     m_indexes.set(name, index);
-    callbacks->onSuccess(index.release());
+    callbacks->onSuccess(index.get());
 }
 
 PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::index(const String& name)
@@ -244,22 +251,29 @@ PassRefPtr<IDBIndexBackendInterface> IDBObjectStoreBackendImpl::index(const Stri
     return m_indexes.get(name);
 }
 
-void IDBObjectStoreBackendImpl::removeIndex(const String& name, PassRefPtr<IDBCallbacks> callbacks)
+static void doDelete(SQLiteDatabase& db, const char* sql, int64_t id)
 {
-    if (!m_indexes.contains(name)) {
-        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Index name does not exist."));
-        return;
-    }
-
-    SQLiteStatement deleteQuery(sqliteDatabase(), "DELETE FROM Indexes WHERE name = ? AND objectStoreId = ?");
+    SQLiteStatement deleteQuery(db, sql);
     bool ok = deleteQuery.prepare() == SQLResultOk;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
-    deleteQuery.bindText(1, name);
-    deleteQuery.bindInt64(2, m_id);
+    deleteQuery.bindInt64(1, id);
     ok = deleteQuery.step() == SQLResultDone;
     ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
+}
+
+void IDBObjectStoreBackendImpl::removeIndex(const String& name, PassRefPtr<IDBCallbacks> callbacks)
+{
+    RefPtr<IDBIndexBackendImpl> index = m_indexes.get(name);
+    if (!index) {
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Index name does not exist."));
+        return;
+    }
 
-    // FIXME: Delete index data as well.
+    SQLiteTransaction transaction(sqliteDatabase());
+    transaction.begin();
+    doDelete(sqliteDatabase(), "DELETE FROM Indexes WHERE id = ?", index->id());
+    doDelete(sqliteDatabase(), "DELETE FROM IndexData WHERE indexId = ?", index->id());
+    transaction.commit();
 
     m_indexes.remove(name);
     callbacks->onSuccess();
@@ -337,9 +351,9 @@ void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> range, unsign
 
     int currentColumn = 1;
     if (range->flags() & IDBKeyRange::LEFT_BOUND || range->flags() == IDBKeyRange::SINGLE)
-        currentColumn += bindKey(*query, currentColumn, range->left().get());
+        currentColumn += range->left()->bind(*query, currentColumn);
     if (range->flags() & IDBKeyRange::RIGHT_BOUND || range->flags() == IDBKeyRange::SINGLE)
-        currentColumn += bindKey(*query, currentColumn, range->right().get());
+        currentColumn += range->right()->bind(*query, currentColumn);
     query->bindInt64(currentColumn, m_id);
 
     if (query->step() != SQLResultRow) {
diff --git a/WebCore/storage/IDBObjectStoreBackendImpl.h b/WebCore/storage/IDBObjectStoreBackendImpl.h
index e1058c8..32ef920 100644
--- a/WebCore/storage/IDBObjectStoreBackendImpl.h
+++ b/WebCore/storage/IDBObjectStoreBackendImpl.h
@@ -35,6 +35,7 @@
 namespace WebCore {
 
 class IDBDatabaseBackendImpl;
+class IDBIndexBackendImpl;
 class SQLiteDatabase;
 
 class IDBObjectStoreBackendImpl : public IDBObjectStoreBackendInterface {
@@ -75,7 +76,7 @@ private:
     String m_keyPath;
     bool m_autoIncrement;
 
-    typedef HashMap<String, RefPtr<IDBIndexBackendInterface> > IndexMap;
+    typedef HashMap<String, RefPtr<IDBIndexBackendImpl> > IndexMap;
     IndexMap m_indexes;
 };
 
diff --git a/WebKit/chromium/ChangeLog b/WebKit/chromium/ChangeLog
index 6378e63..8a34b00 100644
--- a/WebKit/chromium/ChangeLog
+++ b/WebKit/chromium/ChangeLog
@@ -1,3 +1,15 @@
+2010-08-26  Jeremy Orlow  <jorlow at chromium.org>
+
+        Reviewed by Steve Block.
+
+        Add index insertion support to IndexedDB.
+        https://bugs.webkit.org/show_bug.cgi?id=44695
+
+        Add asserts on the [] operator.
+
+        * public/WebVector.h:
+        (WebKit::WebVector::operator[]):
+
 2010-09-06  Anton Muhin  <antonm at chromium.org>
 
         Reviewed by Adam Barth.
diff --git a/WebKit/chromium/public/WebVector.h b/WebKit/chromium/public/WebVector.h
index 0520895..cf3ec95 100644
--- a/WebKit/chromium/public/WebVector.h
+++ b/WebKit/chromium/public/WebVector.h
@@ -115,8 +115,16 @@ public:
     size_t size() const { return m_size; }
     bool isEmpty() const { return !m_size; }
 
-    T& operator[](size_t i) { return m_ptr[i]; }
-    const T& operator[](size_t i) const { return m_ptr[i]; }
+    T& operator[](size_t i)
+    {
+        WEBKIT_ASSERT(i < m_size);
+        return m_ptr[i];
+    }
+    const T& operator[](size_t i) const
+    {
+        WEBKIT_ASSERT(i < m_size);
+        return m_ptr[i];
+    }
 
     T* data() { return m_ptr; }
     const T* data() const { return m_ptr; }

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list