Changeset 128217 in webkit


Ignore:
Timestamp:
Sep 11, 2012 12:17:20 PM (12 years ago)
Author:
jsbell@chromium.org
Message:

IndexedDB: IDBObjectStore.count() is slow
https://bugs.webkit.org/show_bug.cgi?id=96033

Reviewed by Tony Chang.

Avoid decoding record values when performing count() iteration, and factor out common code
used for initializing object store and index cursors. Also, remove unused indexDataId()
methods (which date back to the SQLite backing store), and rename some p's and q's.

No new tests - no functional changes. Covered by existing test:

LayoutTests/storage/indexeddb/objectstore-count.html

  • Modules/indexeddb/IDBBackingStore.h: Expose new (internal) ObjectStoreKeyCursor

(IDBBackingStore):

  • Modules/indexeddb/IDBLevelDBBackingStore.cpp:

(WebCore): Factor out common CursorOptions initialization code. The objectStoreCursorOptions()
function is needed for this patch. The indexCursorOptions() function is not, but eliminates
duplicated code and is a nearly identical refactor.
(WebCore::IDBLevelDBBackingStore::openObjectStoreCursor): Refactor.
(WebCore::IDBLevelDBBackingStore::openObjectStoreKeyCursor): Implement.
(WebCore::IDBLevelDBBackingStore::openIndexKeyCursor): Refactor.
(WebCore::IDBLevelDBBackingStore::openIndexCursor): Ditto.

  • Modules/indexeddb/IDBLevelDBBackingStore.h:

(IDBLevelDBBackingStore):

  • Modules/indexeddb/IDBObjectStoreBackendImpl.cpp:

(WebCore::IDBObjectStoreBackendImpl::countInternal): Use ObjectStoreKeyCursor for iteration.

