Skip to content
Permalink
Browse files
2010-10-19 Jeremy Orlow <jorlow@chromium.org>
        Reviewed by Nate Chapin.

        Fix multiple index support in IndexedDB
        https://bugs.webkit.org/show_bug.cgi?id=47919

        Modify an existing test to verify behavior and add another test for
        something I thought might have been related (but wasn't, but it still
        seems like a good test).

        * storage/indexeddb/index-basics-expected.txt:
        * storage/indexeddb/index-basics.html:
        * storage/indexeddb/queued-commands-expected.txt: Added.
        * storage/indexeddb/queued-commands.html: Added.
2010-10-19  Jeremy Orlow  <jorlow@chromium.org>

        Reviewed by Nate Chapin.

        Fix multiple index support in IndexedDB
        https://bugs.webkit.org/show_bug.cgi?id=47919

        Fix 2 bugs that caused the IndexData of all but the last index to be
        properly updated:
        * The objectStoreDataId is NOT unique if there are multiple indexes. So
          remove the constraint.
        * Do not delete all existing entries with that objectStoreDataId before
          adding an entry for each index. Only do it once at the beginning.

        Test: storage/indexeddb/queued-commands.html
            + index-basics.html modified

        * storage/IDBFactoryBackendImpl.cpp:
        (WebCore::createTables):
        * storage/IDBObjectStoreBackendImpl.cpp:
        (WebCore::deleteIndexData):
        (WebCore::putIndexData):
        (WebCore::IDBObjectStoreBackendImpl::putInternal):

Canonical link: https://commits.webkit.org/60655@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@70093 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Jeremy Orlow committed Oct 19, 2010
1 parent ef28a6c commit 744f4662680765e75755ff38644148da1c9a4d3c
Showing 8 changed files with 279 additions and 5 deletions.
@@ -1,3 +1,19 @@
2010-10-19 Jeremy Orlow <jorlow@chromium.org>

Reviewed by Nate Chapin.

Fix multiple index support in IndexedDB
https://bugs.webkit.org/show_bug.cgi?id=47919

Modify an existing test to verify behavior and add another test for
something I thought might have been related (but wasn't, but it still
seems like a good test).

* storage/indexeddb/index-basics-expected.txt:
* storage/indexeddb/index-basics.html:
* storage/indexeddb/queued-commands-expected.txt: Added.
* storage/indexeddb/queued-commands.html: Added.

2010-10-19 James Robinson <jamesr@chromium.org>

Update chromium expectations.
@@ -44,6 +44,7 @@ PASS trans !== null is true
Deleted all object stores.
db.createObjectStore('storeName', null)
store.createIndex('indexName', 'x')
store.createIndex('indexName2', 'y', false)
PASS 'name' in indexObject is true
PASS indexObject.name is "indexName"
PASS 'storeName' in indexObject is true
@@ -107,6 +108,24 @@ PASS 'onerror' in event.target is true
PASS 'readyState' in event.target is true
PASS event.target.readyState is event.target.DONE

PASS event.result is "key"
indexObject2.getKey('zzz')
PASS 'onsuccess' in result is true
PASS 'onerror' in result is true
PASS 'readyState' in result is true
An event should fire shortly...

Success event fired:
PASS 'result' in event is true
PASS 'code' in event is false
PASS 'message' in event is false
PASS 'source' in event is true
PASS event.source != null is true
PASS 'onsuccess' in event.target is true
PASS 'onerror' in event.target is true
PASS 'readyState' in event.target is true
PASS event.target.readyState is event.target.DONE

PASS event.result is "key"
indexObject.get('value')
PASS 'onsuccess' in result is true
@@ -45,9 +45,10 @@
}

function createIndex()
{
{
window.store = evalAndLog("db.createObjectStore('storeName', null)");
window.indexObject = evalAndLog("store.createIndex('indexName', 'x')");
window.indexObject2 = evalAndLog("store.createIndex('indexName2', 'y', false)");
addData();
}

@@ -97,6 +98,17 @@
verifySuccessEvent(event);
shouldBeEqualToString("event.result", "key");

result = evalAndLog("indexObject2.getKey('zzz')");
verifyResult(result);
result.onsuccess = getObjectData2;
result.onerror = unexpectedErrorCallback;
}

