Bug 628063 - 'IndexedDB: Indexes created after data are added are sometimes improperly populated'. r=sicking, a=blocking.

This commit is contained in:
Ben Turner 2011-01-23 10:16:00 -08:00
parent 9f91a2ed93
commit 056d72865d
4 changed files with 109 additions and 20 deletions

View File

@ -94,7 +94,7 @@ public:
const nsString& KeyPath() const
{
return mName;
return mKeyPath;
}
private:

View File

@ -251,9 +251,6 @@ private:
// In-params.
nsRefPtr<IDBIndex> mIndex;
// Out-params.
PRInt64 mId;
};
class DeleteIndexHelper : public AsyncConnectionHelper
@ -2129,8 +2126,13 @@ CreateIndexHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR;
}
// Get the id of this object store, and store it for future use.
(void)aConnection->GetLastInsertRowID(&mId);
#ifdef DEBUG
{
PRInt64 id;
aConnection->GetLastInsertRowID(&id);
NS_ASSERTION(mIndex->Id() == id, "Bad index id!");
}
#endif
// Now we need to populate the index with data from the object store.
rv = InsertDataFromObjectStore(aConnection);
@ -2144,11 +2146,9 @@ CreateIndexHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
nsresult
CreateIndexHelper::InsertDataFromObjectStore(mozIStorageConnection* aConnection)
{
bool autoIncrement = mIndex->IsAutoIncrement();
nsCAutoString table;
nsCAutoString columns;
if (autoIncrement) {
if (mIndex->IsAutoIncrement()) {
table.AssignLiteral("ai_object_data");
columns.AssignLiteral("id, data");
}
@ -2173,27 +2173,40 @@ CreateIndexHelper::InsertDataFromObjectStore(mozIStorageConnection* aConnection)
PRBool hasResult;
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
nsCOMPtr<mozIStorageStatement> insertStmt =
mTransaction->IndexUpdateStatement(autoIncrement, mIndex->IsUnique(),
false);
mTransaction->IndexUpdateStatement(mIndex->IsAutoIncrement(),
mIndex->IsUnique(), false);
NS_ENSURE_TRUE(insertStmt, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
mozStorageStatementScoper scoper2(insertStmt);
rv = insertStmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"), mId);
rv = insertStmt->BindInt64ByName(NS_LITERAL_CSTRING("index_id"),
mIndex->Id());
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = insertStmt->BindInt64ByName(NS_LITERAL_CSTRING("object_data_id"),
stmt->AsInt64(0));
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
if (!autoIncrement) {
// XXX does this cause problems with the affinity?
nsString key;
rv = stmt->GetString(2, key);
if (!mIndex->IsAutoIncrement()) {
NS_NAMED_LITERAL_CSTRING(objectDataKey, "object_data_key");
PRInt32 keyType;
rv = stmt->GetTypeOfIndex(2, &keyType);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = insertStmt->BindStringByName(NS_LITERAL_CSTRING("object_data_key"),
key);
if (keyType == mozIStorageStatement::VALUE_TYPE_INTEGER) {
rv = insertStmt->BindInt64ByName(objectDataKey, stmt->AsInt64(2));
}
else if (keyType == mozIStorageStatement::VALUE_TYPE_TEXT) {
nsString stringKey;
rv = stmt->GetString(2, stringKey);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = insertStmt->BindStringByName(objectDataKey, stringKey);
}
else {
NS_NOTREACHED("Bad SQLite type!");
}
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
@ -2209,12 +2222,11 @@ CreateIndexHelper::InsertDataFromObjectStore(mozIStorageConnection* aConnection)
&cx, key);
NS_ENSURE_SUCCESS(rv, rv);
NS_NAMED_LITERAL_CSTRING(value, "value");
if (key.IsUnset()) {
continue;
}
NS_NAMED_LITERAL_CSTRING(value, "value");
if (key.IsInt()) {
rv = insertStmt->BindInt64ByName(value, key.IntValue());
}

View File

@ -56,6 +56,7 @@ TEST_FILES = \
test_bfcache.html \
test_clear.html \
test_create_index.html \
test_create_index_with_integer_keys.html \
test_create_objectStore.html \
test_cursors.html \
test_cursor_mutation.html \

View File

@ -0,0 +1,76 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Test</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
function testSteps()
{
const data = { id: new Date().getTime(),
num: parseInt(Math.random() * 1000) };
let request = mozIndexedDB.open(window.location.pathname);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield;
let db = event.target.result;
db.onerror = errorHandler;
db.setVersion("1").onsuccess = grabEventAndContinueHandler;
event = yield;
event.target.transaction.oncomplete = continueToNextStep;
// Make object store, add data.
let objectStore = db.createObjectStore("foo", { keyPath: "id" });
objectStore.add(data);
yield;
db.setVersion("2").onsuccess = grabEventAndContinueHandler;
event = yield;
event.target.transaction.oncomplete = continueToNextStep;
// Create index.
event.target.transaction.objectStore("foo").createIndex("foo", "num");
yield;
// Make sure our object made it into the index.
let seenCount = 0;
db.transaction("foo").objectStore("foo").index("foo")
.openKeyCursor().onsuccess = function(event) {
let cursor = event.target.result;
if (cursor) {
is(cursor.key, data.num, "Good key");
is(cursor.value, data.id, "Good value");
seenCount++;
cursor.continue();
}
else {
continueToNextStep();
}
};
yield;
is(seenCount, 1, "Saw our entry");
finishTest();
yield;
}
</script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
</html>