Location:
trunk/Source
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r128215 r128217  
     12012-09-11  Joshua Bell  <jsbell@chromium.org>
     2
     3        IndexedDB: IDBObjectStore.count() is slow
     4        https://bugs.webkit.org/show_bug.cgi?id=96033
     5
     6        Reviewed by Tony Chang.
     7
     8        Avoid decoding record values when performing count() iteration, and factor out common code
     9        used for initializing object store and index cursors. Also, remove unused indexDataId()
     10        methods (which date back to the SQLite backing store), and rename some p's and q's.
     11
     12        No new tests - no functional changes. Covered by existing test:
     13            LayoutTests/storage/indexeddb/objectstore-count.html
     14
     15        * Modules/indexeddb/IDBBackingStore.h: Expose new (internal) ObjectStoreKeyCursor
     16        (IDBBackingStore):
     17        * Modules/indexeddb/IDBLevelDBBackingStore.cpp:
     18        (WebCore): Factor out common CursorOptions initialization code. The objectStoreCursorOptions()
     19        function is needed for this patch. The indexCursorOptions() function is not, but eliminates
     20        duplicated code and is a nearly identical refactor.
     21        (WebCore::IDBLevelDBBackingStore::openObjectStoreCursor): Refactor.
     22        (WebCore::IDBLevelDBBackingStore::openObjectStoreKeyCursor): Implement.
     23        (WebCore::IDBLevelDBBackingStore::openIndexKeyCursor): Refactor.
     24        (WebCore::IDBLevelDBBackingStore::openIndexCursor): Ditto.
     25        * Modules/indexeddb/IDBLevelDBBackingStore.h:
     26        (IDBLevelDBBackingStore):
     27        * Modules/indexeddb/IDBObjectStoreBackendImpl.cpp:
     28        (WebCore::IDBObjectStoreBackendImpl::countInternal): Use ObjectStoreKeyCursor for iteration.
     29
    1302012-09-11  Ojan Vafai  <ojan@chromium.org>
    231
  • trunk/Source/WebCore/Modules/indexeddb/IDBBackingStore.h

    r124675 r128217  
    102102        virtual String value() = 0;
    103103        virtual PassRefPtr<ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() = 0;
    104         virtual int64_t indexDataId() = 0;
    105104        virtual void close() = 0;
    106105        virtual ~Cursor() { };
     
    108107
    109108    virtual PassRefPtr<Cursor> openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction) = 0;
     109    virtual PassRefPtr<Cursor> openObjectStoreKeyCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction) = 0;
    110110    virtual PassRefPtr<Cursor> openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange*, IDBCursor::Direction) = 0;
    111111    virtual PassRefPtr<Cursor> openIndexCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange*, IDBCursor::Direction) = 0;
  • trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.cpp

    r128136 r128217  
    11401140    virtual String value() = 0;
    11411141    virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() = 0;
    1142     virtual int64_t indexDataId() = 0;
    11431142    virtual void close() { }
    11441143
     
    13181317}
    13191318
     1319class ObjectStoreKeyCursorImpl : public CursorImplCommon {
     1320public:
     1321    static PassRefPtr<ObjectStoreKeyCursorImpl> create(LevelDBTransaction* transaction, const CursorOptions& cursorOptions)
     1322    {
     1323        return adoptRef(new ObjectStoreKeyCursorImpl(transaction, cursorOptions));
     1324    }
     1325
     1326    virtual PassRefPtr<IDBBackingStore::Cursor> clone()
     1327    {
     1328        return adoptRef(new ObjectStoreKeyCursorImpl(this));
     1329    }
     1330
     1331    // CursorImplCommon
     1332    virtual String value() { ASSERT_NOT_REACHED(); return String(); }
     1333    virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() OVERRIDE
     1334    {
     1335        return m_identifier;
     1336    }
     1337    virtual bool loadCurrentRow();
     1338
     1339private:
     1340    ObjectStoreKeyCursorImpl(LevelDBTransaction* transaction, const CursorOptions& cursorOptions)
     1341        : CursorImplCommon(transaction, cursorOptions)
     1342    {
     1343    }
     1344
     1345    ObjectStoreKeyCursorImpl(const ObjectStoreKeyCursorImpl* other)
     1346        : CursorImplCommon(other)
     1347    {
     1348    }
     1349
     1350    RefPtr<LevelDBRecordIdentifier> m_identifier;
     1351};
     1352
     1353bool ObjectStoreKeyCursorImpl::loadCurrentRow()
     1354{
     1355    const char* keyPosition = m_iterator->key().begin();
     1356    const char* keyLimit = m_iterator->key().end();
     1357
     1358    ObjectStoreDataKey objectStoreDataKey;
     1359    keyPosition = ObjectStoreDataKey::decode(keyPosition, keyLimit, &objectStoreDataKey);
     1360    ASSERT(keyPosition);
     1361    if (!keyPosition)
     1362        return false;
     1363
     1364    m_currentKey = objectStoreDataKey.userKey();
     1365
     1366    int64_t version;
     1367    const char* valuePosition = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), version);
     1368    ASSERT(valuePosition);
     1369    if (!valuePosition)
     1370        return false;
     1371
     1372    // FIXME: This re-encodes what was just decoded; try and optimize.
     1373    m_identifier = LevelDBRecordIdentifier::create(encodeIDBKey(*m_currentKey), version);
     1374
     1375    return true;
     1376}
     1377
    13201378class ObjectStoreCursorImpl : public CursorImplCommon {
    13211379public:
     
    13361394        return m_identifier;
    13371395    }
    1338     virtual int64_t indexDataId() { ASSERT_NOT_REACHED(); return 0; }
    13391396    virtual bool loadCurrentRow();
    13401397
     
    13571414bool ObjectStoreCursorImpl::loadCurrentRow()
    13581415{
    1359     const char* p = m_iterator->key().begin();
     1416    const char* keyPosition = m_iterator->key().begin();
    13601417    const char* keyLimit = m_iterator->key().end();
    13611418
    13621419    ObjectStoreDataKey objectStoreDataKey;
    1363     p = ObjectStoreDataKey::decode(p, keyLimit, &objectStoreDataKey);
    1364     ASSERT(p);
    1365     if (!p)
     1420    keyPosition = ObjectStoreDataKey::decode(keyPosition, keyLimit, &objectStoreDataKey);
     1421    ASSERT(keyPosition);
     1422    if (!keyPosition)
    13661423        return false;
    13671424
     
    13691426
    13701427    int64_t version;
    1371     const char* q = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), version);
    1372     ASSERT(q);
    1373     if (!q)
     1428    const char* valuePosition = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), version);
     1429    ASSERT(valuePosition);
     1430    if (!valuePosition)
    13741431        return false;
    13751432
     
    13771434    m_identifier = LevelDBRecordIdentifier::create(encodeIDBKey(*m_currentKey), version);
    13781435
    1379     m_currentValue = decodeString(q, m_iterator->value().end());
     1436    m_currentValue = decodeString(valuePosition, m_iterator->value().end());
    13801437
    13811438    return true;
     
    13981455    virtual PassRefPtr<IDBKey> primaryKey() { return m_primaryKey; }
    13991456    virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() { ASSERT_NOT_REACHED(); return 0; }
    1400     virtual int64_t indexDataId() { ASSERT_NOT_REACHED(); return 0; }
    14011457    virtual bool loadCurrentRow();
    14021458
     
    14181474bool IndexKeyCursorImpl::loadCurrentRow()
    14191475{
    1420     const char* p = m_iterator->key().begin();
     1476    const char* keyPosition = m_iterator->key().begin();
    14211477    const char* keyLimit = m_iterator->key().end();
     1478
    14221479    IndexDataKey indexDataKey;
    1423     p = IndexDataKey::decode(p, keyLimit, &indexDataKey);
     1480    keyPosition = IndexDataKey::decode(keyPosition, keyLimit, &indexDataKey);
    14241481
    14251482    m_currentKey = indexDataKey.userKey();
    14261483
    14271484    int64_t indexDataVersion;
    1428     const char* q = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), indexDataVersion);
    1429     ASSERT(q);
    1430     if (!q)
    1431         return false;
    1432 
    1433     q = decodeIDBKey(q, m_iterator->value().end(), m_primaryKey);
    1434     ASSERT(q);
    1435     if (!q)
     1485    const char* valuePosition = decodeVarInt(m_iterator->value().begin(), m_iterator->value().end(), indexDataVersion);
     1486    ASSERT(valuePosition);
     1487    if (!valuePosition)
     1488        return false;
     1489
     1490    valuePosition = decodeIDBKey(valuePosition, m_iterator->value().end(), m_primaryKey);
     1491    ASSERT(valuePosition);
     1492    if (!valuePosition)
    14361493        return false;
    14371494
     
    14741531    virtual PassRefPtr<IDBKey> primaryKey() { return m_primaryKey; }
    14751532    virtual PassRefPtr<IDBBackingStore::ObjectStoreRecordIdentifier> objectStoreRecordIdentifier() { ASSERT_NOT_REACHED(); return 0; }
    1476     virtual int64_t indexDataId() { ASSERT_NOT_REACHED(); return 0; }
    14771533    bool loadCurrentRow();
    14781534
     
    14981554bool IndexCursorImpl::loadCurrentRow()
    14991555{
    1500     const char* p = m_iterator->key().begin();
    1501     const char* limit = m_iterator->key().end();
     1556    const char* keyPosition = m_iterator->key().begin();
     1557    const char* keyLimit = m_iterator->key().end();
    15021558
    15031559    IndexDataKey indexDataKey;
    1504     p = IndexDataKey::decode(p, limit, &indexDataKey);
     1560    keyPosition = IndexDataKey::decode(keyPosition, keyLimit, &indexDataKey);
    15051561
    15061562    m_currentKey = indexDataKey.userKey();
    15071563
    1508     const char* q = m_iterator->value().begin();
     1564    const char* valuePosition = m_iterator->value().begin();
    15091565    const char* valueLimit = m_iterator->value().end();
    15101566
    15111567    int64_t indexDataVersion;
    1512     q = decodeVarInt(q, valueLimit, indexDataVersion);
    1513     ASSERT(q);
    1514     if (!q)
    1515         return false;
    1516     q = decodeIDBKey(q, valueLimit, m_primaryKey);
    1517     ASSERT(q);
    1518     if (!q)
     1568    valuePosition = decodeVarInt(valuePosition, valueLimit, indexDataVersion);
     1569    ASSERT(valuePosition);
     1570    if (!valuePosition)
     1571        return false;
     1572    valuePosition = decodeIDBKey(valuePosition, valueLimit, m_primaryKey);
     1573    ASSERT(valuePosition);
     1574    if (!valuePosition)
    15191575        return false;
    15201576
     
    15421598}
    15431599
    1544 }
    1545 
    1546 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction)
    1547 {
    1548     IDB_TRACE("IDBLevelDBBackingStore::openObjectStoreCursor");
    1549     ASSERT(m_currentTransaction);
    1550     CursorOptions cursorOptions;
    1551 
     1600bool objectStoreCursorOptions(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction, CursorOptions& cursorOptions)
     1601{
    15521602    bool lowerBound = range && range->lower();
    15531603    bool upperBound = range && range->upper();
     
    15701620        else {
    15711621            // We need a key that exists.
    1572             if (!findGreatestKeyLessThanOrEqual(m_currentTransaction.get(), cursorOptions.highKey, cursorOptions.highKey))
    1573                 return 0;
     1622            if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, cursorOptions.highKey))
     1623                return false;
    15741624            cursorOptions.highOpen = false;
    15751625        }
     
    15811631            // For reverse cursors, we need a key that exists.
    15821632            Vector<char> foundHighKey;
    1583             if (!findGreatestKeyLessThanOrEqual(m_currentTransaction.get(), cursorOptions.highKey, foundHighKey))
    1584                 return 0;
     1633            if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, foundHighKey))
     1634                return false;
    15851635
    15861636            // If the target key should not be included, but we end up with a smaller key, we should include that.
     
    15921642    }
    15931643
    1594     RefPtr<ObjectStoreCursorImpl> cursor = ObjectStoreCursorImpl::create(m_currentTransaction.get(), cursorOptions);
    1595     if (!cursor->firstSeek())
    1596         return 0;
    1597 
    1598     return cursor.release();
    1599 }
    1600 
    1601 PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction)
    1602 {
    1603     IDB_TRACE("IDBLevelDBBackingStore::openIndexKeyCursor");
    1604     ASSERT(m_currentTransaction);
    1605     CursorOptions cursorOptions;
     1644    return true;
     1645}
     1646
     1647bool indexCursorOptions(LevelDBTransaction* transaction, int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction, CursorOptions& cursorOptions)
     1648{
     1649    ASSERT(transaction);
    16061650    bool lowerBound = range && range->lower();
    16071651    bool upperBound = range && range->upper();
     
    16221666
    16231667        if (!cursorOptions.forward) { // We need a key that exists.
    1624             if (!findGreatestKeyLessThanOrEqual(m_currentTransaction.get(), cursorOptions.highKey, cursorOptions.highKey))
    1625                 return 0;
     1668            if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, cursorOptions.highKey))
     1669                return false;
    16261670            cursorOptions.highOpen = false;
    16271671        }
     
    16311675
    16321676        Vector<char> foundHighKey;
    1633         if (!findGreatestKeyLessThanOrEqual(m_currentTransaction.get(), cursorOptions.highKey, foundHighKey)) // Seek to the *last* key in the set of non-unique keys.
    1634             return 0;
     1677        if (!findGreatestKeyLessThanOrEqual(transaction, cursorOptions.highKey, foundHighKey)) // Seek to the *last* key in the set of non-unique keys.
     1678            return false;
    16351679
    16361680        // If the target key should not be included, but we end up with a smaller key, we should include that.
     
    16411685    }
    16421686
     1687    return true;
     1688}
     1689
     1690}
     1691
     1692PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction)
     1693{
     1694    IDB_TRACE("IDBLevelDBBackingStore::openObjectStoreCursor");
     1695    ASSERT(m_currentTransaction);
     1696    CursorOptions cursorOptions;
     1697    if (!objectStoreCursorOptions(m_currentTransaction.get(), databaseId, objectStoreId, range, direction, cursorOptions))
     1698        return 0;
     1699    RefPtr<ObjectStoreCursorImpl> cursor = ObjectStoreCursorImpl::create(m_currentTransaction.get(), cursorOptions);
     1700    if (!cursor->firstSeek())
     1701        return 0;
     1702
     1703    return cursor.release();
     1704}
     1705
     1706PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openObjectStoreKeyCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange* range, IDBCursor::Direction direction)
     1707{
     1708    IDB_TRACE("IDBLevelDBBackingStore::openObjectStoreKeyCursor");
     1709    ASSERT(m_currentTransaction);
     1710    CursorOptions cursorOptions;
     1711    if (!objectStoreCursorOptions(m_currentTransaction.get(), databaseId, objectStoreId, range, direction, cursorOptions))
     1712        return 0;
     1713    RefPtr<ObjectStoreKeyCursorImpl> cursor = ObjectStoreKeyCursorImpl::create(m_currentTransaction.get(), cursorOptions);
     1714    if (!cursor->firstSeek())
     1715        return 0;
     1716
     1717    return cursor.release();
     1718}
     1719
     1720PassRefPtr<IDBBackingStore::Cursor> IDBLevelDBBackingStore::openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange* range, IDBCursor::Direction direction)
     1721{
     1722    IDB_TRACE("IDBLevelDBBackingStore::openIndexKeyCursor");
     1723    ASSERT(m_currentTransaction);
     1724    CursorOptions cursorOptions;
     1725    if (!indexCursorOptions(m_currentTransaction.get(), databaseId, objectStoreId, indexId, range, direction, cursorOptions))
     1726        return 0;
    16431727    RefPtr<IndexKeyCursorImpl> cursor = IndexKeyCursorImpl::create(m_currentTransaction.get(), cursorOptions);
    16441728    if (!cursor->firstSeek())
     
    16531737    ASSERT(m_currentTransaction);
    16541738    CursorOptions cursorOptions;
    1655     bool lowerBound = range && range->lower();
    1656     bool upperBound = range && range->upper();
    1657     cursorOptions.forward = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::NEXT);
    1658     cursorOptions.unique = (direction == IDBCursor::NEXT_NO_DUPLICATE || direction == IDBCursor::PREV_NO_DUPLICATE);
    1659 
    1660     if (!lowerBound) {
    1661         cursorOptions.lowKey = IndexDataKey::encodeMinKey(databaseId, objectStoreId, indexId);
    1662         cursorOptions.lowOpen = false; // Included.
    1663     } else {
    1664         cursorOptions.lowKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->lower());
    1665         cursorOptions.lowOpen = range->lowerOpen();
    1666     }
    1667 
    1668     if (!upperBound) {
    1669         cursorOptions.highKey = IndexDataKey::encodeMaxKey(databaseId, objectStoreId, indexId);
    1670         cursorOptions.highOpen = false; // Included.
    1671 
    1672         if (!cursorOptions.forward) { // We need a key that exists.
    1673             if (!findGreatestKeyLessThanOrEqual(m_currentTransaction.get(), cursorOptions.highKey, cursorOptions.highKey))
    1674                 return 0;
    1675             cursorOptions.highOpen = false;
    1676         }
    1677     } else {
    1678         cursorOptions.highKey = IndexDataKey::encode(databaseId, objectStoreId, indexId, *range->upper());
    1679         cursorOptions.highOpen = range->upperOpen();
    1680 
    1681         Vector<char> foundHighKey;
    1682         if (!findGreatestKeyLessThanOrEqual(m_currentTransaction.get(), cursorOptions.highKey, foundHighKey)) // Seek to the *last* key in the set of non-unique keys.
    1683             return 0;
    1684 
    1685         // If the target key should not be included, but we end up with a smaller key, we should include that.
    1686         if (cursorOptions.highOpen && compareIndexKeys(foundHighKey, cursorOptions.highKey) < 0)
    1687             cursorOptions.highOpen = false;
    1688 
    1689         cursorOptions.highKey = foundHighKey;
    1690     }
    1691 
     1739    if (!indexCursorOptions(m_currentTransaction.get(), databaseId, objectStoreId, indexId, range, direction, cursorOptions))
     1740        return 0;
    16921741    RefPtr<IndexCursorImpl> cursor = IndexCursorImpl::create(m_currentTransaction.get(), cursorOptions);
    16931742    if (!cursor->firstSeek())
  • trunk/Source/WebCore/Modules/indexeddb/IDBLevelDBBackingStore.h

    r125627 r128217  
    7474    virtual bool keyExistsInIndex(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey);
    7575
     76    virtual PassRefPtr<Cursor> openObjectStoreKeyCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction);
    7677    virtual PassRefPtr<Cursor> openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction);
    7778    virtual PassRefPtr<Cursor> openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange*, IDBCursor::Direction);
  • trunk/Source/WebCore/Modules/indexeddb/IDBObjectStoreBackendImpl.cpp

    r127752 r128217  
    542542    IDB_TRACE("IDBObjectStoreBackendImpl::countInternal");
    543543    uint32_t count = 0;
    544     RefPtr<IDBBackingStore::Cursor> backingStoreCursor = objectStore->backingStore()->openObjectStoreCursor(objectStore->databaseId(), objectStore->id(), range.get(), IDBCursor::NEXT);
     544    RefPtr<IDBBackingStore::Cursor> backingStoreCursor = objectStore->backingStore()->openObjectStoreKeyCursor(objectStore->databaseId(), objectStore->id(), range.get(), IDBCursor::NEXT);
    545545    if (!backingStoreCursor) {
    546546        callbacks->onSuccess(SerializedScriptValue::numberValue(count));
  • trunk/Source/WebKit/chromium/tests/IDBFakeBackingStore.h

    r124675 r128217  
    6464    virtual bool keyExistsInIndex(int64_t databaseid, int64_t objectStoreId, int64_t indexId, const IDBKey& indexKey, RefPtr<IDBKey>& foundPrimaryKey) OVERRIDE { return false; }
    6565
     66    virtual PassRefPtr<Cursor> openObjectStoreKeyCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction) OVERRIDE { return PassRefPtr<Cursor>(); }
    6667    virtual PassRefPtr<Cursor> openObjectStoreCursor(int64_t databaseId, int64_t objectStoreId, const IDBKeyRange*, IDBCursor::Direction) OVERRIDE { return PassRefPtr<Cursor>(); }
    6768    virtual PassRefPtr<Cursor> openIndexKeyCursor(int64_t databaseId, int64_t objectStoreId, int64_t indexId, const IDBKeyRange*, IDBCursor::Direction) OVERRIDE { return PassRefPtr<Cursor>(); }
Note: See TracChangeset for help on using the changeset viewer.