summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/storage/IDBDatabaseBackendImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/storage/IDBDatabaseBackendImpl.cpp')
-rw-r--r--Source/WebCore/storage/IDBDatabaseBackendImpl.cpp179
1 files changed, 81 insertions, 98 deletions
diff --git a/Source/WebCore/storage/IDBDatabaseBackendImpl.cpp b/Source/WebCore/storage/IDBDatabaseBackendImpl.cpp
index 133c5ae..94e305b 100644
--- a/Source/WebCore/storage/IDBDatabaseBackendImpl.cpp
+++ b/Source/WebCore/storage/IDBDatabaseBackendImpl.cpp
@@ -30,65 +30,39 @@
#include "CrossThreadTask.h"
#include "DOMStringList.h"
+#include "IDBBackingStore.h"
#include "IDBDatabaseException.h"
#include "IDBFactoryBackendImpl.h"
#include "IDBObjectStoreBackendImpl.h"
-#include "IDBSQLiteDatabase.h"
#include "IDBTransactionBackendImpl.h"
#include "IDBTransactionCoordinator.h"
-#include "SQLiteStatement.h"
-#include "SQLiteTransaction.h"
namespace WebCore {
-static bool extractMetaData(SQLiteDatabase& sqliteDatabase, const String& name, String& foundVersion, int64& foundId)
-{
- SQLiteStatement databaseQuery(sqliteDatabase, "SELECT id, version FROM Databases WHERE name = ?");
- if (databaseQuery.prepare() != SQLResultOk) {
- ASSERT_NOT_REACHED();
- return false;
+class IDBDatabaseBackendImpl::PendingSetVersionCall : public RefCounted<PendingSetVersionCall> {
+public:
+ static PassRefPtr<PendingSetVersionCall> create(const String& version, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks)
+ {
+ return adoptRef(new PendingSetVersionCall(version, callbacks, databaseCallbacks));
}
- databaseQuery.bindText(1, name);
- if (databaseQuery.step() != SQLResultRow)
- return false;
-
- foundId = databaseQuery.getColumnInt64(0);
- foundVersion = databaseQuery.getColumnText(1);
-
- if (databaseQuery.step() == SQLResultRow)
- ASSERT_NOT_REACHED();
- return true;
-}
-
-static bool setMetaData(SQLiteDatabase& sqliteDatabase, const String& name, const String& version, int64_t& rowId)
-{
- ASSERT(!name.isNull());
- ASSERT(!version.isNull());
-
- String sql = rowId != IDBDatabaseBackendImpl::InvalidId ? "UPDATE Databases SET name = ?, version = ? WHERE id = ?"
- : "INSERT INTO Databases (name, description, version) VALUES (?, '', ?)";
- SQLiteStatement query(sqliteDatabase, sql);
- if (query.prepare() != SQLResultOk) {
- ASSERT_NOT_REACHED();
- return false;
+ String version() { return m_version; }
+ PassRefPtr<IDBCallbacks> callbacks() { return m_callbacks; }
+ PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks() { return m_databaseCallbacks; }
+
+private:
+ PendingSetVersionCall(const String& version, PassRefPtr<IDBCallbacks> callbacks, PassRefPtr<IDBDatabaseCallbacks> databaseCallbacks)
+ : m_version(version)
+ , m_callbacks(callbacks)
+ , m_databaseCallbacks(databaseCallbacks)
+ {
}
+ String m_version;
+ RefPtr<IDBCallbacks> m_callbacks;
+ RefPtr<IDBDatabaseCallbacks> m_databaseCallbacks;
+};
- query.bindText(1, name);
- query.bindText(2, version);
- if (rowId != IDBDatabaseBackendImpl::InvalidId)
- query.bindInt64(3, rowId);
-
- if (query.step() != SQLResultDone)
- return false;
-
- if (rowId == IDBDatabaseBackendImpl::InvalidId)
- rowId = sqliteDatabase.lastInsertRowID();
-
- return true;
-}
-
-IDBDatabaseBackendImpl::IDBDatabaseBackendImpl(const String& name, IDBSQLiteDatabase* sqliteDatabase, IDBTransactionCoordinator* coordinator, IDBFactoryBackendImpl* factory, const String& uniqueIdentifier)
- : m_sqliteDatabase(sqliteDatabase)
+IDBDatabaseBackendImpl::IDBDatabaseBackendImpl(const String& name, IDBBackingStore* backingStore, IDBTransactionCoordinator* coordinator, IDBFactoryBackendImpl* factory, const String& uniqueIdentifier)
+ : m_backingStore(backingStore)
, m_id(InvalidId)
, m_name(name)
, m_version("")
@@ -98,9 +72,9 @@ IDBDatabaseBackendImpl::IDBDatabaseBackendImpl(const String& name, IDBSQLiteData
{
ASSERT(!m_name.isNull());
- bool success = extractMetaData(m_sqliteDatabase->db(), m_name, m_version, m_id);
+ bool success = m_backingStore->extractIDBDatabaseMetaData(m_name, m_version, m_id);
ASSERT_UNUSED(success, success == (m_id != InvalidId));
- if (!setMetaData(m_sqliteDatabase->db(), m_name, m_version, m_id))
+ if (!m_backingStore->setIDBDatabaseMetaData(m_name, m_version, m_id, m_id == InvalidId))
ASSERT_NOT_REACHED(); // FIXME: Need better error handling.
loadObjectStores();
}
@@ -110,9 +84,9 @@ IDBDatabaseBackendImpl::~IDBDatabaseBackendImpl()
m_factory->removeIDBDatabaseBackend(m_identifier);
}
-SQLiteDatabase& IDBDatabaseBackendImpl::sqliteDatabase() const
+PassRefPtr<IDBBackingStore> IDBDatabaseBackendImpl::backingStore() const
{
- return m_sqliteDatabase->db();
+ return m_backingStore;
}
PassRefPtr<DOMStringList> IDBDatabaseBackendImpl::objectStoreNames() const
@@ -132,7 +106,7 @@ PassRefPtr<IDBObjectStoreBackendInterface> IDBDatabaseBackendImpl::createObject
return 0;
}
- RefPtr<IDBObjectStoreBackendImpl> objectStore = IDBObjectStoreBackendImpl::create(m_sqliteDatabase.get(), name, keyPath, autoIncrement);
+ RefPtr<IDBObjectStoreBackendImpl> objectStore = IDBObjectStoreBackendImpl::create(m_backingStore.get(), name, keyPath, autoIncrement);
ASSERT(objectStore->name() == name);
RefPtr<IDBDatabaseBackendImpl> database = this;
@@ -149,21 +123,14 @@ PassRefPtr<IDBObjectStoreBackendInterface> IDBDatabaseBackendImpl::createObject
void IDBDatabaseBackendImpl::createObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBTransactionBackendInterface> transaction)
{
- SQLiteStatement insert(database->sqliteDatabase(), "INSERT INTO ObjectStores (name, keyPath, doAutoIncrement, databaseId) VALUES (?, ?, ?, ?)");
- if (insert.prepare() != SQLResultOk) {
- transaction->abort();
- return;
- }
- insert.bindText(1, objectStore->name());
- insert.bindText(2, objectStore->keyPath());
- insert.bindInt(3, static_cast<int>(objectStore->autoIncrement()));
- insert.bindInt64(4, database->id());
- if (insert.step() != SQLResultDone) {
+ int64_t objectStoreId;
+
+ if (!database->m_backingStore->createObjectStore(objectStore->name(), objectStore->keyPath(), objectStore->autoIncrement(), database->id(), objectStoreId)) {
transaction->abort();
return;
}
- int64_t id = database->sqliteDatabase().lastInsertRowID();
- objectStore->setId(id);
+
+ objectStore->setId(objectStoreId);
transaction->didCompleteTaskEvents();
}
@@ -172,16 +139,6 @@ PassRefPtr<IDBObjectStoreBackendInterface> IDBDatabaseBackendImpl::objectStore(c
return m_objectStores.get(name);
}
-static void doDelete(SQLiteDatabase& db, const char* sql, int64_t id)
-{
- SQLiteStatement deleteQuery(db, sql);
- bool ok = deleteQuery.prepare() == SQLResultOk;
- ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
- deleteQuery.bindInt64(1, id);
- ok = deleteQuery.step() == SQLResultDone;
- ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
-}
-
void IDBDatabaseBackendImpl::deleteObjectStore(const String& name, IDBTransactionBackendInterface* transactionPtr, ExceptionCode& ec)
{
RefPtr<IDBObjectStoreBackendImpl> objectStore = m_objectStores.get(name);
@@ -201,19 +158,31 @@ void IDBDatabaseBackendImpl::deleteObjectStore(const String& name, IDBTransactio
void IDBDatabaseBackendImpl::deleteObjectStoreInternal(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, PassRefPtr<IDBObjectStoreBackendImpl> objectStore, PassRefPtr<IDBTransactionBackendInterface> transaction)
{
- doDelete(database->sqliteDatabase(), "DELETE FROM ObjectStores WHERE id = ?", objectStore->id());
- doDelete(database->sqliteDatabase(), "DELETE FROM ObjectStoreData WHERE objectStoreId = ?", objectStore->id());
- doDelete(database->sqliteDatabase(), "DELETE FROM IndexData WHERE indexId IN (SELECT id FROM Indexes WHERE objectStoreId = ?)", objectStore->id());
- doDelete(database->sqliteDatabase(), "DELETE FROM Indexes WHERE objectStoreId = ?", objectStore->id());
-
+ database->m_backingStore->deleteObjectStore(objectStore->id());
transaction->didCompleteTaskEvents();
}
-void IDBDatabaseBackendImpl::setVersion(const String& version, PassRefPtr<IDBCallbacks> prpCallbacks, ExceptionCode& ec)
+void IDBDatabaseBackendImpl::setVersion(const String& version, PassRefPtr<IDBCallbacks> prpCallbacks, PassRefPtr<IDBDatabaseCallbacks> prpDatabaseCallbacks, ExceptionCode& ec)
{
- RefPtr<IDBDatabaseBackendImpl> database = this;
RefPtr<IDBCallbacks> callbacks = prpCallbacks;
+ RefPtr<IDBDatabaseCallbacks> databaseCallbacks = prpDatabaseCallbacks;
+ if (!m_databaseCallbacksSet.contains(databaseCallbacks)) {
+ callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::ABORT_ERR, "Connection was closed before set version transaction was created"));
+ return;
+ }
+ for (DatabaseCallbacksSet::const_iterator it = m_databaseCallbacksSet.begin(); it != m_databaseCallbacksSet.end(); ++it) {
+ if (*it != databaseCallbacks)
+ (*it)->onVersionChange(version);
+ }
+ if (m_databaseCallbacksSet.size() > 1) {
+ callbacks->onBlocked();
+ RefPtr<PendingSetVersionCall> pendingSetVersionCall = PendingSetVersionCall::create(version, callbacks, databaseCallbacks);
+ m_pendingSetVersionCalls.append(pendingSetVersionCall);
+ return;
+ }
+
RefPtr<DOMStringList> objectStoreNames = DOMStringList::create();
+ RefPtr<IDBDatabaseBackendImpl> database = this;
RefPtr<IDBTransactionBackendInterface> transaction = IDBTransactionBackendImpl::create(objectStoreNames.get(), IDBTransaction::VERSION_CHANGE, this);
if (!transaction->scheduleTask(createCallbackTask(&IDBDatabaseBackendImpl::setVersionInternal, database, version, callbacks, transaction),
createCallbackTask(&IDBDatabaseBackendImpl::resetVersion, database, m_version))) {
@@ -225,7 +194,7 @@ void IDBDatabaseBackendImpl::setVersionInternal(ScriptExecutionContext*, PassRef
{
int64_t databaseId = database->id();
database->m_version = version;
- if (!setMetaData(database->m_sqliteDatabase->db(), database->m_name, database->m_version, databaseId)) {
+ if (!database->m_backingStore->setIDBDatabaseMetaData(database->m_name, database->m_version, databaseId, databaseId == InvalidId)) {
// FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
transaction->abort();
@@ -247,29 +216,43 @@ PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::transaction(D
return IDBTransactionBackendImpl::create(objectStoreNames, mode, this);
}
-void IDBDatabaseBackendImpl::close()
+void IDBDatabaseBackendImpl::open(PassRefPtr<IDBDatabaseCallbacks> callbacks)
{
- // FIXME: Implement.
+ m_databaseCallbacksSet.add(RefPtr<IDBDatabaseCallbacks>(callbacks));
}
-void IDBDatabaseBackendImpl::loadObjectStores()
+void IDBDatabaseBackendImpl::close(PassRefPtr<IDBDatabaseCallbacks> prpCallbacks)
{
- SQLiteStatement objectStoresQuery(sqliteDatabase(), "SELECT id, name, keyPath, doAutoIncrement FROM ObjectStores WHERE databaseId = ?");
- bool ok = objectStoresQuery.prepare() == SQLResultOk;
- ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
-
- objectStoresQuery.bindInt64(1, m_id);
-
- 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);
+ RefPtr<IDBDatabaseCallbacks> callbacks = prpCallbacks;
+ ASSERT(m_databaseCallbacksSet.contains(callbacks));
+ m_databaseCallbacksSet.remove(callbacks);
+ if (m_databaseCallbacksSet.size() > 1)
+ return;
- m_objectStores.set(name, IDBObjectStoreBackendImpl::create(m_sqliteDatabase.get(), id, name, keyPath, autoIncrement));
+ while (!m_pendingSetVersionCalls.isEmpty()) {
+ ExceptionCode ec = 0;
+ RefPtr<PendingSetVersionCall> pendingSetVersionCall = m_pendingSetVersionCalls.takeFirst();
+ setVersion(pendingSetVersionCall->version(), pendingSetVersionCall->callbacks(), pendingSetVersionCall->databaseCallbacks(), ec);
+ ASSERT(!ec);
}
}
+void IDBDatabaseBackendImpl::loadObjectStores()
+{
+ Vector<int64_t> ids;
+ Vector<String> names;
+ Vector<String> keyPaths;
+ Vector<bool> autoIncrementFlags;
+ m_backingStore->getObjectStores(m_id, ids, names, keyPaths, autoIncrementFlags);
+
+ ASSERT(names.size() == ids.size());
+ ASSERT(keyPaths.size() == ids.size());
+ ASSERT(autoIncrementFlags.size() == ids.size());
+
+ for (size_t i = 0; i < ids.size(); i++)
+ m_objectStores.set(names[i], IDBObjectStoreBackendImpl::create(m_backingStore.get(), ids[i], names[i], keyPaths[i], autoIncrementFlags[i]));
+}
+
void IDBDatabaseBackendImpl::removeObjectStoreFromMap(ScriptExecutionContext*, PassRefPtr<IDBDatabaseBackendImpl> database, PassRefPtr<IDBObjectStoreBackendImpl> objectStore)
{
ASSERT(database->m_objectStores.contains(objectStore->name()));