IDB: Implement IDBObjectStore.count()
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Jan 2014 23:58:30 +0000 (23:58 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Jan 2014 23:58:30 +0000 (23:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=127888

Reviewed by Tim Horton.

Now count() actually works.

Forward the count() request to the backing store”
* DatabaseProcess/IndexedDB/UniqueIDBDatabase.cpp:
(WebKit::UniqueIDBDatabase::countInBackingStore):

Using a cursor, get a count:
* DatabaseProcess/IndexedDB/UniqueIDBDatabaseBackingStore.h:
* DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp:
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::count):
* DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h:

Give a direct accessor to allow the backing store to close a cursor it opened
for its own use:
* DatabaseProcess/IndexedDB/sqlite/SQLiteIDBTransaction.cpp:
(WebKit::SQLiteIDBTransaction::closeCursor):
* DatabaseProcess/IndexedDB/sqlite/SQLiteIDBTransaction.h:

* WebProcess/Databases/IndexedDB/WebIDBServerConnection.cpp:
(WebKit::WebIDBServerConnection::didCount): Update the logging to show the count.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@163131 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit2/ChangeLog
Source/WebKit2/DatabaseProcess/IndexedDB/UniqueIDBDatabase.cpp
Source/WebKit2/DatabaseProcess/IndexedDB/UniqueIDBDatabaseBackingStore.h
Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/SQLiteIDBTransaction.cpp
Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/SQLiteIDBTransaction.h
Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp
Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h
Source/WebKit2/WebProcess/Databases/IndexedDB/WebIDBServerConnection.cpp

index 1cb09b3..710294d 100644 (file)
@@ -1,3 +1,31 @@
+2014-01-30  Brady Eidson  <beidson@apple.com>
+
+        IDB: Implement IDBObjectStore.count()
+        https://bugs.webkit.org/show_bug.cgi?id=127888
+
+        Reviewed by Tim Horton.
+
+        Now count() actually works.
+
+        Forward the count() request to the backing store”
+        * DatabaseProcess/IndexedDB/UniqueIDBDatabase.cpp:
+        (WebKit::UniqueIDBDatabase::countInBackingStore):
+
+        Using a cursor, get a count:
+        * DatabaseProcess/IndexedDB/UniqueIDBDatabaseBackingStore.h:
+        * DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp:
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::count):
+        * DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h:
+
+        Give a direct accessor to allow the backing store to close a cursor it opened
+        for its own use:
+        * DatabaseProcess/IndexedDB/sqlite/SQLiteIDBTransaction.cpp:
+        (WebKit::SQLiteIDBTransaction::closeCursor):
+        * DatabaseProcess/IndexedDB/sqlite/SQLiteIDBTransaction.h:
+
+        * WebProcess/Databases/IndexedDB/WebIDBServerConnection.cpp:
+        (WebKit::WebIDBServerConnection::didCount): Update the logging to show the count.
+
 2014-01-30  Anders Carlsson  <andersca@apple.com>
 
         Implement NavigationState::PolicyClient::decidePolicyForNewWindowAction
index 8f37a2f..3f91094 100644 (file)
@@ -952,11 +952,16 @@ void UniqueIDBDatabase::didIterateCursorInBackingStore(uint64_t requestID, const
     request->completeRequest(key, primaryKey, SharedBuffer::create(value.data(), value.size()), errorCode, errorMessage);
 }
 
-void UniqueIDBDatabase::countInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const IDBKeyRangeData&)
+void UniqueIDBDatabase::countInBackingStore(uint64_t requestID, const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const IDBKeyRangeData& keyRangeData)
 {
-    // FIXME: Implement
+    int64_t count;
+
+    if (!m_backingStore->count(transactionIdentifier, objectStoreID, indexID, keyRangeData, count)) {
+        LOG_ERROR("Failed to get count from backing store.");
+        postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCountInBackingStore, requestID, 0, IDBDatabaseException::UnknownError, ASCIILiteral("Failed to get count from backing store")));
+    }
 
-    postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCountInBackingStore, requestID, 0, IDBDatabaseException::UnknownError, ASCIILiteral("counting in backing store not supported yet")));
+    postMainThreadTask(createAsyncTask(*this, &UniqueIDBDatabase::didCountInBackingStore, requestID, count, 0, String(StringImpl::empty())));
 }
 
 void UniqueIDBDatabase::didCountInBackingStore(uint64_t requestID, int64_t count, uint32_t errorCode, const String& errorMessage)
index 084ad86..631e1a8 100644 (file)
@@ -71,6 +71,7 @@ public:
 
     virtual bool getKeyRecordFromObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const WebCore::IDBKey&, RefPtr<WebCore::SharedBuffer>& result) = 0;
     virtual bool getKeyRangeRecordFromObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const WebCore::IDBKeyRange&, RefPtr<WebCore::SharedBuffer>& result, RefPtr<WebCore::IDBKey>& resultKey) = 0;