function getObjectData2()
{
verifySuccessEvent(event);
shouldBeEqualToString("event.result", "key");

result = evalAndLog("indexObject.get('value')");
verifyResult(result);
result.onsuccess = getDataFail;
@@ -0,0 +1,104 @@
Verify that queuing up several commands works (and they all fire).

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


webkitIndexedDB.open('name', 'description')
PASS 'onsuccess' in result is true
PASS 'onerror' in result is true
PASS 'readyState' in result is true
An event should fire shortly...

Success event fired:
PASS 'result' in event is true
PASS 'code' in event is false
PASS 'message' in event is false
PASS 'source' in event is true
PASS event.source != null is true
PASS 'onsuccess' in event.target is true
PASS 'onerror' in event.target is true
PASS 'readyState' in event.target is true
PASS event.target.readyState is event.target.DONE

db = event.result
db.setVersion('new version')
PASS 'onsuccess' in result is true
PASS 'onerror' in result is true
PASS 'readyState' in result is true
An event should fire shortly...

setVersionSuccess():
Success event fired:
PASS 'result' in event is true
PASS 'code' in event is false
PASS 'message' in event is false
PASS 'source' in event is true
PASS event.source != null is true
PASS 'onsuccess' in event.target is true
PASS 'onerror' in event.target is true
PASS 'readyState' in event.target is true
PASS event.target.readyState is event.target.DONE

trans = event.result
PASS trans !== null is true
Deleted all object stores.
db.createObjectStore('storeName', null)
store.createIndex('indexName', 'x')
store.add({x: 'value', y: 'zzz'}, 'key')
PASS 'onsuccess' in result is true
PASS 'onerror' in result is true
PASS 'readyState' in result is true
An event should fire shortly...

store.add({x: 'value2', y: 'zzz2'}, 'key2')
PASS 'onsuccess' in result is true
PASS 'onerror' in result is true
PASS 'readyState' in result is true
An event should fire shortly...

store.put({x: 'valu2', y: 'zz2'}, 'ky2')
PASS 'onsuccess' in result is true
PASS 'onerror' in result is true
PASS 'readyState' in result is true
An event should fire shortly...

Success event fired:
PASS 'result' in event is true
PASS 'code' in event is false
PASS 'message' in event is false
PASS 'source' in event is true
PASS event.source != null is true
PASS 'onsuccess' in event.target is true
PASS 'onerror' in event.target is true
PASS 'readyState' in event.target is true
PASS event.target.readyState is event.target.DONE

PASS 0 is 0
Success event fired:
PASS 'result' in event is true
PASS 'code' in event is false
PASS 'message' in event is false
PASS 'source' in event is true
PASS event.source != null is true
PASS 'onsuccess' in event.target is true
PASS 'onerror' in event.target is true
PASS 'readyState' in event.target is true
PASS event.target.readyState is event.target.DONE

PASS 1 is 1
Success event fired:
PASS 'result' in event is true
PASS 'code' in event is false
PASS 'message' in event is false
PASS 'source' in event is true
PASS event.source != null is true
PASS 'onsuccess' in event.target is true
PASS 'onerror' in event.target is true
PASS 'readyState' in event.target is true
PASS event.target.readyState is event.target.DONE

PASS 2 is 2
PASS successfullyParsed is true

TEST COMPLETE

@@ -0,0 +1,87 @@
<html>
<head>
<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
<script src="../../fast/js/resources/js-test-pre.js"></script>
<script src="../../fast/js/resources/js-test-post-function.js"></script>
<script src="resources/shared.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script>

description("Verify that queuing up several commands works (and they all fire).");
if (window.layoutTestController)
layoutTestController.waitUntilDone();

function test()
{
result = evalAndLog("webkitIndexedDB.open('name', 'description')");
verifyResult(result);
result.onsuccess = setVersion;
result.onerror = unexpectedErrorCallback;
}

function setVersion()
{
verifySuccessEvent(event);
db = evalAndLog("db = event.result");

result = evalAndLog("db.setVersion('new version')");
verifyResult(result);
result.onsuccess = deleteExisting;
result.onerror = unexpectedErrorCallback;
}

function deleteExisting()
{
debug("setVersionSuccess():");
verifySuccessEvent(event);
window.trans = evalAndLog("trans = event.result");
shouldBeTrue("trans !== null");
trans.onabort = unexpectedAbortCallback;

deleteAllObjectStores(db, createIndex);
}

function createIndex()
{
window.store = evalAndLog("db.createObjectStore('storeName', null)");
window.indexObject = evalAndLog("store.createIndex('indexName', 'x')");

result = evalAndLog("store.add({x: 'value', y: 'zzz'}, 'key')");
verifyResult(result);
result.onsuccess = function() { verifyAdd(0); };
result.onerror = unexpectedErrorCallback;

result = evalAndLog("store.add({x: 'value2', y: 'zzz2'}, 'key2')");
verifyResult(result);
result.onsuccess = function() { verifyAdd(1); };
result.onerror = unexpectedErrorCallback;

result = evalAndLog("store.put({x: 'valu2', y: 'zz2'}, 'ky2')");
verifyResult(result);
result.onsuccess = function() { verifyAdd(2); };
result.onerror = unexpectedErrorCallback;

window.addCount = 0;
}

function verifyAdd(expected)
{
verifySuccessEvent(event);
shouldBe("" + addCount++, "" + expected);

if (addCount == 3)
done();
if (addCount > 3)
testFailed("Unexpected call to verifyAdd!");
}

test();

var successfullyParsed = true;

</script>
</body>
</html>
@@ -1,3 +1,27 @@
2010-10-19 Jeremy Orlow <jorlow@chromium.org>

Reviewed by Nate Chapin.

Fix multiple index support in IndexedDB
https://bugs.webkit.org/show_bug.cgi?id=47919

Fix 2 bugs that caused the IndexData of all but the last index to be
properly updated:
* The objectStoreDataId is NOT unique if there are multiple indexes. So
remove the constraint.
* Do not delete all existing entries with that objectStoreDataId before
adding an entry for each index. Only do it once at the beginning.

Test: storage/indexeddb/queued-commands.html
+ index-basics.html modified

* storage/IDBFactoryBackendImpl.cpp:
(WebCore::createTables):
* storage/IDBObjectStoreBackendImpl.cpp:
(WebCore::deleteIndexData):
(WebCore::putIndexData):
(WebCore::IDBObjectStoreBackendImpl::putInternal):

2010-10-19 Martin Robinson <mrobinson@igalia.com>

Fix the GTK+ build after r70072. The logic looks incorrect, but
@@ -99,7 +99,7 @@ static bool createTables(SQLiteDatabase* sqliteDatabase)
"CREATE UNIQUE INDEX IF NOT EXISTS ObjectStoreData_composit ON ObjectStoreData(keyString, keyDate, keyNumber, objectStoreId)",

"DROP TABLE IF EXISTS IndexData",
"CREATE TABLE IF NOT EXISTS IndexData (id INTEGER PRIMARY KEY, indexId INTEGER NOT NULL REFERENCES Indexes(id), keyString TEXT, keyDate INTEGER, keyNumber INTEGER, objectStoreDataId INTEGER NOT NULL UNIQUE REFERENCES ObjectStoreData(id))",
"CREATE TABLE IF NOT EXISTS IndexData (id INTEGER PRIMARY KEY, indexId INTEGER NOT NULL REFERENCES Indexes(id), keyString TEXT, keyDate INTEGER, keyNumber INTEGER, objectStoreDataId INTEGER NOT NULL REFERENCES ObjectStoreData(id))",
"DROP INDEX IF EXISTS IndexData_composit",
"CREATE INDEX IF NOT EXISTS IndexData_composit ON IndexData(keyString, keyDate, keyNumber, indexId)",
"DROP INDEX IF EXISTS IndexData_objectStoreDataId",
@@ -154,15 +154,18 @@ static bool putObjectStoreData(SQLiteDatabase& db, IDBKey* key, SerializedScript
return true;
}

static int putIndexData(SQLiteDatabase& db, IDBKey* key, int64_t indexId, int64_t objectStoreDataId)
static bool deleteIndexData(SQLiteDatabase& db, int64_t objectStoreDataId)
{
SQLiteStatement deleteQuery(db, "DELETE FROM IndexData WHERE objectStoreDataId = ?");
if (deleteQuery.prepare() != SQLResultOk)
return false;
deleteQuery.bindInt64(1, objectStoreDataId);
if (deleteQuery.step() != SQLResultDone)
return false;

return deleteQuery.step() == SQLResultDone;
}

static bool putIndexData(SQLiteDatabase& db, IDBKey* key, int64_t indexId, int64_t objectStoreDataId)
{
SQLiteStatement putQuery(db, "INSERT INTO IndexData (keyString, keyDate, keyNumber, indexId, objectStoreDataId) VALUES (?, ?, ?, ?, ?)");
if (putQuery.prepare() != SQLResultOk)
return false;
@@ -191,6 +194,8 @@ void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<
RefPtr<SerializedScriptValue> value = prpValue;
RefPtr<IDBKey> key = prpKey;

// FIXME: Support auto-increment.

if (!objectStore->m_keyPath.isNull()) {
if (key) {
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "A key was supplied for an objectStore that has a keyPath."));
@@ -241,6 +246,13 @@ void IDBObjectStoreBackendImpl::putInternal(ScriptExecutionContext*, PassRefPtr<
return;
}

if (!deleteIndexData(objectStore->sqliteDatabase(), dataRowId)) {
// FIXME: The Indexed Database specification does not have an error code dedicated to I/O errors.
callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "Error writing data to stable storage."));
transaction->abort();
return;
}

int i = 0;
for (IndexMap::iterator it = objectStore->m_indexes.begin(); it != objectStore->m_indexes.end(); ++it, ++i) {
if (!putIndexData(objectStore->sqliteDatabase(), indexKeys[i].get(), it->second->id(), dataRowId)) {

0 comments on commit 744f466

Please sign in to comment.