Changeset 209960 in webkit


Ignore:
Timestamp:
Dec 16, 2016 11:29:17 PM (7 years ago)
Author:
beidson@apple.com
Message:

IndexedDB: Refactor SQLiteIDBCursor to prepare for cursor prefetching.
https://bugs.webkit.org/show_bug.cgi?id=165978

Reviewed by Alex Christensen.

No new tests (Refactor, no behavior change).

In preparation for cursor prefetching, we need to shift the cursor off of keeping "the current record"
and onto keeping "a deque of fetched records", the first of which is "the current record".

This patch does just that, but with no behavior change; The deque only ever holds 0 or 1 records.

  • Modules/indexeddb/server/SQLiteIDBCursor.cpp:

(WebCore::IDBServer::SQLiteIDBCursor::currentData):
(WebCore::IDBServer::SQLiteIDBCursor::objectStoreRecordsChanged):
(WebCore::IDBServer::SQLiteIDBCursor::resetAndRebindStatement):
(WebCore::IDBServer::SQLiteIDBCursor::prefetch):
(WebCore::IDBServer::SQLiteIDBCursor::advance):
(WebCore::IDBServer::SQLiteIDBCursor::fetch):
(WebCore::IDBServer::SQLiteIDBCursor::fetchNextRecord):
(WebCore::IDBServer::SQLiteIDBCursor::markAsErrored):
(WebCore::IDBServer::SQLiteIDBCursor::internalFetchNextRecord):
(WebCore::IDBServer::SQLiteIDBCursor::iterate):
(WebCore::IDBServer::SQLiteIDBCursor::currentKey):
(WebCore::IDBServer::SQLiteIDBCursor::currentPrimaryKey):
(WebCore::IDBServer::SQLiteIDBCursor::currentValue):
(WebCore::IDBServer::SQLiteIDBCursor::didComplete):
(WebCore::IDBServer::SQLiteIDBCursor::didError):
(WebCore::IDBServer::SQLiteIDBCursor::currentRecordRowID):
(WebCore::IDBServer::SQLiteIDBCursor::advanceUnique): Deleted.
(WebCore::IDBServer::SQLiteIDBCursor::advanceOnce): Deleted.
(WebCore::IDBServer::SQLiteIDBCursor::internalAdvanceOnce): Deleted.

  • Modules/indexeddb/server/SQLiteIDBCursor.h:

