[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 12:19:48 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit b3393ab8d30057d19368917fc3652c62b949bd03
Author: jorlow at chromium.org <jorlow at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Aug 19 14:38:34 2010 +0000

    2010-08-18  Jeremy Orlow  <jorlow at chromium.org>
    
            Implement persistance for IndexedDB ObjectStores
            https://bugs.webkit.org/show_bug.cgi?id=44164
    
            Remove old object stores before running test.
    
            * storage/indexeddb/resources/shared.js:
            (deleteAllObjectStores):
            * storage/indexeddb/script-tests/objectstore-basics.js:
            (openSuccess):
            * storage/indexeddb/script-tests/open-cursor.js:
            (openSuccess):
    2010-08-18  Jeremy Orlow  <jorlow at chromium.org>
    
            Reviewed by Steve Block.
    
            Implement persistance for IndexedDB ObjectStores
            https://bugs.webkit.org/show_bug.cgi?id=44164
    
            Get rid of the in-memory storage of ObjectStores and instead
            use SQL backed memory.
    
            Existing tests give most of the coverage.  Will update the manual
            test in the next patch (which will also re-work database.description).
    
            * manual-tests/indexed-database.html: Get rid of race where you can click before the page loads.
            * platform/sql/SQLiteStatement.cpp: Add two helper functions
            (WebCore::SQLiteStatement::bindInt):
            (WebCore::SQLiteStatement::isColumnNull):
            * platform/sql/SQLiteStatement.h:
            * storage/IDBCursorBackendImpl.cpp:
            * storage/IDBDatabaseBackendImpl.cpp:
            (WebCore::IDBDatabaseBackendImpl::IDBDatabaseBackendImpl):
            (WebCore::IDBDatabaseBackendImpl::createObjectStore):
            (WebCore::IDBDatabaseBackendImpl::removeObjectStore):
            (WebCore::IDBDatabaseBackendImpl::importObjectStores):
            * storage/IDBDatabaseBackendImpl.h:
            (WebCore::IDBDatabaseBackendImpl::sqliteDatabase):
            * storage/IDBFactoryBackendImpl.cpp:
            (WebCore::createTables):
            * storage/IDBIndexBackendImpl.cpp:
            (WebCore::IDBIndexBackendImpl::IDBIndexBackendImpl):
            (WebCore::IDBIndexBackendImpl::sqliteDatabase):
            * storage/IDBIndexBackendImpl.h:
            (WebCore::IDBIndexBackendImpl::create):
            * storage/IDBObjectStoreBackendImpl.cpp:
            (WebCore::IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl):
            (WebCore::whereClause):
            (WebCore::bindKey):
            (WebCore::IDBObjectStoreBackendImpl::get):
            (WebCore::IDBObjectStoreBackendImpl::put):
            (WebCore::IDBObjectStoreBackendImpl::remove):
            (WebCore::IDBObjectStoreBackendImpl::createIndex):
            (WebCore::IDBObjectStoreBackendImpl::removeIndex):
            (WebCore::IDBObjectStoreBackendImpl::openCursor):
            (WebCore::IDBObjectStoreBackendImpl::importIndexes):
            (WebCore::IDBObjectStoreBackendImpl::sqliteDatabase):
            * storage/IDBObjectStoreBackendImpl.h:
            (WebCore::IDBObjectStoreBackendImpl::create):
            (WebCore::IDBObjectStoreBackendImpl::database):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@65667 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index af26686..30c00e6 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,17 @@
+2010-08-18  Jeremy Orlow  <jorlow at chromium.org>
+
+        Implement persistance for IndexedDB ObjectStores
+        https://bugs.webkit.org/show_bug.cgi?id=44164
+
+        Remove old object stores before running test.
+
+        * storage/indexeddb/resources/shared.js:
+        (deleteAllObjectStores):
+        * storage/indexeddb/script-tests/objectstore-basics.js:
+        (openSuccess):
+        * storage/indexeddb/script-tests/open-cursor.js:
+        (openSuccess):
+
 2010-08-19  Gustavo Noronha Silva  <gustavo.noronha at collabora.co.uk>
 
         Reviewed by Kenneth Rohde Christiansen.
diff --git a/LayoutTests/storage/indexeddb/resources/shared.js b/LayoutTests/storage/indexeddb/resources/shared.js
index e510be1..6769ed2 100644
--- a/LayoutTests/storage/indexeddb/resources/shared.js
+++ b/LayoutTests/storage/indexeddb/resources/shared.js
@@ -53,3 +53,10 @@ function unexpectedErrorCallback()
     done();
 }
 
