<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[175378] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/175378">175378</a></dd>
<dt>Author</dt> <dd>beidson@apple.com</dd>
<dt>Date</dt> <dd>2014-10-30 14:00:58 -0700 (Thu, 30 Oct 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>IndexedDB is deleting data when a PK is shared amongst two objectStores
rdar://problem/18479306 and https://bugs.webkit.org/show_bug.cgi?id=137154

Reviewed by Jer Noble.

Source/WebKit2:

* DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp:
(WebKit::v1RecordsTableSchema): Store away the v1 schema for introspection into the database.
(WebKit::v2RecordsTableSchema): Add utility methods to get the v2 schema with different Table names.
(WebKit::createOrMigrateRecordsTableIfNecessary): Check to see if the Records table exists with
  the correct schema. If it is the v1 schema, then migrate the data to a new v2 table, drop the v1
  table, then slide the new table into place.
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::ensureValidRecordsTable): Make sure the Records table
  exists and is v2, and then make sure the uniqueness index exists.
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::createAndPopulateInitialMetadata): Don’t bother creating
  the Records table here as it will have already been established earlier.
(WebKit::UniqueIDBDatabaseBackingStoreSQLite::getOrEstablishMetadata):
* DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h:

LayoutTests:

* storage/indexeddb/primary-key-unique-to-objectstore-expected.txt: Added.
* storage/indexeddb/primary-key-unique-to-objectstore.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2DatabaseProcessIndexedDBsqliteUniqueIDBDatabaseBackingStoreSQLitecpp">trunk/Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp</a></li>
<li><a href="#trunkSourceWebKit2DatabaseProcessIndexedDBsqliteUniqueIDBDatabaseBackingStoreSQLiteh">trunk/Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsstorageindexeddbprimarykeyuniquetoobjectstoreexpectedtxt">trunk/LayoutTests/storage/indexeddb/primary-key-unique-to-objectstore-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstorageindexeddbprimarykeyuniquetoobjectstorehtml">trunk/LayoutTests/storage/indexeddb/primary-key-unique-to-objectstore.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (175377 => 175378)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-10-30 20:57:57 UTC (rev 175377)
+++ trunk/LayoutTests/ChangeLog        2014-10-30 21:00:58 UTC (rev 175378)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2014-10-30  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        IndexedDB is deleting data when a PK is shared amongst two objectStores
+        rdar://problem/18479306 and https://bugs.webkit.org/show_bug.cgi?id=137154
+
+        Reviewed by Jer Noble.
+
+        * storage/indexeddb/primary-key-unique-to-objectstore-expected.txt: Added.
+        * storage/indexeddb/primary-key-unique-to-objectstore.html: Added.
+
</ins><span class="cx"> 2014-10-30  Jer Noble  &lt;jer.noble@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed gardening; rebaseline two media/ tests.
</span></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbprimarykeyuniquetoobjectstoreexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/primary-key-unique-to-objectstore-expected.txt (0 => 175378)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/primary-key-unique-to-objectstore-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/primary-key-unique-to-objectstore-expected.txt        2014-10-30 21:00:58 UTC (rev 175378)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+About to add person and note
+Successfully added person
+Successfully added note
+Successfully got person
+name
+id
+Successfully got note
+note
+uid
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstorageindexeddbprimarykeyuniquetoobjectstorehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/indexeddb/primary-key-unique-to-objectstore.html (0 => 175378)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/indexeddb/primary-key-unique-to-objectstore.html                                (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/primary-key-unique-to-objectstore.html        2014-10-30 21:00:58 UTC (rev 175378)
</span><span class="lines">@@ -0,0 +1,147 @@
</span><ins>+&lt;body&gt;
+&lt;div id=&quot;logger&quot;&gt;&lt;/div&gt;
+&lt;script&gt;
+if (testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+}
+
+function log(msg) {
+    document.getElementById(&quot;logger&quot;).innerHTML += msg + &quot;&lt;br&gt;&quot;;
+}
+
+var openRequest = indexedDB.open(&quot;pkutos&quot;, 1);
+
+openRequest.onupgradeneeded = function(e) {
+    var thisDB = e.target.result;
+
+    if(!thisDB.objectStoreNames.contains(&quot;people&quot;)) {
+        thisDB.createObjectStore(&quot;people&quot;, {keyPath:&quot;id&quot;});
+    }
+
+    if(!thisDB.objectStoreNames.contains(&quot;notes&quot;)) {
+        thisDB.createObjectStore(&quot;notes&quot;, {keyPath:&quot;uid&quot;});
+    }
+}
+
+openRequest.onsuccess = function(e) {
+    db = e.target.result;
+    addPerson();
+}    
+
+openRequest.onerror = function(e) {
+    log(&quot;openRequest error - &quot; + e);
+}
+
+var sharedID = 0;
+
+function addPerson() {
+    log(&quot;About to add person and note&quot;);
+
+    //Get a transaction
+    //default for OS list is all, default for type is read
+    var transaction = db.transaction([&quot;people&quot;], &quot;readwrite&quot;);
+
+    //Ask for the objectStore
+    var store = transaction.objectStore(&quot;people&quot;);
+
+    //Define a person
+    var person = {
+        name: &quot;Person&quot;,
+        id: sharedID
+    }
+
+    //Perform the add
+    var request = store.add(person);
+
+    request.onerror = function(e) {
+        log(&quot;Error adding person - &quot;, e);
+    }
+
+    request.onsuccess = function(e) {
+        log(&quot;Successfully added person&quot;);
+        setTimeout(&quot;addComplete();&quot;, 0);
+    }
+    
+    //Define a note
+    var note = {
+        note: &quot;Note&quot;,
+        uid: sharedID
+    }
+
+    var transaction2 = db.transaction([&quot;notes&quot;], &quot;readwrite&quot;);
+
+    //Ask for the objectStore
+    var store2 = transaction2.objectStore(&quot;notes&quot;);
+
+    //Perform the add
+    var request2 = store2.add(note);
+
+    request2.onerror = function(e) {
+        log(&quot;Error adding note - &quot;, e);
+    }
+
+    request2.onsuccess = function(e) {
+        log(&quot;Successfully added note&quot;);
+        setTimeout(&quot;addComplete();&quot;, 0);
+    }
+    
+}
+
+var completedAdds = 0;
+function addComplete()
+{
+    if (++completedAdds &lt; 2)
+        return;
+
+    //Get a transaction
+    var transaction = db.transaction([&quot;people&quot;], &quot;readwrite&quot;);
+
+    //Ask for the objectStore
+    var store = transaction.objectStore(&quot;people&quot;);
+
+    //Perform the add
+    var request = store.get(sharedID);
+
+    request.onerror = function(e) {
+        log(&quot;Error getting person - &quot;, e);
+    }
+
+    request.onsuccess = function(e) {
+        log(&quot;Successfully got person&quot;);
+        for (n in e.target.result) {
+            log(n);
+        }
+        getComplete();
+    }
+
+    var transaction2 = db.transaction([&quot;notes&quot;], &quot;readwrite&quot;);
+
+    //Ask for the objectStore
+    var store2 = transaction2.objectStore(&quot;notes&quot;);
+
+    //Perform the add
+    var request2 = store2.get(sharedID);
+
+    request2.onerror = function(e) {
+        log(&quot;Error getting note - &quot;, e);
+    }
+
+    request2.onsuccess = function(e) {
+        log(&quot;Successfully got note&quot;);
+        for (n in e.target.result) {
+            log(n);
+        }
+        getComplete();
+    }
+}
+
+var completedGets = 0;
+function getComplete()
+{
+    if (++completedGets == 2 &amp;&amp; testRunner)
+        testRunner.notifyDone();
+}
+&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (175377 => 175378)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-10-30 20:57:57 UTC (rev 175377)
+++ trunk/Source/WebKit2/ChangeLog        2014-10-30 21:00:58 UTC (rev 175378)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2014-10-30  Brady Eidson  &lt;beidson@apple.com&gt;
+
+        IndexedDB is deleting data when a PK is shared amongst two objectStores
+        rdar://problem/18479306 and https://bugs.webkit.org/show_bug.cgi?id=137154
+
+        Reviewed by Jer Noble.
+
+        * DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp:
+        (WebKit::v1RecordsTableSchema): Store away the v1 schema for introspection into the database.
+        (WebKit::v2RecordsTableSchema): Add utility methods to get the v2 schema with different Table names.
+        (WebKit::createOrMigrateRecordsTableIfNecessary): Check to see if the Records table exists with
+          the correct schema. If it is the v1 schema, then migrate the data to a new v2 table, drop the v1
+          table, then slide the new table into place.
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::ensureValidRecordsTable): Make sure the Records table
+          exists and is v2, and then make sure the uniqueness index exists.
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::createAndPopulateInitialMetadata): Don’t bother creating
+          the Records table here as it will have already been established earlier.
+        (WebKit::UniqueIDBDatabaseBackingStoreSQLite::getOrEstablishMetadata):
+        * DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h:
+
</ins><span class="cx"> 2014-10-30  Beth Dakin  &lt;bdakin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement action menus for text
</span></span></pre></div>
<a id="trunkSourceWebKit2DatabaseProcessIndexedDBsqliteUniqueIDBDatabaseBackingStoreSQLitecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp (175377 => 175378)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp        2014-10-30 20:57:57 UTC (rev 175377)
+++ trunk/Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.cpp        2014-10-30 21:00:58 UTC (rev 175378)
</span><span class="lines">@@ -41,7 +41,9 @@
</span><span class="cx"> #include &lt;WebCore/IDBKeyRange.h&gt;
</span><span class="cx"> #include &lt;WebCore/SQLiteDatabase.h&gt;
</span><span class="cx"> #include &lt;WebCore/SQLiteStatement.h&gt;
</span><ins>+#include &lt;WebCore/SQLiteTransaction.h&gt;
</ins><span class="cx"> #include &lt;WebCore/SharedBuffer.h&gt;
</span><ins>+#include &lt;wtf/NeverDestroyed.h&gt;
</ins><span class="cx"> #include &lt;wtf/RunLoop.h&gt;
</span><span class="cx"> 
</span><span class="cx"> using namespace JSC;
</span><span class="lines">@@ -52,6 +54,29 @@
</span><span class="cx"> // Current version of the metadata schema being used in the metadata database.
</span><span class="cx"> static const int currentMetadataVersion = 1;
</span><span class="cx"> 
</span><ins>+static const String&amp; v1RecordsTableSchema()
+{
+    static NeverDestroyed&lt;WTF::String&gt; v1RecordsTableSchemaString(ASCIILiteral(
+        &quot;CREATE TABLE Records (objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, key TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE, value NOT NULL ON CONFLICT FAIL)&quot;));
+    return v1RecordsTableSchemaString;
+}
+
+static const String v2RecordsTableSchema(const String&amp; tableName)
+{
+    StringBuilder builder;
+    builder.append(&quot;CREATE TABLE &quot;);
+    builder.append(tableName);
+    builder.append(&quot; (objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, key TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL, value NOT NULL ON CONFLICT FAIL)&quot;);
+
+    return builder.toString();
+}
+
+static const String&amp; v2RecordsTableSchema()
+{
+    static NeverDestroyed&lt;WTF::String&gt; v2RecordsTableSchemaString(v2RecordsTableSchema(&quot;Records&quot;));
+    return v2RecordsTableSchemaString;
+}
+
</ins><span class="cx"> static int64_t generateDatabaseId()
</span><span class="cx"> {
</span><span class="cx">     static int64_t databaseID = 0;
</span><span class="lines">@@ -82,6 +107,97 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static bool createOrMigrateRecordsTableIfNecessary(SQLiteDatabase&amp; database)
+{
+    String currentSchema;
+    {
+        // Fetch the schema for an existing records table.
+        SQLiteStatement statement(database, &quot;SELECT type, sql FROM sqlite_master WHERE tbl_name='Records'&quot;);
+        if (statement.prepare() != SQLResultOk) {
+            LOG_ERROR(&quot;Unable to prepare statement to fetch schema for the Records table.&quot;);
+            return false;
+        }
+
+        int sqliteResult = statement.step();
+
+        // If there is no Records table at all, create it and then bail.
+        if (sqliteResult == SQLResultDone) {
+            if (!database.executeCommand(v2RecordsTableSchema())) {
+                LOG_ERROR(&quot;Could not create Records table in database (%i) - %s&quot;, database.lastError(), database.lastErrorMsg());
+                return false;
+            }
+
+            return true;
+        }
+
+        if (sqliteResult != SQLResultRow) {
+            LOG_ERROR(&quot;Error executing statement to fetch schema for the Records table.&quot;);
+            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 == v2RecordsTableSchema())
+        return true;
+
+    // Currently the Records table should only be one of either the v1 or v2 schemas.
+    if (currentSchema != v1RecordsTableSchema()) {
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+    SQLiteTransaction transaction(database);
+    transaction.begin();
+
+    // Create a temporary table with the correct schema and migrate all existing content over.
+    if (!database.executeCommand(v2RecordsTableSchema(&quot;_Temp_Records&quot;))) {
+        LOG_ERROR(&quot;Could not create temporary records table in database (%i) - %s&quot;, database.lastError(), database.lastErrorMsg());
+        return false;
+    }
+
+    if (!database.executeCommand(&quot;INSERT INTO _Temp_Records SELECT * FROM Records&quot;)) {
+        LOG_ERROR(&quot;Could not migrate existing Records content (%i) - %s&quot;, database.lastError(), database.lastErrorMsg());
+        return false;
+    }
+
+    if (!database.executeCommand(&quot;DROP TABLE Records&quot;)) {
+        LOG_ERROR(&quot;Could not drop existing Records table (%i) - %s&quot;, database.lastError(), database.lastErrorMsg());
+        return false;
+    }
+
+    if (!database.executeCommand(&quot;ALTER TABLE _Temp_Records RENAME TO Records&quot;)) {
+        LOG_ERROR(&quot;Could not rename temporary Records table (%i) - %s&quot;, database.lastError(), database.lastErrorMsg());
+        return false;
+    }
+
+    transaction.commit();
+
+    return true;
+}
+
+bool UniqueIDBDatabaseBackingStoreSQLite::ensureValidRecordsTable()
+{
+    ASSERT(!RunLoop::isMain());
+    ASSERT(m_sqliteDB);
+    ASSERT(m_sqliteDB-&gt;isOpen());
+
+    if (!createOrMigrateRecordsTableIfNecessary(*m_sqliteDB))
+        return false;
+
+    // Whether the updated records table already existed or if it was just created and the data migrated over,
+    // make sure the uniqueness index exists.
+    if (!m_sqliteDB-&gt;executeCommand(&quot;CREATE UNIQUE INDEX IF NOT EXISTS RecordsIndex ON Records (objectStoreID, key);&quot;)) {
+        LOG_ERROR(&quot;Could not create RecordsIndex on Records table in database (%i) - %s&quot;, m_sqliteDB-&gt;lastError(), m_sqliteDB-&gt;lastErrorMsg());
+        return false;
+    }
+
+    return true;
+}
+
</ins><span class="cx"> std::unique_ptr&lt;IDBDatabaseMetadata&gt; UniqueIDBDatabaseBackingStoreSQLite::createAndPopulateInitialMetadata()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!RunLoop::isMain());
</span><span class="lines">@@ -106,12 +222,6 @@
</span><span class="cx">         return nullptr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!m_sqliteDB-&gt;executeCommand(&quot;CREATE TABLE Records (objectStoreID INTEGER NOT NULL ON CONFLICT FAIL, key TEXT COLLATE IDBKEY NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE, value NOT NULL ON CONFLICT FAIL);&quot;)) {
-        LOG_ERROR(&quot;Could not create Records table in database (%i) - %s&quot;, m_sqliteDB-&gt;lastError(), m_sqliteDB-&gt;lastErrorMsg());
-        m_sqliteDB = nullptr;
-        return nullptr;
-    }
-
</del><span class="cx">     if (!m_sqliteDB-&gt;executeCommand(&quot;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);&quot;)) {
</span><span class="cx">         LOG_ERROR(&quot;Could not create IndexRecords table in database (%i) - %s&quot;, m_sqliteDB-&gt;lastError(), m_sqliteDB-&gt;lastErrorMsg());
</span><span class="cx">         m_sqliteDB = nullptr;
</span><span class="lines">@@ -317,6 +427,12 @@
</span><span class="cx">         return idbKeyCollate(aLength, a, bLength, b);
</span><span class="cx">     });
</span><span class="cx"> 
</span><ins>+    if (!ensureValidRecordsTable()) {
+        LOG_ERROR(&quot;Error creating or migrating Records table in database&quot;);
+        m_sqliteDB = nullptr;
+        return nullptr;
+    }
+
</ins><span class="cx">     std::unique_ptr&lt;IDBDatabaseMetadata&gt; metadata = extractExistingMetadata();
</span><span class="cx">     if (!metadata)
</span><span class="cx">         metadata = createAndPopulateInitialMetadata();
</span></span></pre></div>
<a id="trunkSourceWebKit2DatabaseProcessIndexedDBsqliteUniqueIDBDatabaseBackingStoreSQLiteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h (175377 => 175378)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h        2014-10-30 20:57:57 UTC (rev 175377)
+++ trunk/Source/WebKit2/DatabaseProcess/IndexedDB/sqlite/UniqueIDBDatabaseBackingStoreSQLite.h        2014-10-30 21:00:58 UTC (rev 175378)
</span><span class="lines">@@ -101,6 +101,8 @@
</span><span class="cx">     std::unique_ptr&lt;WebCore::IDBDatabaseMetadata&gt; extractExistingMetadata();
</span><span class="cx">     std::unique_ptr&lt;WebCore::IDBDatabaseMetadata&gt; createAndPopulateInitialMetadata();
</span><span class="cx"> 
</span><ins>+    bool ensureValidRecordsTable();
+
</ins><span class="cx">     bool deleteRecord(SQLiteIDBTransaction&amp;, int64_t objectStoreID, const WebCore::IDBKeyData&amp;);
</span><span class="cx">     bool uncheckedPutIndexRecord(int64_t objectStoreID, int64_t indexID, const WebCore::IDBKeyData&amp; keyValue, const WebCore::IDBKeyData&amp; indexKey);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>