Changeset 209824 in webkit


Ignore:
Timestamp:
Dec 14, 2016 12:56:50 PM (7 years ago)
Author:
beidson@apple.com
Message:

IndexedDB 2.0: Massively speedup IDBIndex.get().
https://bugs.webkit.org/show_bug.cgi?id=165802

Reviewed by Alex Christensen.

Source/WebCore:

No new tests (No behavior change to Javascript, table upgrade change covered by API test).

This change upgrades the IndexRecords schema to include the ObjectStore record ID for the referenced record.
It also adds a SQLite Index-by-key on IndexRecords.

This speeds up PerformanceTests/IndexedDB/index-get.html by 15-20x.

  • Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:

(WebCore::IDBServer::v3IndexRecordsTableSchema):
(WebCore::IDBServer::v3IndexRecordsTableSchemaAlternate):
(WebCore::IDBServer::v1IndexRecordsIndexSchema):
(WebCore::IDBServer::SQLiteIDBBackingStore::ensureValidIndexRecordsTable):
(WebCore::IDBServer::SQLiteIDBBackingStore::ensureValidIndexRecordsIndex):
(WebCore::IDBServer::SQLiteIDBBackingStore::getOrEstablishDatabaseInfo):
(WebCore::IDBServer::SQLiteIDBBackingStore::createIndex):
(WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedPutIndexKey):
(WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedPutIndexRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::updateOneIndexForAddRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::updateAllIndexesForAddRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::addRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::getIndexRecord):
(WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedGetIndexRecordForOneKey):

  • Modules/indexeddb/server/SQLiteIDBBackingStore.h:
  • Modules/indexeddb/server/SQLiteIDBCursor.cpp:

(WebCore::IDBServer::SQLiteIDBCursor::markAsErrored):
(WebCore::IDBServer::SQLiteIDBCursor::internalAdvanceOnce):

  • Modules/indexeddb/server/SQLiteIDBCursor.h:

(WebCore::IDBServer::SQLiteIDBCursor::currentRecordRowID):

Tools:

  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/WebKit2Cocoa/IDBIndexUpgradeToV2.html: Added.
  • TestWebKitAPI/Tests/WebKit2Cocoa/IDBIndexUpgradeToV2.mm: Added.
  • TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.blob: Added.
  • TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.sqlite3: Added.