+function deleteAllObjectStores(db)
+{
+    objectStores = db.objectStores;
+    for (var i = 0; i < objectStores.length; ++i)
+        db.removeObjectStore(objectStores[i]);
+}
+
diff --git a/LayoutTests/storage/indexeddb/script-tests/objectstore-basics.js b/LayoutTests/storage/indexeddb/script-tests/objectstore-basics.js
index 9869579..63675ad 100644
--- a/LayoutTests/storage/indexeddb/script-tests/objectstore-basics.js
+++ b/LayoutTests/storage/indexeddb/script-tests/objectstore-basics.js
@@ -16,8 +16,7 @@ function openSuccess()
     verifySuccessEvent(event);
     db = evalAndLog("db = event.result");
 
-    // FIXME: remove any previously created object stores.
-    // This requires IDBDatabaseRequest::removeObjectStore to be implemented.
+    deleteAllObjectStores(db);
 
     result = evalAndLog("db.createObjectStore('storeName', null)");
     verifyResult(result);
diff --git a/LayoutTests/storage/indexeddb/script-tests/open-cursor.js b/LayoutTests/storage/indexeddb/script-tests/open-cursor.js
index e3c615c..ff0b711 100644
--- a/LayoutTests/storage/indexeddb/script-tests/open-cursor.js
+++ b/LayoutTests/storage/indexeddb/script-tests/open-cursor.js
@@ -60,6 +60,9 @@ function openSuccess()
 {
     verifySuccessEvent(event);
     var db = evalAndLog("db = event.result");
+
+    deleteAllObjectStores(db);
+
     result = evalAndLog("db.createObjectStore('test')");
     verifyResult(result);
     result.onsuccess = createObjectStoreSuccess;
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index b5cf24f..ee18fc1 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,52 @@
+2010-08-18  Jeremy Orlow  <jorlow at chromium.org>
+
+        Reviewed by Steve Block.
+
+        Implement persistance for IndexedDB ObjectStores
+        https://bugs.webkit.org/show_bug.cgi?id=44164
+
+        Get rid of the in-memory storage of ObjectStores and instead
+        use SQL backed memory.
+
+        Existing tests give most of the coverage.  Will update the manual
+        test in the next patch (which will also re-work database.description).
+
+        * manual-tests/indexed-database.html: Get rid of race where you can click before the page loads.
+        * platform/sql/SQLiteStatement.cpp: Add two helper functions
+        (WebCore::SQLiteStatement::bindInt):
+        (WebCore::SQLiteStatement::isColumnNull):
+        * platform/sql/SQLiteStatement.h:
+        * storage/IDBCursorBackendImpl.cpp: 
+        * storage/IDBDatabaseBackendImpl.cpp:
+        (WebCore::IDBDatabaseBackendImpl::IDBDatabaseBackendImpl):
+        (WebCore::IDBDatabaseBackendImpl::createObjectStore):
+        (WebCore::IDBDatabaseBackendImpl::removeObjectStore):
+        (WebCore::IDBDatabaseBackendImpl::importObjectStores):
+        * storage/IDBDatabaseBackendImpl.h:
+        (WebCore::IDBDatabaseBackendImpl::sqliteDatabase):
+        * storage/IDBFactoryBackendImpl.cpp:
+        (WebCore::createTables):
+        * storage/IDBIndexBackendImpl.cpp:
+        (WebCore::IDBIndexBackendImpl::IDBIndexBackendImpl):
+        (WebCore::IDBIndexBackendImpl::sqliteDatabase):
+        * storage/IDBIndexBackendImpl.h:
+        (WebCore::IDBIndexBackendImpl::create):
+        * storage/IDBObjectStoreBackendImpl.cpp:
+        (WebCore::IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl):
+        (WebCore::whereClause):
+        (WebCore::bindKey):
+        (WebCore::IDBObjectStoreBackendImpl::get):
+        (WebCore::IDBObjectStoreBackendImpl::put):
+        (WebCore::IDBObjectStoreBackendImpl::remove):
+        (WebCore::IDBObjectStoreBackendImpl::createIndex):
+        (WebCore::IDBObjectStoreBackendImpl::removeIndex):
+        (WebCore::IDBObjectStoreBackendImpl::openCursor):
+        (WebCore::IDBObjectStoreBackendImpl::importIndexes):
+        (WebCore::IDBObjectStoreBackendImpl::sqliteDatabase):
+        * storage/IDBObjectStoreBackendImpl.h:
+        (WebCore::IDBObjectStoreBackendImpl::create):
+        (WebCore::IDBObjectStoreBackendImpl::database):
+
 2010-08-19  Nikolas Zimmermann  <nzimmermann at rim.com>
 
         Reviewed by Dirk Schulze.
diff --git a/WebCore/manual-tests/indexed-database.html b/WebCore/manual-tests/indexed-database.html
index d0fb381..bcc8fe4 100644
--- a/WebCore/manual-tests/indexed-database.html
+++ b/WebCore/manual-tests/indexed-database.html
@@ -16,6 +16,8 @@
 
 <script>
 
+    readyCount = 0;
+
     if (!('indexedDB' in window))
         document.getElementById("enabled").innerHTML = "<font color=red>Your build does NOT seem to have it enabled.  So all code on this page is disabled.</font>";
     else {
@@ -25,6 +27,7 @@
         request.onsuccess = function() {
             document.getElementById("result").innerHTML = "<font color=green>Success!</font>";
             window.nameDB = event.result;
+            ++readyCount;
         };
         request.onerror = function() {
             document.getElementById("result").innerHTML = "<font color=red>Error: " + event.message + ".</font>";
@@ -33,17 +36,28 @@
         request = indexedDB.open("another", "test of the description attribute");
         request.onsuccess = function() {
             window.anotherDB = event.result;
+            ++readyCount;
         };
     }
 
     function updateDescription()
     {
+        if (readCount < 2) {
+            alert("The page has not finished loading.  Hold on a sec...");
+            return;
+        }
+
         indexedDB.open("name", "test of the description attribute");
         indexedDB.open("another", "xyz");
     }
 
     function readDescription()
     {
+        if (readCount < 2) {
+            alert("The page has not finished loading.  Hold on a sec...");
+            return;
+        }
+
         if (window.nameDB.description != "test of the description attribute") {
             // Since we passed in nothing, the description should not be reset.
             document.getElementById("description").innerHTML = "<font color=red>Failure: (Database 'name' was this: " + window.nameDB.description + ").</font>";
diff --git a/WebCore/platform/sql/SQLiteStatement.cpp b/WebCore/platform/sql/SQLiteStatement.cpp
index 4dc80fb..037ec79 100644
--- a/WebCore/platform/sql/SQLiteStatement.cpp
+++ b/WebCore/platform/sql/SQLiteStatement.cpp
@@ -192,6 +192,14 @@ int SQLiteStatement::bindText(int index, const String& text)
     return sqlite3_bind_text16(m_statement, index, characters, sizeof(UChar) * text.length(), SQLITE_TRANSIENT);
 }
 
+int SQLiteStatement::bindInt(int index, int integer)
+{
+    ASSERT(m_isPrepared);
+    ASSERT(index > 0);
+    ASSERT(static_cast<unsigned>(index) <= bindParameterCount());
+
+    return sqlite3_bind_int(m_statement, index, integer);
+}
 
 int SQLiteStatement::bindInt64(int index, int64_t integer)
 {
@@ -251,6 +259,18 @@ int SQLiteStatement::columnCount()
     return sqlite3_data_count(m_statement);
 }
 
+bool SQLiteStatement::isColumnNull(int col)
+{
+    ASSERT(col >= 0);
+    if (!m_statement)
+        if (prepareAndStep() != SQLITE_ROW)
+            return false;
+    if (columnCount() <= col)
+        return false;
+
+    return sqlite3_column_type(m_statement, col) == SQLITE_NULL;
+}
+
 String SQLiteStatement::getColumnName(int col)
 {
     ASSERT(col >= 0);
diff --git a/WebCore/platform/sql/SQLiteStatement.h b/WebCore/platform/sql/SQLiteStatement.h
index e62b4f0..1444f0e 100644
--- a/WebCore/platform/sql/SQLiteStatement.h
+++ b/WebCore/platform/sql/SQLiteStatement.h
@@ -42,6 +42,7 @@ public:
     int prepare();
     int bindBlob(int index, const void* blob, int size);
     int bindText(int index, const String&);
+    int bindInt(int index, int);
     int bindInt64(int index, int64_t);
     int bindDouble(int index, double);
     int bindNull(int index);
@@ -70,6 +71,7 @@ public:
     // returned in the last step()
     int columnCount();
     
+    bool isColumnNull(int col);
     String getColumnName(int col);
     SQLValue getColumnValue(int col);
     String getColumnText(int col);
diff --git a/WebCore/storage/IDBCursorBackendImpl.cpp b/WebCore/storage/IDBCursorBackendImpl.cpp
index 4e08b8f..d3298b3 100644
--- a/WebCore/storage/IDBCursorBackendImpl.cpp
+++ b/WebCore/storage/IDBCursorBackendImpl.cpp
@@ -33,6 +33,7 @@
 #include "IDBKeyRange.h"
 #include "IDBObjectStoreBackendImpl.h"
 #include "IDBRequest.h"
+#include "SQLiteDatabase.h"
 #include "SerializedScriptValue.h"
 
 namespace WebCore {
diff --git a/WebCore/storage/IDBDatabaseBackendImpl.cpp b/WebCore/storage/IDBDatabaseBackendImpl.cpp
index e550e18..3acf2a5 100644
--- a/WebCore/storage/IDBDatabaseBackendImpl.cpp
+++ b/WebCore/storage/IDBDatabaseBackendImpl.cpp
@@ -97,6 +97,8 @@ IDBDatabaseBackendImpl::IDBDatabaseBackendImpl(const String& name, const String&
 
     if (!result || m_description != foundDescription)
         setMetaData(m_sqliteDatabase.get(), m_name, m_description, m_version);
+
+    loadObjectStores();
 }
 
 IDBDatabaseBackendImpl::~IDBDatabaseBackendImpl()
@@ -127,7 +129,18 @@ void IDBDatabaseBackendImpl::createObjectStore(const String& name, const String&
         return;
     }
 
-    RefPtr<IDBObjectStoreBackendInterface> objectStore = IDBObjectStoreBackendImpl::create(name, keyPath, autoIncrement);
+    SQLiteStatement insert(sqliteDatabase(), "INSERT INTO ObjectStores (name, keyPath, doAutoIncrement) VALUES (?, ?, ?)");
+    bool ok = insert.prepare() == SQLResultOk;
+    ASSERT(ok); // FIXME: Better error handling.
+    insert.bindText(1, name);
+    insert.bindText(2, keyPath);
+    insert.bindInt(3, static_cast<int>(autoIncrement));
+    ok = insert.step() == SQLResultDone;
+    ASSERT(ok); // FIXME: Better error handling.
+    int64_t id = sqliteDatabase().lastInsertRowID();
+
+    RefPtr<IDBObjectStoreBackendInterface> objectStore = IDBObjectStoreBackendImpl::create(this, id, name, keyPath, autoIncrement);
+    ASSERT(objectStore->name() == name);
     m_objectStores.set(name, objectStore);
     callbacks->onSuccess(objectStore.release());
 }
@@ -146,6 +159,13 @@ void IDBDatabaseBackendImpl::removeObjectStore(const String& name, PassRefPtr<ID
         return;
     }
 
+    SQLiteStatement deleteQuery(sqliteDatabase(), "DELETE FROM ObjectStores WHERE name = ?");
+    bool ok = deleteQuery.prepare() == SQLResultOk;
+    ASSERT(ok); // FIXME: Better error handling.
+    deleteQuery.bindText(1, name);
+    ok = deleteQuery.step() == SQLResultDone;
+    ASSERT(ok); // FIXME: Better error handling.
+
     m_objectStores.remove(name);
     callbacks->onSuccess();
 }
@@ -157,6 +177,22 @@ PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::transaction(D
     return 0;
 }
 
+void IDBDatabaseBackendImpl::loadObjectStores()
+{
+    SQLiteStatement objectStoresQuery(sqliteDatabase(), "SELECT id, name, keyPath, doAutoIncrement FROM ObjectStores");
+    bool ok = objectStoresQuery.prepare() == SQLResultOk;
+    ASSERT(ok); // FIXME: Better error handling?
+
+    while (objectStoresQuery.step() == SQLResultRow) {
+        int64_t id = objectStoresQuery.getColumnInt64(0);
+        String name = objectStoresQuery.getColumnText(1);
+        String keyPath = objectStoresQuery.getColumnText(2);
+        bool autoIncrement = !!objectStoresQuery.getColumnInt(3);
+
+        m_objectStores.set(name, IDBObjectStoreBackendImpl::create(this, id, name, keyPath, autoIncrement));
+    }
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
diff --git a/WebCore/storage/IDBDatabaseBackendImpl.h b/WebCore/storage/IDBDatabaseBackendImpl.h
index 60bec1f..c8c5a91 100644
--- a/WebCore/storage/IDBDatabaseBackendImpl.h
+++ b/WebCore/storage/IDBDatabaseBackendImpl.h
@@ -46,6 +46,7 @@ public:
     virtual ~IDBDatabaseBackendImpl();
 
     void setDescription(const String& description);
+    SQLiteDatabase& sqliteDatabase() const { return *m_sqliteDatabase.get(); }
 
     // Implements IDBDatabase
     virtual String name() const { return m_name; }
@@ -60,6 +61,8 @@ public:
 private:
     IDBDatabaseBackendImpl(const String& name, const String& description, PassOwnPtr<SQLiteDatabase> database);
 
+    void loadObjectStores();
+
     OwnPtr<SQLiteDatabase> m_sqliteDatabase;
 
     String m_name;
diff --git a/WebCore/storage/IDBFactoryBackendImpl.cpp b/WebCore/storage/IDBFactoryBackendImpl.cpp
index 905726f..5af33e7 100644
--- a/WebCore/storage/IDBFactoryBackendImpl.cpp
+++ b/WebCore/storage/IDBFactoryBackendImpl.cpp
@@ -75,8 +75,25 @@ static PassOwnPtr<SQLiteDatabase> openSQLiteDatabase(SecurityOrigin* securityOri
 
 static bool createTables(SQLiteDatabase* sqliteDatabase)
 {
+    // FIXME: Remove all the drop table commands once the on disk structure stabilizes.
     static const char* commands[] = {
-        "CREATE TABLE IF NOT EXISTS MetaData (name TEXT, description TEXT, version TEXT)"
+        "DROP TABLE IF EXISTS MetaData",
+        "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)",
+        "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) ON DELETE CASCADE, name TEXT NOT NULL, 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) ON DELETE CASCADE, keyString TEXT, keyDate INTEGER, keyNumber INTEGER, value TEXT NOT NULL)",
+        "DROP INDEX IF EXISTS ObjectStoreData_composit",
+        "CREATE UNIQUE INDEX IF NOT EXISTS ObjectStoreData_composit ON ObjectStoreData(keyString, keyDate, keyNumber, objectStoreId)"
         };
 
     for (size_t i = 0; i < arraysize(commands); ++i) {
diff --git a/WebCore/storage/IDBIndexBackendImpl.cpp b/WebCore/storage/IDBIndexBackendImpl.cpp
index 406e37f..180ff1d 100644
--- a/WebCore/storage/IDBIndexBackendImpl.cpp
+++ b/WebCore/storage/IDBIndexBackendImpl.cpp
@@ -28,10 +28,16 @@
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "IDBDatabaseBackendImpl.h"
+#include "IDBObjectStoreBackendImpl.h"
+#include "SQLiteDatabase.h"
+
 namespace WebCore {
 
-IDBIndexBackendImpl::IDBIndexBackendImpl(const String& name, const String& keyPath, bool unique)
-    : m_name(name)
+IDBIndexBackendImpl::IDBIndexBackendImpl(IDBObjectStoreBackendImpl* objectStore, int64_t id, const String& name, const String& keyPath, bool unique)
+    : m_objectStore(objectStore)
+    , m_id(id)
+    , m_name(name)
     , m_keyPath(keyPath)
     , m_unique(unique)
 {
@@ -41,6 +47,11 @@ IDBIndexBackendImpl::~IDBIndexBackendImpl()
 {
 }
 
+SQLiteDatabase& IDBIndexBackendImpl::sqliteDatabase() const
+{
+    return m_objectStore->database()->sqliteDatabase();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INDEXED_DATABASE)
diff --git a/WebCore/storage/IDBIndexBackendImpl.h b/WebCore/storage/IDBIndexBackendImpl.h
index ca3f01e..acf6b1f 100644
--- a/WebCore/storage/IDBIndexBackendImpl.h
+++ b/WebCore/storage/IDBIndexBackendImpl.h
@@ -32,11 +32,14 @@
 
 namespace WebCore {
 
+class IDBObjectStoreBackendImpl;
+class SQLiteDatabase;
+
 class IDBIndexBackendImpl : public IDBIndexBackendInterface {
 public:
-    static PassRefPtr<IDBIndexBackendImpl> create(const String& name, const String& keyPath, bool unique)
+    static PassRefPtr<IDBIndexBackendImpl> create(IDBObjectStoreBackendImpl* objectStore, int64_t id, const String& name, const String& keyPath, bool unique)
     {
-        return adoptRef(new IDBIndexBackendImpl(name, keyPath, unique));
+        return adoptRef(new IDBIndexBackendImpl(objectStore, id, name, keyPath, unique));
     }
     virtual ~IDBIndexBackendImpl();
 
@@ -46,8 +49,13 @@ public:
     virtual bool unique() { return m_unique; }
 
 private:
-    IDBIndexBackendImpl(const String& name, const String& keyPath, bool unique);
+    IDBIndexBackendImpl(IDBObjectStoreBackendImpl*, int64_t id, const String& name, const String& keyPath, bool unique);
+
+    SQLiteDatabase& sqliteDatabase() const;
+
+    RefPtr<IDBObjectStoreBackendImpl> m_objectStore;
 
+    int64_t m_id;
     String m_name;
     String m_keyPath;
     bool m_unique;
diff --git a/WebCore/storage/IDBObjectStoreBackendImpl.cpp b/WebCore/storage/IDBObjectStoreBackendImpl.cpp
index 9732bc1..b305a3c 100755
--- a/WebCore/storage/IDBObjectStoreBackendImpl.cpp
+++ b/WebCore/storage/IDBObjectStoreBackendImpl.cpp
@@ -30,10 +30,12 @@
 #include "IDBBindingUtilities.h"
 #include "IDBCallbacks.h"
 #include "IDBCursorBackendImpl.h"
+#include "IDBDatabaseBackendImpl.h"
 #include "IDBDatabaseException.h"
 #include "IDBIndexBackendImpl.h"
 #include "IDBKeyRange.h"
-#include "IDBKeyTree.h"
+#include "SQLiteDatabase.h"
+#include "SQLiteStatement.h"
 
 #if ENABLE(INDEXED_DATABASE)
 
@@ -43,12 +45,14 @@ IDBObjectStoreBackendImpl::~IDBObjectStoreBackendImpl()
 {
 }
 
-IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl(const String& name, const String& keyPath, bool autoIncrement)
-    : m_name(name)
+IDBObjectStoreBackendImpl::IDBObjectStoreBackendImpl(IDBDatabaseBackendImpl* database, int64_t id, const String& name, const String& keyPath, bool autoIncrement)
+    : m_database(database)
+    , m_id(id)
+    , m_name(name)
     , m_keyPath(keyPath)
     , m_autoIncrement(autoIncrement)
-    , m_tree(Tree::create())
 {
+    loadIndexes();
 }
 
 PassRefPtr<DOMStringList> IDBObjectStoreBackendImpl::indexNames() const
@@ -59,14 +63,65 @@ PassRefPtr<DOMStringList> IDBObjectStoreBackendImpl::indexNames() const
     return indexNames.release();
 }
 
+static String whereClause(IDBKey::Type type)
+{
+    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;
+}
+
+static void bindWhereClause(SQLiteStatement& query, int64_t id, IDBKey* key)
+{
+    query.bindInt64(1, id);
+    bindKey(query, 2, key);
+}
+
 void IDBObjectStoreBackendImpl::get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
 {
-    RefPtr<SerializedScriptValue> value = m_tree->get(key.get());
-    if (!value) {
+    SQLiteStatement query(sqliteDatabase(), "SELECT keyString, keyDate, keyNumber, value FROM ObjectStoreData " + whereClause(key->type()));
+    bool ok = query.prepare() == SQLResultOk;
+    ASSERT(ok); // FIXME: Better error handling?
+
+    bindWhereClause(query, m_id, key.get());
+    if (query.step() != SQLResultRow) {
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store."));
         return;
     }
-    callbacks->onSuccess(value.get());
+
+    ASSERT((key->type() == IDBKey::StringType) != query.isColumnNull(0));
+    // FIXME: Implement date.
+    ASSERT((key->type() == IDBKey::NumberType) != query.isColumnNull(2));
+
+    callbacks->onSuccess(SerializedScriptValue::createFromWire(query.getColumnText(3)));
+    ASSERT(query.step() != SQLResultRow);
 }
 
 void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> value, PassRefPtr<IDBKey> prpKey, bool addOnly, PassRefPtr<IDBCallbacks> callbacks)
@@ -88,18 +143,66 @@ void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> value, Pas
         return;
     }
 
-    if (addOnly && m_tree->get(key.get())) {
+    SQLiteStatement getQuery(sqliteDatabase(), "SELECT id FROM ObjectStoreData " + whereClause(key->type()));
+    bool ok = getQuery.prepare() == SQLResultOk;
+    ASSERT(ok); // FIXME: Better error handling?
+
+    bindWhereClause(getQuery, m_id, key.get());
+    bool existingValue = getQuery.step() == SQLResultRow;
+    if (addOnly && existingValue) {
         callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Key already exists in the object store."));
         return;
     }
 
-    m_tree->put(key.get(), value.get());
+    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(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);
+
+    ok = putQuery.step() == SQLResultDone;
+    ASSERT(ok); // FIXME: Better error handling?
+
     callbacks->onSuccess(key.get());
 }
 
 void IDBObjectStoreBackendImpl::remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
 {
-    m_tree->remove(key.get());
+    SQLiteStatement query(sqliteDatabase(), "DELETE FROM ObjectStoreData " + whereClause(key->type()));
+    bool ok = query.prepare() == SQLResultOk;
+    ASSERT(ok); // FIXME: Better error handling?
+
+    bindWhereClause(query, m_id, key.get());
+    if (query.step() != SQLResultDone) {
+        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store."));
+        return;
+    }
+
     callbacks->onSuccess();
 }
 
@@ -110,7 +213,18 @@ void IDBObjectStoreBackendImpl::createIndex(const String& name, const String& ke
         return;
     }
 
-    RefPtr<IDBIndexBackendInterface> index = IDBIndexBackendImpl::create(name, keyPath, unique);
+    SQLiteStatement insert(sqliteDatabase(), "INSERT INTO Indexes (objectStoreId, name, keyPath, isUnique) VALUES (?, ?, ?, ?)");
+    bool ok = insert.prepare() == SQLResultOk;
+    ASSERT(ok); // FIXME: Better error handling.
+    insert.bindInt64(1, m_id);
+    insert.bindText(2, name);
+    insert.bindText(3, keyPath);
+    insert.bindInt(4, static_cast<int>(unique));
+    ok = insert.step() == SQLResultDone;
+    ASSERT(ok); // FIXME: Better error handling.
+    int64_t id = sqliteDatabase().lastInsertRowID();
+
+    RefPtr<IDBIndexBackendInterface> index = IDBIndexBackendImpl::create(this, id, name, keyPath, unique);
     ASSERT(index->name() == name);
     m_indexes.set(name, index);
     callbacks->onSuccess(index.release());
@@ -128,19 +242,59 @@ void IDBObjectStoreBackendImpl::removeIndex(const String& name, PassRefPtr<IDBCa
         return;
     }
 
+    SQLiteStatement deleteQuery(sqliteDatabase(), "DELETE FROM Indexes WHERE name = ? AND objectStoreId = ?");
+    bool ok = deleteQuery.prepare() == SQLResultOk;
+    ASSERT(ok); // FIXME: Better error handling.
+    deleteQuery.bindText(1, name);
+    deleteQuery.bindInt64(2, m_id);
+    ok = deleteQuery.step() == SQLResultDone;
+    ASSERT(ok); // FIXME: Better error handling.
+
     m_indexes.remove(name);
     callbacks->onSuccess();
 }
 
 void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks> callbacks)
 {
+    // FIXME: Fully implement.
+
     RefPtr<IDBKey> key = range->left();
-    RefPtr<SerializedScriptValue> value = m_tree->get(key.get());
-    if (value) {
-        RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(this, range, static_cast<IDBCursor::Direction>(direction), key, value);
-        callbacks->onSuccess(cursor.release());
-    } else
-      callbacks->onSuccess();
+    SQLiteStatement query(sqliteDatabase(), "SELECT id, value FROM ObjectStoreData " + whereClause(key->type()));
+    bool ok = query.prepare() == SQLResultOk;
+    ASSERT(ok); // FIXME: Better error handling?
+
+    bindWhereClause(query, m_id, key.get());
+    if (query.step() != SQLResultRow) {
+        callbacks->onSuccess();
+        return;
+    }
+
+    RefPtr<SerializedScriptValue> value = SerializedScriptValue::createFromWire(query.getColumnText(1));
+    RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(this, range, static_cast<IDBCursor::Direction>(direction), key.release(), value.release());
+    callbacks->onSuccess(cursor.release());
+}
+
+void IDBObjectStoreBackendImpl::loadIndexes()
+{
+    SQLiteStatement indexQuery(sqliteDatabase(), "SELECT id, name, keyPath, isUnique FROM Indexes WHERE objectStoreId = ?");
+    bool ok = indexQuery.prepare() == SQLResultOk;
+    ASSERT(ok); // FIXME: Better error handling?
+
+    indexQuery.bindInt64(1, m_id);
+
+    while (indexQuery.step() == SQLResultRow) {
+        int64_t id = indexQuery.getColumnInt64(0);
+        String name = indexQuery.getColumnText(1);
+        String keyPath = indexQuery.getColumnText(2);
+        bool unique = !!indexQuery.getColumnInt(3);
+
+        m_indexes.set(name, IDBIndexBackendImpl::create(this, id, name, keyPath, unique));
+    }
+}
+
+SQLiteDatabase& IDBObjectStoreBackendImpl::sqliteDatabase() const 
+{
+    return m_database->sqliteDatabase();
 }
 
 } // namespace WebCore
diff --git a/WebCore/storage/IDBObjectStoreBackendImpl.h b/WebCore/storage/IDBObjectStoreBackendImpl.h
index 4b909af..02dcf04 100644
--- a/WebCore/storage/IDBObjectStoreBackendImpl.h
+++ b/WebCore/storage/IDBObjectStoreBackendImpl.h
@@ -34,13 +34,14 @@
 
 namespace WebCore {
 
-template <typename ValueType> class IDBKeyTree;
+class IDBDatabaseBackendImpl;
+class SQLiteDatabase;
 
 class IDBObjectStoreBackendImpl : public IDBObjectStoreBackendInterface {
 public:
-    static PassRefPtr<IDBObjectStoreBackendInterface> create(const String& name, const String& keyPath, bool autoIncrement)
+    static PassRefPtr<IDBObjectStoreBackendInterface> create(IDBDatabaseBackendImpl* database, int64_t id, const String& name, const String& keyPath, bool autoIncrement)
     {
-        return adoptRef(new IDBObjectStoreBackendImpl(name, keyPath, autoIncrement));
+        return adoptRef(new IDBObjectStoreBackendImpl(database, id, name, keyPath, autoIncrement));
     }
     ~IDBObjectStoreBackendImpl();
 
@@ -58,18 +59,23 @@ public:
 
     void openCursor(PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks>);
 
+    IDBDatabaseBackendImpl* database() const { return m_database.get(); }
+
 private:
-    IDBObjectStoreBackendImpl(const String& name, const String& keyPath, bool autoIncrement);
+    IDBObjectStoreBackendImpl(IDBDatabaseBackendImpl*, int64_t id, const String& name, const String& keyPath, bool autoIncrement);
+
+    void loadIndexes();
+    SQLiteDatabase& sqliteDatabase() const;
 
+    RefPtr<IDBDatabaseBackendImpl> m_database;
+
+    int64_t m_id;
     String m_name;
     String m_keyPath;
     bool m_autoIncrement;
 
     typedef HashMap<String, RefPtr<IDBIndexBackendInterface> > IndexMap;
     IndexMap m_indexes;
-
-    typedef IDBKeyTree<SerializedScriptValue> Tree;
-    RefPtr<Tree> m_tree;
 };
 
 } // namespace WebCore

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list