[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