(WebCore::IDBServer::SQLiteIDBCursor::SQLiteCursorRecord::isTerminalRecord):
(WebCore::IDBServer::SQLiteIDBCursor::currentRecordRowID): Deleted.
(WebCore::IDBServer::SQLiteIDBCursor::currentKey): Deleted.
(WebCore::IDBServer::SQLiteIDBCursor::currentPrimaryKey): Deleted.
(WebCore::IDBServer::SQLiteIDBCursor::currentValue): Deleted.
(WebCore::IDBServer::SQLiteIDBCursor::didComplete): Deleted.
(WebCore::IDBServer::SQLiteIDBCursor::didError): Deleted.

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r209959 r209960  
     12016-12-16  Brady Eidson  <beidson@apple.com>
     2
     3        IndexedDB: Refactor SQLiteIDBCursor to prepare for cursor prefetching.
     4        https://bugs.webkit.org/show_bug.cgi?id=165978
     5
     6        Reviewed by Alex Christensen.
     7
     8        No new tests (Refactor, no behavior change).
     9       
     10        In preparation for cursor prefetching, we need to shift the cursor off of keeping "the current record"
     11        and onto keeping "a deque of fetched records", the first of which is "the current record".
     12       
     13        This patch does just that, but with no behavior change; The deque only ever holds 0 or 1 records.
     14
     15        * Modules/indexeddb/server/SQLiteIDBCursor.cpp:
     16        (WebCore::IDBServer::SQLiteIDBCursor::currentData):
     17        (WebCore::IDBServer::SQLiteIDBCursor::objectStoreRecordsChanged):
     18        (WebCore::IDBServer::SQLiteIDBCursor::resetAndRebindStatement):
     19        (WebCore::IDBServer::SQLiteIDBCursor::prefetch):
     20        (WebCore::IDBServer::SQLiteIDBCursor::advance):
     21        (WebCore::IDBServer::SQLiteIDBCursor::fetch):
     22        (WebCore::IDBServer::SQLiteIDBCursor::fetchNextRecord):
     23        (WebCore::IDBServer::SQLiteIDBCursor::markAsErrored):
     24        (WebCore::IDBServer::SQLiteIDBCursor::internalFetchNextRecord):
     25        (WebCore::IDBServer::SQLiteIDBCursor::iterate):
     26        (WebCore::IDBServer::SQLiteIDBCursor::currentKey):
     27        (WebCore::IDBServer::SQLiteIDBCursor::currentPrimaryKey):
     28        (WebCore::IDBServer::SQLiteIDBCursor::currentValue):
     29        (WebCore::IDBServer::SQLiteIDBCursor::didComplete):
     30        (WebCore::IDBServer::SQLiteIDBCursor::didError):
     31        (WebCore::IDBServer::SQLiteIDBCursor::currentRecordRowID):
     32        (WebCore::IDBServer::SQLiteIDBCursor::advanceUnique): Deleted.
     33        (WebCore::IDBServer::SQLiteIDBCursor::advanceOnce): Deleted.
     34        (WebCore::IDBServer::SQLiteIDBCursor::internalAdvanceOnce): Deleted.
     35       
     36        * Modules/indexeddb/server/SQLiteIDBCursor.h:
     37        (WebCore::IDBServer::SQLiteIDBCursor::SQLiteCursorRecord::isTerminalRecord):
     38        (WebCore::IDBServer::SQLiteIDBCursor::currentRecordRowID): Deleted.
     39        (WebCore::IDBServer::SQLiteIDBCursor::currentKey): Deleted.
     40        (WebCore::IDBServer::SQLiteIDBCursor::currentPrimaryKey): Deleted.
     41        (WebCore::IDBServer::SQLiteIDBCursor::currentValue): Deleted.
     42        (WebCore::IDBServer::SQLiteIDBCursor::didComplete): Deleted.
     43        (WebCore::IDBServer::SQLiteIDBCursor::didError): Deleted.
     44
    1452016-12-16  Darin Adler  <darin@apple.com>
    246
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.cpp

    r209942 r209960  
    102102void SQLiteIDBCursor::currentData(IDBGetResult& result)
    103103{
    104     if (m_currentRecord.completed) {
    105         ASSERT(!m_currentRecord.errored);
     104    ASSERT(!m_fetchedRecords.isEmpty());
     105
     106    auto& currentRecord = m_fetchedRecords.first();
     107    if (currentRecord.completed) {
     108        ASSERT(!currentRecord.errored);
    106109        result = { };
    107110        return;
    108111    }
    109112
    110     result = { m_currentRecord.record.key, m_currentRecord.record.primaryKey, m_currentRecord.record.value ? *m_currentRecord.record.value : IDBValue() };
     113    result = { currentRecord.record.key, currentRecord.record.primaryKey, currentRecord.record.value ? *currentRecord.record.value : IDBValue() };
    111114}
    112115
     
    207210void SQLiteIDBCursor::objectStoreRecordsChanged()
    208211{
     212    if (m_statementNeedsReset)
     213        return;
     214
    209215    // If ObjectStore or Index contents changed, we need to reset the statement and bind new parameters to it.
    210216    // This is to pick up any changes that might exist.
     217    // We also need to throw away any fetched records as they may no longer be valid.
    211218
    212219    m_statementNeedsReset = true;
    213 }
    214 
    215 void SQLiteIDBCursor::resetAndRebindStatement()
    216 {
    217     ASSERT(!m_currentLowerKey.isNull());
    218     ASSERT(!m_currentUpperKey.isNull());
    219     ASSERT(m_transaction->sqliteTransaction());
    220     ASSERT(m_statement);
    221     ASSERT(m_statementNeedsReset);
    222 
    223     m_statementNeedsReset = false;
    224 
    225     // If this cursor never fetched any records, we don't need to reset the statement.
    226     if (m_currentRecord.record.key.isNull())
    227         return;
    228 
    229     // Otherwise update the lower key or upper key used for the cursor range.
    230     // This is so the cursor can pick up where we left off.
    231     // We might also have to change the statement from closed to open so we don't refetch the current key a second time.
     220    ASSERT(!m_fetchedRecords.isEmpty());
     221
    232222    if (m_cursorDirection == IndexedDB::CursorDirection::Next || m_cursorDirection == IndexedDB::CursorDirection::NextNoDuplicate) {
    233         m_currentLowerKey = m_currentRecord.record.key;
     223        m_currentLowerKey = m_fetchedRecords.first().record.key;
    234224        if (!m_keyRange.lowerOpen) {
    235225            m_keyRange.lowerOpen = true;
     
    238228        }
    239229    } else {
    240         m_currentUpperKey = m_currentRecord.record.key;
     230        m_currentUpperKey = m_fetchedRecords.first().record.key;
    241231        if (!m_keyRange.upperOpen) {
    242232            m_keyRange.upperOpen = true;
     
    246236    }
    247237
     238    m_fetchedRecords.clear();
     239}
     240
     241void SQLiteIDBCursor::resetAndRebindStatement()
     242{
     243    ASSERT(!m_currentLowerKey.isNull());
     244    ASSERT(!m_currentUpperKey.isNull());
     245    ASSERT(m_transaction->sqliteTransaction());
     246    ASSERT(m_statementNeedsReset);
     247
     248    m_statementNeedsReset = false;
     249
    248250    if (!m_statement && !establishStatement()) {
    249251        LOG_ERROR("Unable to establish new statement for cursor iteration");
     
    290292}
    291293
     294void SQLiteIDBCursor::prefetch()
     295{
     296    ASSERT(!m_fetchedRecords.isEmpty());
     297    if (m_fetchedRecords.last().errored || m_fetchedRecords.last().completed)
     298        return;
     299
     300    m_currentKeyForUniqueness = m_fetchedRecords.last().record.key;
     301    fetch();
     302}
     303
    292304bool SQLiteIDBCursor::advance(uint64_t count)
    293305{
    294     bool isUnique = m_cursorDirection == IndexedDB::CursorDirection::NextNoDuplicate || m_cursorDirection == IndexedDB::CursorDirection::PrevNoDuplicate;
    295 
    296     if (m_currentRecord.completed) {
     306    ASSERT(count);
     307
     308    if (!m_fetchedRecords.isEmpty() && m_fetchedRecords.first().isTerminalRecord()) {
    297309        LOG_ERROR("Attempt to advance a completed cursor");
    298310        return false;
    299311    }
    300312
     313    if (!m_fetchedRecords.isEmpty())
     314        m_currentKeyForUniqueness = m_fetchedRecords.last().record.key;
     315
     316    // Drop already-fetched records up to `count` to see if we've already fetched the record we're looking for.
     317    for (size_t i = 0; i < count && !m_fetchedRecords.isEmpty(); ++i) {
     318        if (m_fetchedRecords.first().isTerminalRecord())
     319            break;
     320
     321        m_fetchedRecords.removeFirst();
     322    }
     323
     324    // If we still have any records left, the first record is our new current record.
     325    if (!m_fetchedRecords.isEmpty())
     326        return !m_fetchedRecords.first().isTerminalRecord();
     327
     328    ASSERT(m_fetchedRecords.isEmpty());
     329
    301330    for (uint64_t i = 0; i < count; ++i) {
    302         if (!isUnique) {
    303             if (!advanceOnce())
    304                 return false;
    305         } else {
    306             if (!advanceUnique())
    307                 return false;
    308         }
    309 
    310         if (m_currentRecord.completed)
     331        if (!m_fetchedRecords.isEmpty()) {
     332            ASSERT(m_fetchedRecords.size() == 1);
     333            m_currentKeyForUniqueness = m_fetchedRecords.first().record.key;
     334            m_fetchedRecords.removeFirst();
     335        }
     336
     337        if (!fetch())
     338            return false;
     339
     340        ASSERT(!m_fetchedRecords.isEmpty());
     341        ASSERT(!m_fetchedRecords.first().errored);
     342        if (m_fetchedRecords.first().completed)
    311343            break;
    312344    }
     
    315347}
    316348
    317 bool SQLiteIDBCursor::advanceUnique()
    318 {
    319     IDBKeyData currentKey = m_currentRecord.record.key;
    320 
    321     while (!m_currentRecord.completed) {
    322         if (!advanceOnce())
     349bool SQLiteIDBCursor::fetch()
     350{
     351    ASSERT(m_fetchedRecords.isEmpty() || !m_fetchedRecords.last().isTerminalRecord());
     352
     353    m_fetchedRecords.append({ });
     354
     355    bool isUnique = m_cursorDirection == IndexedDB::CursorDirection::NextNoDuplicate || m_cursorDirection == IndexedDB::CursorDirection::PrevNoDuplicate;
     356    if (!isUnique)
     357        return fetchNextRecord(m_fetchedRecords.last());
     358
     359    while (!m_fetchedRecords.last().completed) {
     360        if (!fetchNextRecord(m_fetchedRecords.last()))
    323361            return false;
    324362
    325363        // If the new current key is different from the old current key, we're done.
    326         if (currentKey.compare(m_currentRecord.record.key))
     364        if (m_currentKeyForUniqueness.compare(m_fetchedRecords.last().record.key))
    327365            return true;
    328366    }
     
    331369}
    332370
    333 bool SQLiteIDBCursor::advanceOnce()
     371bool SQLiteIDBCursor::fetchNextRecord(SQLiteCursorRecord& record)
    334372{
    335373    if (m_statementNeedsReset)
    336374        resetAndRebindStatement();
    337375
    338     AdvanceResult result;
     376    FetchResult result;
    339377    do {
    340         result = internalAdvanceOnce();
    341     } while (result == AdvanceResult::ShouldAdvanceAgain);
    342 
    343     return result == AdvanceResult::Success;
    344 }
    345 
    346 void SQLiteIDBCursor::markAsErrored()
    347 {
    348     m_currentRecord.completed = true;
    349     m_currentRecord.errored = true;
    350     m_currentRecord.rowID = 0;
    351 }
    352 
    353 SQLiteIDBCursor::AdvanceResult SQLiteIDBCursor::internalAdvanceOnce()
     378        result = internalFetchNextRecord(record);
     379    } while (result == FetchResult::ShouldFetchAgain);
     380
     381    return result == FetchResult::Success;
     382}
     383
     384void SQLiteIDBCursor::markAsErrored(SQLiteCursorRecord& record)
     385{
     386    record.record = { };
     387    record.completed = true;
     388    record.errored = true;
     389    record.rowID = 0;
     390}
     391
     392SQLiteIDBCursor::FetchResult SQLiteIDBCursor::internalFetchNextRecord(SQLiteCursorRecord& record)
    354393{
    355394    ASSERT(m_transaction->sqliteTransaction());
    356395    ASSERT(m_statement);
    357     ASSERT(!m_currentRecord.completed);
    358 
    359     m_currentRecord.record.value = nullptr;
     396    ASSERT(!m_fetchedRecords.isEmpty());
     397    ASSERT(!m_fetchedRecords.last().isTerminalRecord());
     398
     399    record.record.value = nullptr;
    360400
    361401    int result = m_statement->step();
    362402    if (result == SQLITE_DONE) {
    363403        // When a cursor reaches its end, that is indicated by having undefined keys/values
    364         m_currentRecord = { };
    365         m_currentRecord.completed = true;
    366         m_currentRecord.rowID = 0;
    367 
    368         return AdvanceResult::Success;
     404        record = { };
     405        record.completed = true;
     406
     407        return FetchResult::Success;
    369408    }
    370409
    371410    if (result != SQLITE_ROW) {
    372411        LOG_ERROR("Error advancing cursor - (%i) %s", result, m_transaction->sqliteTransaction()->database().lastErrorMsg());
    373         markAsErrored();
    374         return AdvanceResult::Failure;
    375     }
    376 
    377     m_currentRecord.rowID = m_statement->getColumnInt64(0);
    378     ASSERT(m_currentRecord.rowID);
     412        markAsErrored(record);
     413        return FetchResult::Failure;
     414    }
     415
     416    record.rowID = m_statement->getColumnInt64(0);
     417    ASSERT(record.rowID);
    379418
    380419    Vector<uint8_t> keyData;
    381420    m_statement->getColumnBlobAsVector(1, keyData);
    382421
    383     if (!deserializeIDBKeyData(keyData.data(), keyData.size(), m_currentRecord.record.key)) {
     422    if (!deserializeIDBKeyData(keyData.data(), keyData.size(), record.record.key)) {
    384423        LOG_ERROR("Unable to deserialize key data from database while advancing cursor");
    385         markAsErrored();
    386         return AdvanceResult::Failure;
     424        markAsErrored(record);
     425        return FetchResult::Failure;
    387426    }
    388427
     
    391430    // The primaryKey of an ObjectStore cursor is the same as its key.
    392431    if (m_indexID == IDBIndexInfo::InvalidId) {
    393         m_currentRecord.record.primaryKey = m_currentRecord.record.key;
     432        record.record.primaryKey = record.record.key;
    394433
    395434        Vector<String> blobURLs, blobFilePaths;
    396         auto error = m_transaction->backingStore().getBlobRecordsForObjectStoreRecord(m_currentRecord.rowID, blobURLs, blobFilePaths);
     435        auto error = m_transaction->backingStore().getBlobRecordsForObjectStoreRecord(record.rowID, blobURLs, blobFilePaths);
    397436        if (!error.isNull()) {
    398437            LOG_ERROR("Unable to fetch blob records from database while advancing cursor");
    399             markAsErrored();
    400             return AdvanceResult::Failure;
     438            markAsErrored(record);
     439            return FetchResult::Failure;
    401440        }
    402441
    403442        if (m_cursorType == IndexedDB::CursorType::KeyAndValue)
    404             m_currentRecord.record.value = std::make_unique<IDBValue>(ThreadSafeDataBuffer::adoptVector(keyData), blobURLs, blobFilePaths);
     443            record.record.value = std::make_unique<IDBValue>(ThreadSafeDataBuffer::adoptVector(keyData), blobURLs, blobFilePaths);
    405444    } else {
    406         if (!deserializeIDBKeyData(keyData.data(), keyData.size(), m_currentRecord.record.primaryKey)) {
     445        if (!deserializeIDBKeyData(keyData.data(), keyData.size(), record.record.primaryKey)) {
    407446            LOG_ERROR("Unable to deserialize value data from database while advancing index cursor");
    408             markAsErrored();
    409             return AdvanceResult::Failure;
     447            markAsErrored(record);
     448            return FetchResult::Failure;
    410449        }
    411450
     
    416455            || objectStoreStatement.bindInt64(2, m_objectStoreID) != SQLITE_OK) {
    417456            LOG_ERROR("Could not create index cursor statement into object store records (%i) '%s'", m_statement->database().lastError(), m_statement->database().lastErrorMsg());
    418             markAsErrored();
    419             return AdvanceResult::Failure;
     457            markAsErrored(record);
     458            return FetchResult::Failure;
    420459        }
    421460
     
    424463        if (result == SQLITE_ROW) {
    425464            objectStoreStatement.getColumnBlobAsVector(0, keyData);
    426             m_currentRecord.record.value = std::make_unique<IDBValue>(ThreadSafeDataBuffer::adoptVector(keyData));
     465            record.record.value = std::make_unique<IDBValue>(ThreadSafeDataBuffer::adoptVector(keyData));
    427466        } else if (result == SQLITE_DONE) {
    428467            // This indicates that the record we're trying to retrieve has been removed from the object store.
    429468            // Skip over it.
    430             return AdvanceResult::ShouldAdvanceAgain;
     469            return FetchResult::ShouldFetchAgain;
    431470        } else {
    432471            LOG_ERROR("Could not step index cursor statement into object store records (%i) '%s'", m_statement->database().lastError(), m_statement->database().lastErrorMsg());
    433             markAsErrored();
    434             return AdvanceResult::Failure;
    435 
    436         }
    437     }
    438 
    439     return AdvanceResult::Success;
     472            markAsErrored(record);
     473            return FetchResult::Failure;
     474
     475        }
     476    }
     477
     478    return FetchResult::Success;
    440479}
    441480
     
    446485
    447486    bool result = advance(1);
     487    ASSERT(!m_fetchedRecords.isEmpty());
    448488
    449489    // Iterating with no key is equivalent to advancing 1 step.
     
    451491        return result;
    452492
    453     while (!m_currentRecord.completed) {
     493    while (!m_fetchedRecords.first().isTerminalRecord()) {
    454494        if (!result)
    455495            return false;
     
    457497        // Search for the next key >= the target if the cursor is a Next cursor, or the next key <= if the cursor is a Previous cursor.
    458498        if (m_cursorDirection == IndexedDB::CursorDirection::Next || m_cursorDirection == IndexedDB::CursorDirection::NextNoDuplicate) {
    459             if (m_currentRecord.record.key.compare(targetKey) >= 0)
     499            if (m_fetchedRecords.first().record.key.compare(targetKey) >= 0)
    460500                break;
    461         } else if (m_currentRecord.record.key.compare(targetKey) <= 0)
     501        } else if (m_fetchedRecords.first().record.key.compare(targetKey) <= 0)
    462502            break;
    463503
     
    466506
    467507    if (targetPrimaryKey.isValid()) {
    468         while (!m_currentRecord.completed && !m_currentRecord.record.key.compare(targetKey)) {
     508        while (!m_fetchedRecords.first().isTerminalRecord() && !m_fetchedRecords.first().record.key.compare(targetKey)) {
    469509            if (!result)
    470510                return false;
     
    472512            // Search for the next primary key >= the primary target if the cursor is a Next cursor, or the next key <= if the cursor is a Previous cursor.
    473513            if (m_cursorDirection == IndexedDB::CursorDirection::Next || m_cursorDirection == IndexedDB::CursorDirection::NextNoDuplicate) {
    474                 if (m_currentRecord.record.primaryKey.compare(targetPrimaryKey) >= 0)
     514                if (m_fetchedRecords.first().record.primaryKey.compare(targetPrimaryKey) >= 0)
    475515                    break;
    476             } else if (m_currentRecord.record.primaryKey.compare(targetPrimaryKey) <= 0)
     516            } else if (m_fetchedRecords.first().record.primaryKey.compare(targetPrimaryKey) <= 0)
    477517                break;
    478518
     
    483523    return result;
    484524}
     525
     526const IDBKeyData& SQLiteIDBCursor::currentKey() const
     527{
     528    ASSERT(!m_fetchedRecords.isEmpty());
     529    return m_fetchedRecords.first().record.key;
     530}
     531
     532const IDBKeyData& SQLiteIDBCursor::currentPrimaryKey() const
     533{
     534    ASSERT(!m_fetchedRecords.isEmpty());
     535    return m_fetchedRecords.first().record.primaryKey;
     536}
     537
     538IDBValue* SQLiteIDBCursor::currentValue() const
     539{
     540    ASSERT(!m_fetchedRecords.isEmpty());
     541    return m_fetchedRecords.first().record.value.get();
     542}
     543
     544bool SQLiteIDBCursor::didComplete() const
     545{
     546    ASSERT(!m_fetchedRecords.isEmpty());
     547    return m_fetchedRecords.first().completed;
     548}
     549
     550bool SQLiteIDBCursor::didError() const
     551{
     552    ASSERT(!m_fetchedRecords.isEmpty());
     553    return m_fetchedRecords.first().errored;
     554}
     555
     556int64_t SQLiteIDBCursor::currentRecordRowID() const
     557{
     558    ASSERT(!m_fetchedRecords.isEmpty());
     559    return m_fetchedRecords.first().rowID;
     560}
     561
    485562
    486563} // namespace IDBServer
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.h

    r209942 r209960  
    3535#include "IDBValue.h"
    3636#include "SQLiteStatement.h"
     37#include <wtf/Deque.h>
    3738#include <wtf/Noncopyable.h>
    3839
     
    6162
    6263    int64_t objectStoreID() const { return m_objectStoreID; }
    63     int64_t currentRecordRowID() const { return m_currentRecord.rowID; }
     64    int64_t currentRecordRowID() const;
    6465
    65     const IDBKeyData& currentKey() const { return m_currentRecord.record.key; }
    66     const IDBKeyData& currentPrimaryKey() const { return m_currentRecord.record.primaryKey; }
    67     IDBValue* currentValue() const { return m_currentRecord.record.value.get(); }
     66    const IDBKeyData& currentKey() const;
     67    const IDBKeyData& currentPrimaryKey() const;
     68    IDBValue* currentValue() const;
    6869
    6970    bool advance(uint64_t count);
    7071    bool iterate(const IDBKeyData& targetKey, const IDBKeyData& targetPrimaryKey);
     72    void prefetch();
    7173
    72     bool didComplete() const { return m_currentRecord.completed; }
    73     bool didError() const { return m_currentRecord.errored; }
     74    bool didComplete() const;
     75    bool didError() const;
    7476
    7577    void objectStoreRecordsChanged();
     
    8486    void resetAndRebindStatement();
    8587
    86     void markAsErrored();
    87 
    88     enum class AdvanceResult {
     88    enum class FetchResult {
    8989        Success,
    9090        Failure,
    91         ShouldAdvanceAgain
     91        ShouldFetchAgain
    9292    };
    9393
    94     AdvanceResult internalAdvanceOnce();
    95     bool advanceOnce();
    96     bool advanceUnique();
     94    bool fetch();
     95
     96    struct SQLiteCursorRecord {
     97        IDBCursorRecord record;
     98        bool completed { false };
     99        bool errored { false };
     100        int64_t rowID { 0 };
     101        bool isTerminalRecord() const { return completed || errored; }
     102    };
     103    bool fetchNextRecord(SQLiteCursorRecord&);
     104    FetchResult internalFetchNextRecord(SQLiteCursorRecord&);
     105
     106    void markAsErrored(SQLiteCursorRecord&);
    97107
    98108    SQLiteIDBTransaction* m_transaction;
     
    107117    IDBKeyData m_currentUpperKey;
    108118
    109     struct SQLiteCursorRecord {
    110         IDBCursorRecord record;
    111         bool completed { false };
    112         bool errored { false };
    113         int64_t rowID { 0 };
    114     };
    115 
    116     SQLiteCursorRecord m_currentRecord;
     119    Deque<SQLiteCursorRecord> m_fetchedRecords;
     120    IDBKeyData m_currentKeyForUniqueness;
    117121
    118122    std::unique_ptr<SQLiteStatement> m_statement;
    119     bool m_statementNeedsReset { false };
     123    bool m_statementNeedsReset { true };
    120124    int64_t m_boundID { 0 };
    121125
Note: See TracChangeset for help on using the changeset viewer.