Title: [196038] trunk
Revision
196038
Author
[email protected]
Date
2016-02-02 16:12:23 -0800 (Tue, 02 Feb 2016)

Log 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:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (196037 => 196038)


--- trunk/LayoutTests/ChangeLog	2016-02-03 00:09:33 UTC (rev 196037)
+++ trunk/LayoutTests/ChangeLog	2016-02-03 00:12:23 UTC (rev 196038)
@@ -1,3 +1,12 @@
+2016-02-02  Brady Eidson  <[email protected]>
+
+        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.
+
+        * platform/mac-wk1/TestExpectations:
+
 2016-02-02  Tim Horton  <[email protected]>
 
         <attachment> should attempt to guess the icon from the file extension if all else fails

Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (196037 => 196038)


--- trunk/LayoutTests/platform/mac-wk1/TestExpectations	2016-02-03 00:09:33 UTC (rev 196037)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations	2016-02-03 00:12:23 UTC (rev 196038)
@@ -253,18 +253,15 @@
 ########################################
 ### START OF (3) IndexedDB failures with SQLite
 
-# Completes successfully after ~40 seconds in a debug build with logging
+# Completes with passing results, but too slowly for our test timeouts.
 imported/w3c/indexeddb/idbindex-multientry-big.htm [ Failure ]
+imported/w3c/indexeddb/idbcursor_iterating.htm [ Failure ]
 
-# Integer part of the test iterates 0, 1, 2, Inf, -1, -2, -Inf - Should be in order from -Inf to Inf.
-storage/indexeddb/cursor-primary-key-order.html [ Failure ]
-
 # SQLite backend tests that timeout
 storage/indexeddb/modern/transaction-scheduler-1.html [ Skip ]
 storage/indexeddb/modern/transaction-scheduler-2.html [ Skip ]
 storage/indexeddb/modern/transaction-scheduler-5.html [ Skip ]
 storage/indexeddb/modern/transaction-scheduler-6.html [ Skip ]
-storage/indexeddb/prefetch-invalidation.html [ Skip ]
 storage/indexeddb/transaction-coordination-within-database.html [ Skip ]
 
 ### END OF (3) IndexedDB failures with SQLite

Modified: trunk/Source/WebCore/ChangeLog (196037 => 196038)


--- trunk/Source/WebCore/ChangeLog	2016-02-03 00:09:33 UTC (rev 196037)
+++ trunk/Source/WebCore/ChangeLog	2016-02-03 00:12:23 UTC (rev 196038)
@@ -1,3 +1,25 @@
+2016-02-02  Brady Eidson  <[email protected]>
+
+        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.
+
+        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:
+
 2016-02-02  Tim Horton  <[email protected]>
 
         <attachment> should attempt to guess the icon from the file extension if all else fails

Modified: trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp (196037 => 196038)


--- trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp	2016-02-03 00:09:33 UTC (rev 196037)
+++ trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp	2016-02-03 00:12:23 UTC (rev 196038)
@@ -109,6 +109,41 @@
     return v2RecordsTableSchemaString;
 }
 
+static const String v1IndexRecordsTableSchema(const String& tableName)
+{
+    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)");
+}
+
+static const String& v1IndexRecordsTableSchema()
+{
+    static NeverDestroyed<WTF::String> v1IndexRecordsTableSchemaString(v1IndexRecordsTableSchema("IndexRecords"));
+    return v1IndexRecordsTableSchemaString;
+}
+
+static const String& v1IndexRecordsTableSchemaAlternate()
+{
+    static NeverDestroyed<WTF::String> v1IndexRecordsTableSchemaString(v1IndexRecordsTableSchema("\"IndexRecords\""));
+    return v1IndexRecordsTableSchemaString;
+}
+
+static const String v2IndexRecordsTableSchema(const String& tableName)
+{
+    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)");
+}
+
+static const String& v2IndexRecordsTableSchema()
+{
+    static NeverDestroyed<WTF::String> v2IndexRecordsTableSchemaString(v2IndexRecordsTableSchema("IndexRecords"));
+    return v2IndexRecordsTableSchemaString;
+}
+
+static const String& v2IndexRecordsTableSchemaAlternate()
+{
+    static NeverDestroyed<WTF::String> v2IndexRecordsTableSchemaString(v2IndexRecordsTableSchema("\"IndexRecords\""));
+    return v2IndexRecordsTableSchemaString;
+}
+
+
 SQLiteIDBBackingStore::SQLiteIDBBackingStore(const IDBDatabaseIdentifier& identifier, const String& databaseRootDirectory)
     : m_identifier(identifier)
 {
@@ -240,6 +275,80 @@
     return true;
 }
 
