Changeset 196038 in webkit


Ignore:
Timestamp:
Feb 2, 2016 4:12:23 PM (8 years ago)
Author:
beidson@apple.com
Message:

Modern IDB: storage/indexeddb/cursor-primary-key-order.html fails with SQLite backend.
https://bugs.webkit.org/show_bug.cgi?id=153800

Reviewed by Alex Christensen.

Source/WebCore:

No new tests (Existing tests now unskipped).

The IndexRecords SQL schema did not order things by primaryKey.

Easy fix to the schema. Sadly requires a migration...

  • Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:

(WebCore::IDBServer::v1IndexRecordsTableSchema):
(WebCore::IDBServer::v1IndexRecordsTableSchemaAlternate):
(WebCore::IDBServer::v2IndexRecordsTableSchema):
(WebCore::IDBServer::v2IndexRecordsTableSchemaAlternate):
(WebCore::IDBServer::SQLiteIDBBackingStore::ensureValidIndexRecordsTable):
(WebCore::IDBServer::SQLiteIDBBackingStore::createAndPopulateInitialDatabaseInfo):

  • Modules/indexeddb/server/SQLiteIDBBackingStore.h:

LayoutTests:

  • platform/mac-wk1/TestExpectations:
Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r196036 r196038  
     12016-02-02  Brady Eidson  <beidson@apple.com>
     2
     3        Modern IDB: storage/indexeddb/cursor-primary-key-order.html fails with SQLite backend.
     4        https://bugs.webkit.org/show_bug.cgi?id=153800
     5
     6        Reviewed by Alex Christensen.
     7
     8        * platform/mac-wk1/TestExpectations:
     9
    1102016-02-02  Tim Horton  <timothy_horton@apple.com>
    211
  • trunk/LayoutTests/platform/mac-wk1/TestExpectations

    r196025 r196038  
    254254### START OF (3) IndexedDB failures with SQLite
    255255
    256 # Completes successfully after ~40 seconds in a debug build with logging
     256# Completes with passing results, but too slowly for our test timeouts.
    257257imported/w3c/indexeddb/idbindex-multientry-big.htm [ Failure ]
    258 
    259 # Integer part of the test iterates 0, 1, 2, Inf, -1, -2, -Inf - Should be in order from -Inf to Inf.
    260 storage/indexeddb/cursor-primary-key-order.html [ Failure ]
     258imported/w3c/indexeddb/idbcursor_iterating.htm [ Failure ]
    261259
    262260# SQLite backend tests that timeout
     
    265263storage/indexeddb/modern/transaction-scheduler-5.html [ Skip ]
    266264storage/indexeddb/modern/transaction-scheduler-6.html [ Skip ]
    267 storage/indexeddb/prefetch-invalidation.html [ Skip ]
    268265storage/indexeddb/transaction-coordination-within-database.html [ Skip ]
    269266
  • trunk/Source/WebCore/ChangeLog

    r196036 r196038  
     12016-02-02  Brady Eidson  <beidson@apple.com>
     2
     3        Modern IDB: storage/indexeddb/cursor-primary-key-order.html fails with SQLite backend.
     4        https://bugs.webkit.org/show_bug.cgi?id=153800
     5
     6        Reviewed by Alex Christensen.
     7
     8        No new tests (Existing tests now unskipped).
     9
     10        The IndexRecords SQL schema did not order things by primaryKey.
     11       
     12        Easy fix to the schema. Sadly requires a migration...
     13
     14        * Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
     15        (WebCore::IDBServer::v1IndexRecordsTableSchema):
     16        (WebCore::IDBServer::v1IndexRecordsTableSchemaAlternate):
     17        (WebCore::IDBServer::v2IndexRecordsTableSchema):
     18        (WebCore::IDBServer::v2IndexRecordsTableSchemaAlternate):
     19        (WebCore::IDBServer::SQLiteIDBBackingStore::ensureValidIndexRecordsTable):
     20        (WebCore::IDBServer::SQLiteIDBBackingStore::createAndPopulateInitialDatabaseInfo):
     21        * Modules/indexeddb/server/SQLiteIDBBackingStore.h:
     22
    1232016-02-02  Tim Horton  <timothy_horton@apple.com>
    224
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp

    r195850 r196038  
    110110}
    111111
     112static const String v1IndexRecordsTableSchema(const String& tableName)
     113{
     114    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 NOT NULL ON CONFLICT FAIL)");
     115}
     116
     117static const String& v1IndexRecordsTableSchema()
     118{
     119    static NeverDestroyed<WTF::String> v1IndexRecordsTableSchemaString(v1IndexRecordsTableSchema("IndexRecords"));
     120    return v1IndexRecordsTableSchemaString;
     121}
     122
     123static const String& v1IndexRecordsTableSchemaAlternate()
     124{
     125    static NeverDestroyed<WTF::String> v1IndexRecordsTableSchemaString(v1IndexRecordsTableSchema("\"IndexRecords\""));
     126    return v1IndexRecordsTableSchemaString;
     127}
     128
     129static const String v2IndexRecordsTableSchema(const String& tableName)
     130{
     131    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)");
     132}
     133
     134static const String& v2IndexRecordsTableSchema()
     135{
     136    static NeverDestroyed<WTF::String> v2IndexRecordsTableSchemaString(v2IndexRecordsTableSchema("IndexRecords"));
     137    return v2IndexRecordsTableSchemaString;
     138}
     139
     140static const String& v2IndexRecordsTableSchemaAlternate()
     141{
     142    static NeverDestroyed<WTF::String> v2IndexRecordsTableSchemaString(v2IndexRecordsTableSchema("\"IndexRecords\""));
     143    return v2IndexRecordsTableSchemaString;
     144}
     145
     146
    112147SQLiteIDBBackingStore::SQLiteIDBBackingStore(const IDBDatabaseIdentifier& identifier, const String& databaseRootDirectory)
    113148    : m_identifier(identifier)
     
    241276}
    242277
     278bool SQLiteIDBBackingStore::ensureValidIndexRecordsTable()
     279{
     280    ASSERT(m_sqliteDB);
     281    ASSERT(m_sqliteDB->isOpen());
     282
     283    String currentSchema;
     284    {
     285        // Fetch the schema for an existing index record table.
     286        SQLiteStatement statement(*m_sqliteDB, "SELECT type, sql FROM sqlite_master WHERE tbl_name='IndexRecords'");
     287        if (statement.prepare() != SQLITE_OK) {
     288            LOG_ERROR("Unable to prepare statement to fetch schema for the IndexRecords table.");
     289            return false;
     290        }
     291
     292        int sqliteResult = statement.step();
     293
     294        // If there is no IndexRecords table at all, create it and then bail.
     295        if (sqliteResult == SQLITE_DONE) {
     296            if (!m_sqliteDB->executeCommand(v2IndexRecordsTableSchema())) {
     297                LOG_ERROR("Could not create IndexRecords table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
     298                return false;
     299            }
     300
     301            return true;
     302        }
     303
     304        if (sqliteResult != SQLITE_ROW) {
     305            LOG_ERROR("Error executing statement to fetch schema for the IndexRecords table.");
     306            return false;
     307        }
     308
     309        currentSchema = statement.getColumnText(1);
     310    }
     311
     312    ASSERT(!currentSchema.isEmpty());
     313
     314    // If the schema in the backing store is the current schema, we're done.
     315    if (currentSchema == v2IndexRecordsTableSchema() || currentSchema == v2IndexRecordsTableSchemaAlternate())
     316        return true;
     317
     318    // If the record table is not the current schema then it must be one of the previous schemas.
     319    // If it is not then the database is in an unrecoverable state and this should be considered a fatal error.
     320    if (currentSchema != v1IndexRecordsTableSchema() && currentSchema != v1IndexRecordsTableSchemaAlternate())
     321        RELEASE_ASSERT_NOT_REACHED();
     322
     323    SQLiteTransaction transaction(*m_sqliteDB);
     324    transaction.begin();
     325
     326    // Create a temporary table with the correct schema and migrate all existing content over.
     327    if (!m_sqliteDB->executeCommand(v2IndexRecordsTableSchema("_Temp_IndexRecords"))) {
     328        LOG_ERROR("Could not create temporary index records table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
     329        return false;
     330    }
     331
     332    if (!m_sqliteDB->executeCommand("INSERT INTO _Temp_IndexRecords SELECT * FROM IndexRecords")) {
     333        LOG_ERROR("Could not migrate existing IndexRecords content (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
     334        return false;
     335    }
     336
     337    if (!m_sqliteDB->executeCommand("DROP TABLE IndexRecords")) {
     338        LOG_ERROR("Could not drop existing IndexRecords table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
     339        return false;
     340    }
     341
     342    if (!m_sqliteDB->executeCommand("ALTER TABLE _Temp_IndexRecords RENAME TO IndexRecords")) {
     343        LOG_ERROR("Could not rename temporary IndexRecords table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
     344        return false;
     345    }
     346
     347    transaction.commit();
     348
     349    return true;
     350}
     351
    243352std::unique_ptr<IDBDatabaseInfo> SQLiteIDBBackingStore::createAndPopulateInitialDatabaseInfo()
    244353{
     
    264373    }
    265374
    266     if (!m_sqliteDB->executeCommand("CREATE TABLE IndexRecords (indexID INTEGER NOT NULL ON CONFLICT FAIL, objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, key TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL, value NOT NULL ON CONFLICT FAIL);")) {
     375    if (!ensureValidIndexRecordsTable()) {
    267376        LOG_ERROR("Could not create IndexRecords table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
    268377        m_sqliteDB = nullptr;
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h

    r195765 r196038  
    8585
    8686    bool ensureValidRecordsTable();
     87    bool ensureValidIndexRecordsTable();
    8788    std::unique_ptr<IDBDatabaseInfo> createAndPopulateInitialDatabaseInfo();
    8889    std::unique_ptr<IDBDatabaseInfo> extractExistingDatabaseInfo();
Note: See TracChangeset for help on using the changeset viewer.