Location:
trunk
Files:
4 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r209823 r209824  
     12016-12-14  Brady Eidson  <beidson@apple.com>
     2
     3        IndexedDB 2.0: Massively speedup IDBIndex.get().
     4        https://bugs.webkit.org/show_bug.cgi?id=165802
     5
     6        Reviewed by Alex Christensen.
     7
     8        No new tests (No behavior change to Javascript, table upgrade change covered by API test).
     9
     10        This change upgrades the IndexRecords schema to include the ObjectStore record ID for the referenced record.
     11        It also adds a SQLite Index-by-key on IndexRecords.
     12       
     13        This speeds up PerformanceTests/IndexedDB/index-get.html by 15-20x.
     14       
     15        * Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
     16        (WebCore::IDBServer::v3IndexRecordsTableSchema):
     17        (WebCore::IDBServer::v3IndexRecordsTableSchemaAlternate):
     18        (WebCore::IDBServer::v1IndexRecordsIndexSchema):
     19        (WebCore::IDBServer::SQLiteIDBBackingStore::ensureValidIndexRecordsTable):
     20        (WebCore::IDBServer::SQLiteIDBBackingStore::ensureValidIndexRecordsIndex):
     21        (WebCore::IDBServer::SQLiteIDBBackingStore::getOrEstablishDatabaseInfo):
     22        (WebCore::IDBServer::SQLiteIDBBackingStore::createIndex):
     23        (WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedPutIndexKey):
     24        (WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedPutIndexRecord):
     25        (WebCore::IDBServer::SQLiteIDBBackingStore::updateOneIndexForAddRecord):
     26        (WebCore::IDBServer::SQLiteIDBBackingStore::updateAllIndexesForAddRecord):
     27        (WebCore::IDBServer::SQLiteIDBBackingStore::addRecord):
     28        (WebCore::IDBServer::SQLiteIDBBackingStore::getIndexRecord):
     29        (WebCore::IDBServer::SQLiteIDBBackingStore::uncheckedGetIndexRecordForOneKey):
     30        * Modules/indexeddb/server/SQLiteIDBBackingStore.h:
     31
     32        * Modules/indexeddb/server/SQLiteIDBCursor.cpp:
     33        (WebCore::IDBServer::SQLiteIDBCursor::markAsErrored):
     34        (WebCore::IDBServer::SQLiteIDBCursor::internalAdvanceOnce):
     35        * Modules/indexeddb/server/SQLiteIDBCursor.h:
     36        (WebCore::IDBServer::SQLiteIDBCursor::currentRecordRowID):
     37
    1382016-12-14  Sam Weinig  <sam@webkit.org>
    239
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp

    r209197 r209824  
    172172}
    173173
     174static const String v3IndexRecordsTableSchema(const String& tableName)
     175{
     176    return makeString("CREATE TABLE ", tableName, " (indexID INTEGER NOT NULL ON CONFLICT FAIL, objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, key TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL, value TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL, objectStoreRecordID INTEGER NOT NULL ON CONFLICT FAIL)");
     177}
     178
     179static const String v3IndexRecordsTableSchema()
     180{
     181    static NeverDestroyed<WTF::String> indexRecordsTableSchemaString = v3IndexRecordsTableSchema("IndexRecords");
     182    return indexRecordsTableSchemaString;
     183}
     184
     185static const String v3IndexRecordsTableSchemaAlternate()
     186{
     187    static NeverDestroyed<WTF::String> indexRecordsTableSchemaString = v3IndexRecordsTableSchema("\"IndexRecords\"");
     188    return indexRecordsTableSchemaString;
     189}
     190
     191static const String& v1IndexRecordsIndexSchema()
     192{
     193    static NeverDestroyed<WTF::String> indexRecordsIndexSchemaString("CREATE INDEX IndexRecordsIndex ON IndexRecords (key)");
     194    return indexRecordsIndexSchemaString;
     195}
     196
    174197static const String blobRecordsTableSchema(const String& tableName)
    175198{
     
    429452        // If there is no IndexRecords table at all, create it and then bail.
    430453        if (sqliteResult == SQLITE_DONE) {
    431             if (!m_sqliteDB->executeCommand(v2IndexRecordsTableSchema())) {
     454            if (!m_sqliteDB->executeCommand(v3IndexRecordsTableSchema())) {
    432455                LOG_ERROR("Could not create IndexRecords table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    433456                return false;
     
    448471
    449472    // If the schema in the backing store is the current schema, we're done.
    450     if (currentSchema == v2IndexRecordsTableSchema() || currentSchema == v2IndexRecordsTableSchemaAlternate())
     473    if (currentSchema == v3IndexRecordsTableSchema() || currentSchema == v3IndexRecordsTableSchemaAlternate())
    451474        return true;
    452475
    453476    // If the record table is not the current schema then it must be one of the previous schemas.
    454477    // If it is not then the database is in an unrecoverable state and this should be considered a fatal error.
    455     if (currentSchema != v1IndexRecordsTableSchema() && currentSchema != v1IndexRecordsTableSchemaAlternate())
     478    if (currentSchema != v1IndexRecordsTableSchema() && currentSchema != v1IndexRecordsTableSchemaAlternate()
     479        && currentSchema != v2IndexRecordsTableSchema() && currentSchema != v2IndexRecordsTableSchemaAlternate())
    456480        RELEASE_ASSERT_NOT_REACHED();
    457481
     
    460484
    461485    // Create a temporary table with the correct schema and migrate all existing content over.
    462     if (!m_sqliteDB->executeCommand(v2IndexRecordsTableSchema("_Temp_IndexRecords"))) {
     486    if (!m_sqliteDB->executeCommand(v3IndexRecordsTableSchema("_Temp_IndexRecords"))) {
    463487        LOG_ERROR("Could not create temporary index records table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    464488        return false;
    465489    }
    466490
    467     if (!m_sqliteDB->executeCommand("INSERT INTO _Temp_IndexRecords SELECT * FROM IndexRecords")) {
     491    if (!m_sqliteDB->executeCommand("INSERT INTO _Temp_IndexRecords SELECT IndexRecords.indexID, IndexRecords.objectStoreID, IndexRecords.key, IndexRecords.value, Records.rowid FROM IndexRecords INNER JOIN Records ON Records.key = IndexRecords.value AND Records.objectStoreID = IndexRecords.objectStoreID")) {
    468492        LOG_ERROR("Could not migrate existing IndexRecords content (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    469493        return false;
     
    483507
    484508    return true;
     509}
     510
     511bool SQLiteIDBBackingStore::ensureValidIndexRecordsIndex()
     512{
     513    ASSERT(m_sqliteDB);
     514    ASSERT(m_sqliteDB->isOpen());
     515
     516    String currentSchema;
     517    {
     518        // Fetch the schema for an existing index record index.
     519        SQLiteStatement statement(*m_sqliteDB, "SELECT sql FROM sqlite_master WHERE name='IndexRecordsIndex'");
     520        if (statement.prepare() != SQLITE_OK) {
     521            LOG_ERROR("Unable to prepare statement to fetch schema for the IndexRecordsIndex index.");
     522            return false;
     523        }
     524
     525        int sqliteResult = statement.step();
     526
     527        // If there is no IndexRecordsIndex index at all, create it and then bail.
     528        if (sqliteResult == SQLITE_DONE) {
     529            if (!m_sqliteDB->executeCommand(v1IndexRecordsIndexSchema())) {
     530                LOG_ERROR("Could not create IndexRecordsIndex index in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
     531                return false;
     532            }
     533
     534            return true;
     535        }
     536
     537        if (sqliteResult != SQLITE_ROW) {
     538            LOG_ERROR("Error executing statement to fetch schema for the IndexRecordsIndex index.");
     539            return false;
     540        }
     541
     542        currentSchema = statement.getColumnText(0);
     543    }
     544
     545    ASSERT(!currentSchema.isEmpty());
     546
     547    // If the schema in the backing store is the current schema, we're done.
     548    if (currentSchema == v1IndexRecordsIndexSchema())
     549        return true;
     550
     551    // There is currently no outdated schema for the IndexRecordsIndex, so any other existing schema means this database is invalid.
     552    return false;
    485553}
    486554
     
    743811        closeSQLiteDB();
    744812        return { IDBDatabaseException::UnknownError, ASCIILiteral("Error creating or migrating Index Records table in database") };
     813    }
     814
     815    if (!ensureValidIndexRecordsIndex()) {
     816        LOG_ERROR("Error creating or migrating Index Records index in database");
     817        closeSQLiteDB();
     818        return { IDBDatabaseException::UnknownError, ASCIILiteral("Error creating or migrating Index Records index in database") };
    745819    }
    746820
     
    11081182        ThreadSafeDataBuffer valueBuffer = value ? value->data() : ThreadSafeDataBuffer();
    11091183
    1110         IDBError error = updateOneIndexForAddRecord(info, key, valueBuffer);
     1184        ASSERT(cursor->currentRecordRowID());
     1185
     1186        IDBError error = updateOneIndexForAddRecord(info, key, valueBuffer, cursor->currentRecordRowID());
    11111187        if (!error.isNull()) {
    11121188            auto* sql = cachedStatement(SQL::DeleteIndexInfo, ASCIILiteral("DELETE FROM IndexInfo WHERE id = ? AND objectStoreID = ?;"));
     
    11681244}
    11691245
    1170 IDBError SQLiteIDBBackingStore::uncheckedPutIndexKey(const IDBIndexInfo& info, const IDBKeyData& key, const IndexKey& indexKey)
     1246IDBError SQLiteIDBBackingStore::uncheckedPutIndexKey(const IDBIndexInfo& info, const IDBKeyData& key, const IndexKey& indexKey, int64_t recordID)
    11711247{
    11721248    LOG(IndexedDB, "SQLiteIDBBackingStore::uncheckedPutIndexKey - (%" PRIu64 ") %s, %s", info.identifier(), key.loggingString().utf8().data(), indexKey.asOneKey().loggingString().utf8().data());
     
    11951271        if (!indexKey.isValid())
    11961272            continue;
    1197         auto error = uncheckedPutIndexRecord(info.objectStoreIdentifier(), info.identifier(), key, indexKey);
     1273        auto error = uncheckedPutIndexRecord(info.objectStoreIdentifier(), info.identifier(), key, indexKey, recordID);
    11981274        if (!error.isNull()) {
    11991275            LOG_ERROR("Unable to put index record for newly created index");
     
    12051281}
    12061282
    1207 IDBError SQLiteIDBBackingStore::uncheckedPutIndexRecord(int64_t objectStoreID, int64_t indexID, const WebCore::IDBKeyData& keyValue, const WebCore::IDBKeyData& indexKey)
     1283IDBError SQLiteIDBBackingStore::uncheckedPutIndexRecord(int64_t objectStoreID, int64_t indexID, const WebCore::IDBKeyData& keyValue, const WebCore::IDBKeyData& indexKey, int64_t recordID)
    12081284{
    12091285    LOG(IndexedDB, "SQLiteIDBBackingStore::uncheckedPutIndexRecord - %s, %s", keyValue.loggingString().utf8().data(), indexKey.loggingString().utf8().data());
     
    12221298
    12231299    {
    1224         auto* sql = cachedStatement(SQL::PutIndexRecord, ASCIILiteral("INSERT INTO IndexRecords VALUES (?, ?, CAST(? AS TEXT), CAST(? AS TEXT));"));
     1300        auto* sql = cachedStatement(SQL::PutIndexRecord, ASCIILiteral("INSERT INTO IndexRecords VALUES (?, ?, CAST(? AS TEXT), CAST(? AS TEXT), ?);"));
    12251301        if (!sql
    12261302            || sql->bindInt64(1, indexID) != SQLITE_OK
     
    12281304            || sql->bindBlob(3, indexKeyBuffer->data(), indexKeyBuffer->size()) != SQLITE_OK
    12291305            || sql->bindBlob(4, valueBuffer->data(), valueBuffer->size()) != SQLITE_OK
     1306            || sql->bindInt64(5, recordID) != SQLITE_OK
    12301307            || sql->step() != SQLITE_DONE) {
    12311308            LOG_ERROR("Could not put index record for index %" PRIi64 " in object store %" PRIi64 " in Records table (%i) - %s", indexID, objectStoreID, m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
     
    15641641}
    15651642
    1566 IDBError SQLiteIDBBackingStore::updateOneIndexForAddRecord(const IDBIndexInfo& info, const IDBKeyData& key, const ThreadSafeDataBuffer& value)
     1643IDBError SQLiteIDBBackingStore::updateOneIndexForAddRecord(const IDBIndexInfo& info, const IDBKeyData& key, const ThreadSafeDataBuffer& value, int64_t recordID)
    15671644{
    15681645    JSLockHolder locker(vm());
     
    15781655        return { };
    15791656
    1580     return uncheckedPutIndexKey(info, key, indexKey);
    1581 }
    1582 
    1583 IDBError SQLiteIDBBackingStore::updateAllIndexesForAddRecord(const IDBObjectStoreInfo& info, const IDBKeyData& key, const ThreadSafeDataBuffer& value)
     1657    return uncheckedPutIndexKey(info, key, indexKey, recordID);
     1658}
     1659
     1660IDBError SQLiteIDBBackingStore::updateAllIndexesForAddRecord(const IDBObjectStoreInfo& info, const IDBKeyData& key, const ThreadSafeDataBuffer& value, int64_t recordID)
    15841661{
    15851662    JSLockHolder locker(vm());
     
    15981675            continue;
    15991676
    1600         error = uncheckedPutIndexKey(index, key, indexKey);
     1677        error = uncheckedPutIndexKey(index, key, indexKey, recordID);
    16011678        if (!error.isNull())
    16021679            break;
     
    16621739    }
    16631740
    1664     auto error = updateAllIndexesForAddRecord(objectStoreInfo, keyData, value.data());
     1741    auto error = updateAllIndexesForAddRecord(objectStoreInfo, keyData, value.data(), recordID);
    16651742
    16661743    if (!error.isNull()) {
     
    21132190    }
    21142191
     2192    if (range.isExactlyOneKey())
     2193        return uncheckedGetIndexRecordForOneKey(indexID, objectStoreID, type, range.lowerKey, getResult);
     2194
    21152195    auto cursor = transaction->maybeOpenBackingStoreCursor(objectStoreID, indexID, range);
    21162196    if (!cursor) {
     
    21332213    }
    21342214
     2215    return { };
     2216}
     2217
     2218IDBError SQLiteIDBBackingStore::uncheckedGetIndexRecordForOneKey(int64_t indexID, int64_t objectStoreID, IndexedDB::IndexRecordType type, const IDBKeyData& key, IDBGetResult& getResult)
     2219{
     2220    LOG(IndexedDB, "SQLiteIDBBackingStore::uncheckedGetIndexRecordForOneKey");
     2221
     2222    ASSERT(key.isValid() && key.type() != KeyType::Max && key.type() != KeyType::Min);
     2223
     2224    RefPtr<SharedBuffer> buffer = serializeIDBKeyData(key);
     2225    if (!buffer) {
     2226        LOG_ERROR("Unable to serialize IDBKey to look up one index record");
     2227        return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to serialize IDBKey to look up one index record") };
     2228    }
     2229
     2230    auto* sql = cachedStatement(SQL::GetIndexRecordForOneKey, ASCIILiteral("SELECT IndexRecords.value, Records.value, Records.recordID FROM Records INNER JOIN IndexRecords ON Records.recordID = IndexRecords.objectStoreRecordID WHERE IndexRecords.indexID = ? AND IndexRecords.objectStoreID = ? AND IndexRecords.key = CAST(? AS TEXT) ORDER BY IndexRecords.key, IndexRecords.value"));
     2231
     2232    if (!sql
     2233        || sql->bindInt64(1, indexID) != SQLITE_OK
     2234        || sql->bindInt64(2, objectStoreID) != SQLITE_OK
     2235        || sql->bindBlob(3, buffer->data(), buffer->size()) != SQLITE_OK) {
     2236        LOG_ERROR("Unable to lookup index record in database");
     2237        return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to lookup index record in database") };
     2238    }
     2239
     2240    int result = sql->step();
     2241    if (result != SQLITE_ROW && result != SQLITE_DONE) {
     2242        LOG_ERROR("Unable to lookup index record in database");
     2243        return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to lookup index record in database") };
     2244    }
     2245
     2246    if (result == SQLITE_DONE)
     2247        return { };
     2248
     2249    IDBKeyData objectStoreKey;
     2250    Vector<uint8_t> keyVector;
     2251    sql->getColumnBlobAsVector(0, keyVector);
     2252
     2253    if (!deserializeIDBKeyData(keyVector.data(), keyVector.size(), objectStoreKey)) {
     2254        LOG_ERROR("Unable to deserialize key looking up index record in database");
     2255        return { IDBDatabaseException::UnknownError, ASCIILiteral("Unable to deserialize key looking up index record in database") };
     2256    }
     2257
     2258    if (type == IndexedDB::IndexRecordType::Key) {
     2259        getResult = { objectStoreKey };
     2260        return { };
     2261    }
     2262
     2263    sql->getColumnBlobAsVector(1, keyVector);
     2264
     2265    int64_t recordID = sql->getColumnInt64(2);
     2266    Vector<String> blobURLs, blobFilePaths;
     2267    auto error = getBlobRecordsForObjectStoreRecord(recordID, blobURLs, blobFilePaths);
     2268    ASSERT(blobURLs.size() == blobFilePaths.size());
     2269
     2270    if (!error.isNull())
     2271        return error;
     2272
     2273    getResult = { { ThreadSafeDataBuffer::adoptVector(keyVector), WTFMove(blobURLs), WTFMove(blobFilePaths) }, objectStoreKey };
    21352274    return { };
    21362275}
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h

    r209197 r209824  
    9999    bool ensureValidRecordsTable();
    100100    bool ensureValidIndexRecordsTable();
     101    bool ensureValidIndexRecordsIndex();
    101102    bool ensureValidBlobTables();
    102103    std::unique_ptr<IDBDatabaseInfo> createAndPopulateInitialDatabaseInfo();
     
    107108    IDBError uncheckedSetKeyGeneratorValue(int64_t objectStoreID, uint64_t value);
    108109
    109     IDBError updateAllIndexesForAddRecord(const IDBObjectStoreInfo&, const IDBKeyData&, const ThreadSafeDataBuffer& value);
    110     IDBError updateOneIndexForAddRecord(const IDBIndexInfo&, const IDBKeyData&, const ThreadSafeDataBuffer& value);
    111     IDBError uncheckedPutIndexKey(const IDBIndexInfo&, const IDBKeyData& keyValue, const IndexKey&);
    112     IDBError uncheckedPutIndexRecord(int64_t objectStoreID, int64_t indexID, const IDBKeyData& keyValue, const IDBKeyData& indexKey);
     110    IDBError updateAllIndexesForAddRecord(const IDBObjectStoreInfo&, const IDBKeyData&, const ThreadSafeDataBuffer& value, int64_t recordID);
     111    IDBError updateOneIndexForAddRecord(const IDBIndexInfo&, const IDBKeyData&, const ThreadSafeDataBuffer& value, int64_t recordID);
     112    IDBError uncheckedPutIndexKey(const IDBIndexInfo&, const IDBKeyData& keyValue, const IndexKey&, int64_t recordID);
     113    IDBError uncheckedPutIndexRecord(int64_t objectStoreID, int64_t indexID, const IDBKeyData& keyValue, const IDBKeyData& indexKey, int64_t recordID);
    113114    IDBError uncheckedHasIndexRecord(const IDBIndexInfo&, const IDBKeyData&, bool& hasRecord);
     115    IDBError uncheckedGetIndexRecordForOneKey(int64_t indexeID, int64_t objectStoreID, IndexedDB::IndexRecordType, const IDBKeyData&, IDBGetResult&);
    114116
    115117    IDBError deleteUnusedBlobFileRecords(SQLiteIDBTransaction&);
     
    136138        HasIndexRecord,
    137139        PutIndexRecord,
     140        GetIndexRecordForOneKey,
    138141        DeleteIndexRecords,
    139142        RenameIndex,
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.cpp

    r208500 r209824  
    344344}
    345345
     346void SQLiteIDBCursor::markAsErrored()
     347{
     348    m_completed = true;
     349    m_errored = true;
     350    m_currentRecordRowID = 0;
     351}
     352
    346353SQLiteIDBCursor::AdvanceResult SQLiteIDBCursor::internalAdvanceOnce()
    347354{
     
    360367        m_currentPrimaryKey = IDBKeyData();
    361368        m_currentValue = nullptr;
     369        m_currentRecordRowID = 0;
    362370
    363371        return AdvanceResult::Success;
     
    366374    if (result != SQLITE_ROW) {
    367375        LOG_ERROR("Error advancing cursor - (%i) %s", result, m_transaction->sqliteTransaction()->database().lastErrorMsg());
    368         m_completed = true;
    369         m_errored = true;
     376        markAsErrored();
    370377        return AdvanceResult::Failure;
    371378    }
     379
     380    m_currentRecordRowID = m_statement->getColumnInt64(0);
     381    ASSERT(m_currentRecordRowID);
    372382
    373383    Vector<uint8_t> keyData;
     
    376386    if (!deserializeIDBKeyData(keyData.data(), keyData.size(), m_currentKey)) {
    377387        LOG_ERROR("Unable to deserialize key data from database while advancing cursor");
    378         m_completed = true;
    379         m_errored = true;
     388        markAsErrored();
    380389        return AdvanceResult::Failure;
    381390    }
    382391
    383392    m_statement->getColumnBlobAsVector(2, keyData);
    384 
    385     int64_t recordID = m_statement->getColumnInt64(0);
    386     ASSERT(recordID);
    387393
    388394    // The primaryKey of an ObjectStore cursor is the same as its key.
     
    391397
    392398        Vector<String> blobURLs, blobFilePaths;
    393         auto error = m_transaction->backingStore().getBlobRecordsForObjectStoreRecord(recordID, blobURLs, blobFilePaths);
     399        auto error = m_transaction->backingStore().getBlobRecordsForObjectStoreRecord(m_currentRecordRowID, blobURLs, blobFilePaths);
    394400        if (!error.isNull()) {
    395401            LOG_ERROR("Unable to fetch blob records from database while advancing cursor");
    396             m_completed = true;
    397             m_errored = true;
     402            markAsErrored();
    398403            return AdvanceResult::Failure;
    399404        }
     
    404409        if (!deserializeIDBKeyData(keyData.data(), keyData.size(), m_currentPrimaryKey)) {
    405410            LOG_ERROR("Unable to deserialize value data from database while advancing index cursor");
    406             m_completed = true;
    407             m_errored = true;
     411            markAsErrored();
    408412            return AdvanceResult::Failure;
    409413        }
     
    415419            || objectStoreStatement.bindInt64(2, m_objectStoreID) != SQLITE_OK) {
    416420            LOG_ERROR("Could not create index cursor statement into object store records (%i) '%s'", m_statement->database().lastError(), m_statement->database().lastErrorMsg());
    417             m_completed = true;
    418             m_errored = true;
     421            markAsErrored();
    419422            return AdvanceResult::Failure;
    420423        }
     
    431434        } else {
    432435            LOG_ERROR("Could not step index cursor statement into object store records (%i) '%s'", m_statement->database().lastError(), m_statement->database().lastErrorMsg());
    433             m_completed = true;
    434             m_errored = true;
     436            markAsErrored();
    435437            return AdvanceResult::Failure;
    436438
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.h

    r208646 r209824  
    6060
    6161    int64_t objectStoreID() const { return m_objectStoreID; }
     62    int64_t currentRecordRowID() const { return m_currentRecordRowID; }
    6263
    6364    const IDBKeyData& currentKey() const { return m_currentKey; }
     
    8182
    8283    void resetAndRebindStatement();
     84
     85    void markAsErrored();
    8386
    8487    enum class AdvanceResult {
     
    115118
    116119    bool m_backingStoreCursor { false };
     120    int64_t m_currentRecordRowID { 0 };
    117121};
    118122
  • trunk/Tools/ChangeLog

    r209804 r209824  
     12016-12-14  Brady Eidson  <beidson@apple.com>
     2
     3        IndexedDB 2.0: Massively speedup IDBIndex.get().
     4        https://bugs.webkit.org/show_bug.cgi?id=165802
     5
     6        Reviewed by Alex Christensen.
     7
     8        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     9        * TestWebKitAPI/Tests/WebKit2Cocoa/IDBIndexUpgradeToV2.html: Added.
     10        * TestWebKitAPI/Tests/WebKit2Cocoa/IDBIndexUpgradeToV2.mm: Added.
     11        * TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.blob: Added.
     12        * TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.sqlite3: Added.
     13
    1142016-12-14  Carlos Alberto Lopez Perez  <clopez@igalia.com>
    215
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r209558 r209824  
    120120                510477771D298E72009747EB /* IDBDeleteRecovery.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 510477761D298E57009747EB /* IDBDeleteRecovery.html */; };
    121121                510477781D29923B009747EB /* IDBDeleteRecovery.mm in Sources */ = {isa = PBXBuildFile; fileRef = 510477751D298E03009747EB /* IDBDeleteRecovery.mm */; };
     122                5110FCF11E01CD64006F8D0B /* IDBIndexUpgradeToV2.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5110FCF01E01CD53006F8D0B /* IDBIndexUpgradeToV2.html */; };
     123                5110FCF61E01CD83006F8D0B /* IndexUpgrade.sqlite3 in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5110FCF31E01CD77006F8D0B /* IndexUpgrade.sqlite3 */; };
     124                5110FCF91E01CD8A006F8D0B /* IndexUpgrade.blob in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5110FCF21E01CD77006F8D0B /* IndexUpgrade.blob */; };
     125                5110FCFA1E01CDB8006F8D0B /* IDBIndexUpgradeToV2.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5110FCEF1E01CBAA006F8D0B /* IDBIndexUpgradeToV2.mm */; };
    122126                51393E221523952D005F39C5 /* DOMWindowExtensionBasic_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51393E1D1523944A005F39C5 /* DOMWindowExtensionBasic_Bundle.cpp */; };
    123127                5142B2731517C8C800C32B19 /* ContextMenuCanCopyURL.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5142B2721517C89100C32B19 /* ContextMenuCanCopyURL.html */; };
     
    589593                        dstSubfolderSpec = 7;
    590594                        files = (
     595                                5110FCF91E01CD8A006F8D0B /* IndexUpgrade.blob in Copy Resources */,
     596                                5110FCF61E01CD83006F8D0B /* IndexUpgrade.sqlite3 in Copy Resources */,
     597                                5110FCF11E01CD64006F8D0B /* IDBIndexUpgradeToV2.html in Copy Resources */,
    591598                                5C9E56871DF914AE00C9EE33 /* contentBlockerCheck.html in Copy Resources */,
    592599                                07492B3C1DF8B86600633DE1 /* enumerateMediaDevices.html in Copy Resources */,
     
    918925                510477751D298E03009747EB /* IDBDeleteRecovery.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IDBDeleteRecovery.mm; sourceTree = "<group>"; };
    919926                510477761D298E57009747EB /* IDBDeleteRecovery.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = IDBDeleteRecovery.html; sourceTree = "<group>"; };
     927                5110FCEF1E01CBAA006F8D0B /* IDBIndexUpgradeToV2.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IDBIndexUpgradeToV2.mm; sourceTree = "<group>"; };
     928                5110FCF01E01CD53006F8D0B /* IDBIndexUpgradeToV2.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = IDBIndexUpgradeToV2.html; sourceTree = "<group>"; };
     929                5110FCF21E01CD77006F8D0B /* IndexUpgrade.blob */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = IndexUpgrade.blob; sourceTree = "<group>"; };
     930                5110FCF31E01CD77006F8D0B /* IndexUpgrade.sqlite3 */ = {isa = PBXFileReference; lastKnownFileType = file; path = IndexUpgrade.sqlite3; sourceTree = "<group>"; };
    920931                51393E1D1523944A005F39C5 /* DOMWindowExtensionBasic_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMWindowExtensionBasic_Bundle.cpp; sourceTree = "<group>"; };
    921932                51393E1E1523944A005F39C5 /* DOMWindowExtensionBasic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMWindowExtensionBasic.cpp; sourceTree = "<group>"; };
     
    14521463                                CDE195B31CFE0ADE0053D256 /* FullscreenTopContentInset.mm */,
    14531464                                510477751D298E03009747EB /* IDBDeleteRecovery.mm */,
     1465                                5110FCEF1E01CBAA006F8D0B /* IDBIndexUpgradeToV2.mm */,
    14541466                                51A587841D272EF3004BA9AF /* IndexedDBDatabaseProcessKill.mm */,
    14551467                                51BCEE491C84F4AF0042C82E /* IndexedDBMultiProcess.mm */,
     
    16191631                                510477701D298D85009747EB /* IDBDeleteRecovery.sqlite3-shm */,
    16201632                                510477711D298D85009747EB /* IDBDeleteRecovery.sqlite3-wal */,
     1633                                5110FCF01E01CD53006F8D0B /* IDBIndexUpgradeToV2.html */,
     1634                                5110FCF21E01CD77006F8D0B /* IndexUpgrade.blob */,
     1635                                5110FCF31E01CD77006F8D0B /* IndexUpgrade.sqlite3 */,
    16211636                                51A587821D272EB5004BA9AF /* IndexedDBDatabaseProcessKill-1.html */,
    16221637                                51BCEE4C1C84F52C0042C82E /* IndexedDBMultiProcess-1.html */,
     
    26522667                                7C83E0B51D0A649300FEBCF3 /* WKRetainPtr.cpp in Sources */,
    26532668                                9C64DC321D76198A004B598E /* YouTubePluginReplacement.cpp in Sources */,
     2669                                5110FCFA1E01CDB8006F8D0B /* IDBIndexUpgradeToV2.mm in Sources */,
    26542670                                5E4B1D2E1D404C6100053621 /* WKScrollViewDelegateCrash.mm in Sources */,
    26552671                                7CCE7F221A411AE600447C4C /* WKString.cpp in Sources */,
Note: See TracChangeset for help on using the changeset viewer.