+bool SQLiteIDBBackingStore::ensureValidIndexRecordsTable()
+{
+    ASSERT(m_sqliteDB);
+    ASSERT(m_sqliteDB->isOpen());
+
+    String currentSchema;
+    {
+        // Fetch the schema for an existing index record table.
+        SQLiteStatement statement(*m_sqliteDB, "SELECT type, sql FROM sqlite_master WHERE tbl_name='IndexRecords'");
+        if (statement.prepare() != SQLITE_OK) {
+            LOG_ERROR("Unable to prepare statement to fetch schema for the IndexRecords table.");
+            return false;
+        }
+
+        int sqliteResult = statement.step();
+
+        // If there is no IndexRecords table at all, create it and then bail.
+        if (sqliteResult == SQLITE_DONE) {
+            if (!m_sqliteDB->executeCommand(v2IndexRecordsTableSchema())) {
+                LOG_ERROR("Could not create IndexRecords table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+                return false;
+            }
+
+            return true;
+        }
+
+        if (sqliteResult != SQLITE_ROW) {
+            LOG_ERROR("Error executing statement to fetch schema for the IndexRecords table.");
+            return false;
+        }
+
+        currentSchema = statement.getColumnText(1);
+    }
+
+    ASSERT(!currentSchema.isEmpty());
+
+    // If the schema in the backing store is the current schema, we're done.
+    if (currentSchema == v2IndexRecordsTableSchema() || currentSchema == v2IndexRecordsTableSchemaAlternate())
+        return true;
+
+    // If the record table is not the current schema then it must be one of the previous schemas.
+    // If it is not then the database is in an unrecoverable state and this should be considered a fatal error.
+    if (currentSchema != v1IndexRecordsTableSchema() && currentSchema != v1IndexRecordsTableSchemaAlternate())
+        RELEASE_ASSERT_NOT_REACHED();
+
+    SQLiteTransaction transaction(*m_sqliteDB);
+    transaction.begin();
+
+    // Create a temporary table with the correct schema and migrate all existing content over.
+    if (!m_sqliteDB->executeCommand(v2IndexRecordsTableSchema("_Temp_IndexRecords"))) {
+        LOG_ERROR("Could not create temporary index records table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+        return false;
+    }
+
+    if (!m_sqliteDB->executeCommand("INSERT INTO _Temp_IndexRecords SELECT * FROM IndexRecords")) {
+        LOG_ERROR("Could not migrate existing IndexRecords content (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+        return false;
+    }
+
+    if (!m_sqliteDB->executeCommand("DROP TABLE IndexRecords")) {
+        LOG_ERROR("Could not drop existing IndexRecords table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+        return false;
+    }
+
+    if (!m_sqliteDB->executeCommand("ALTER TABLE _Temp_IndexRecords RENAME TO IndexRecords")) {
+        LOG_ERROR("Could not rename temporary IndexRecords table (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
+        return false;
+    }
+
+    transaction.commit();
+
+    return true;
+}
+
 std::unique_ptr<IDBDatabaseInfo> SQLiteIDBBackingStore::createAndPopulateInitialDatabaseInfo()
 {
     ASSERT(m_sqliteDB);
@@ -263,7 +372,7 @@
         return nullptr;
     }
 
-    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);")) {
+    if (!ensureValidIndexRecordsTable()) {
         LOG_ERROR("Could not create IndexRecords table in database (%i) - %s", m_sqliteDB->lastError(), m_sqliteDB->lastErrorMsg());
         m_sqliteDB = nullptr;
         return nullptr;

Modified: trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h (196037 => 196038)


--- trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h	2016-02-03 00:09:33 UTC (rev 196037)
+++ trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h	2016-02-03 00:12:23 UTC (rev 196038)
@@ -84,6 +84,7 @@
     String fullDatabasePath() const;
 
     bool ensureValidRecordsTable();
+    bool ensureValidIndexRecordsTable();
     std::unique_ptr<IDBDatabaseInfo> createAndPopulateInitialDatabaseInfo();
     std::unique_ptr<IDBDatabaseInfo> extractExistingDatabaseInfo();
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to