+    virtual bool count(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const WebCore::IDBKeyRangeData&, int64_t& count) = 0;
 
     virtual bool openCursor(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, WebCore::IndexedDB::CursorDirection, WebCore::IndexedDB::CursorType, WebCore::IDBDatabaseBackend::TaskType, const WebCore::IDBKeyRangeData&, int64_t& cursorID) = 0;
     virtual bool advanceCursor(const IDBIdentifier& cursorIdentifier, uint64_t count, WebCore::IDBKeyData&, WebCore::IDBKeyData&, Vector<char>&) = 0;
index d9da196..13b84f3 100644 (file)
@@ -114,6 +114,14 @@ SQLiteIDBCursor* SQLiteIDBTransaction::openCursor(int64_t objectStoreID, int64_t
     return addResult.iterator->value.get();
 }
 
+void SQLiteIDBTransaction::closeCursor(SQLiteIDBCursor& cursor)
+{
+    ASSERT(m_cursors.contains(cursor.identifier()));
+
+    m_backingStore.unregisterCursor(&cursor);
+    m_cursors.remove(cursor.identifier());
+}
+
 void SQLiteIDBTransaction::clearCursors()
 {
     // Iterate over the keys instead of each key/value pair because std::unique_ptr<> can't be iterated over directly.
index df1bf16..6538443 100644 (file)
@@ -72,6 +72,8 @@ public:
 
     SQLiteIDBCursor* openCursor(int64_t objectStoreID, int64_t indexID, WebCore::IndexedDB::CursorDirection, WebCore::IndexedDB::CursorType, WebCore::IDBDatabaseBackend::TaskType, const WebCore::IDBKeyRangeData&);
 
+    void closeCursor(SQLiteIDBCursor&);
+
     WebCore::IndexedDB::TransactionMode mode() const { return m_mode; }
     bool inProgress() const;
 
index 79c5c2f..673f9b2 100644 (file)
@@ -798,6 +798,36 @@ bool UniqueIDBDatabaseBackingStoreSQLite::getKeyRangeRecordFromObjectStore(const
     return true;
 }
 
+bool UniqueIDBDatabaseBackingStoreSQLite::count(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const IDBKeyRangeData& keyRangeData, int64_t& count)
+{
+    ASSERT(!isMainThread());
+    ASSERT(m_sqliteDB);
+    ASSERT(m_sqliteDB->isOpen());
+
+    SQLiteIDBTransaction* transaction = m_transactions.get(transactionIdentifier);
+    if (!transaction || !transaction->inProgress()) {
+        LOG_ERROR("Attempt to get count from database without an established, in-progress transaction");
+        return false;
+    }
+
+    SQLiteIDBCursor* cursor = transaction->openCursor(objectStoreID, indexID, IndexedDB::CursorDirection::Next, IndexedDB::CursorType::KeyOnly, IDBDatabaseBackend::NormalTask, keyRangeData);
+
+    if (!cursor) {
+        LOG_ERROR("Cannot open cursor to get count in database");
+        return false;
+    }
+
+    m_cursors.set(cursor->identifier(), cursor);
+
+    count = 0;
+    while (cursor->advance(1))
+        ++count;
+
+    transaction->closeCursor(*cursor);
+
+    return true;
+}
+
 bool UniqueIDBDatabaseBackingStoreSQLite::openCursor(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, IndexedDB::CursorDirection cursorDirection, IndexedDB::CursorType cursorType, IDBDatabaseBackend::TaskType taskType, const IDBKeyRangeData& keyRange, int64_t& cursorID)
 {
     ASSERT(!isMainThread());
index 13e0413..2ffbe48 100644 (file)
@@ -76,6 +76,7 @@ public:
 
     virtual bool getKeyRecordFromObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const WebCore::IDBKey&, RefPtr<WebCore::SharedBuffer>& result) override;
     virtual bool getKeyRangeRecordFromObjectStore(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, const WebCore::IDBKeyRange&, RefPtr<WebCore::SharedBuffer>& result, RefPtr<WebCore::IDBKey>& resultKey) override;
+    virtual bool count(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, const WebCore::IDBKeyRangeData&, int64_t& count) override;
 
     virtual bool openCursor(const IDBIdentifier& transactionIdentifier, int64_t objectStoreID, int64_t indexID, WebCore::IndexedDB::CursorDirection, WebCore::IndexedDB::CursorType, WebCore::IDBDatabaseBackend::TaskType, const WebCore::IDBKeyRangeData&, int64_t& cursorID) override;
     virtual bool advanceCursor(const IDBIdentifier& cursorIdentifier, uint64_t count, WebCore::IDBKeyData&, WebCore::IDBKeyData&, Vector<char>&) override;
index 89c5465..aedd690 100644 (file)
@@ -501,7 +501,7 @@ void WebIDBServerConnection::count(IDBTransactionBackend& transaction, const Cou
 
 void WebIDBServerConnection::didCount(uint64_t requestID, int64_t count, uint32_t errorCode, const String& errorMessage)
 {
-    LOG(IDB, "WebProcess didCount request ID %llu (error - %s)", requestID, errorMessage.utf8().data());
+    LOG(IDB, "WebProcess didCount %lli request ID %llu (error - %s)", count, requestID, errorMessage.utf8().data());
 
     RefPtr<AsyncRequest> serverRequest = m_serverRequests.take(requestID);