diff --git a/dom/indexedDB/IDBIndexRequest.cpp b/dom/indexedDB/IDBIndexRequest.cpp index 8dbea0094709..1f833959585f 100644 --- a/dom/indexedDB/IDBIndexRequest.cpp +++ b/dom/indexedDB/IDBIndexRequest.cpp @@ -241,9 +241,26 @@ IDBIndexRequest::OpenCursor(nsIIDBKeyRange* aKeyRange, return NS_ERROR_UNEXPECTED; } + nsresult rv; + Key leftKey, rightKey; + PRUint16 keyRangeFlags = 0; + if (aKeyRange) { - NS_NOTYETIMPLEMENTED("Implement me!"); - return NS_ERROR_NOT_IMPLEMENTED; + rv = aKeyRange->GetFlags(&keyRangeFlags); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr variant; + rv = aKeyRange->GetLeft(getter_AddRefs(variant)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = IDBObjectStoreRequest::GetKeyFromVariant(variant, leftKey); + NS_ENSURE_SUCCESS(rv, rv); + + rv = aKeyRange->GetRight(getter_AddRefs(variant)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = IDBObjectStoreRequest::GetKeyFromVariant(variant, rightKey); + NS_ENSURE_SUCCESS(rv, rv); } if (aOptionalArgCount >= 2) { @@ -274,10 +291,10 @@ IDBIndexRequest::OpenCursor(nsIIDBKeyRange* aKeyRange, nsRefPtr helper = new OpenCursorHelper(mObjectStore->Transaction(), request, this, mId, - mUnique, mAutoIncrement, Key(), Key(), 0, aDirection, - aPreload); + mUnique, mAutoIncrement, leftKey, rightKey, + keyRangeFlags, aDirection, aPreload); - nsresult rv = helper->DispatchToTransactionPool(); + rv = helper->DispatchToTransactionPool(); NS_ENSURE_SUCCESS(rv, rv); request.forget(_retval); @@ -516,6 +533,33 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection) } NS_NAMED_LITERAL_CSTRING(indexId, "index_id"); + NS_NAMED_LITERAL_CSTRING(leftKeyName, "left_key"); + NS_NAMED_LITERAL_CSTRING(rightKeyName, "right_key"); + + nsCAutoString keyRangeClause; + if (!mLeftKey.IsUnset()) { + keyRangeClause.AppendLiteral(" AND value"); + if (mKeyRangeFlags & nsIIDBKeyRange::LEFT_OPEN) { + keyRangeClause.AppendLiteral(" > :"); + } + else { + NS_ASSERTION(mKeyRangeFlags & nsIIDBKeyRange::LEFT_BOUND, "Bad flags!"); + keyRangeClause.AppendLiteral(" >= :"); + } + keyRangeClause.Append(leftKeyName); + } + + if (!mRightKey.IsUnset()) { + keyRangeClause.AppendLiteral(" AND value"); + if (mKeyRangeFlags & nsIIDBKeyRange::RIGHT_OPEN) { + keyRangeClause.AppendLiteral(" < :"); + } + else { + NS_ASSERTION(mKeyRangeFlags & nsIIDBKeyRange::RIGHT_BOUND, "Bad flags!"); + keyRangeClause.AppendLiteral(" <= :"); + } + keyRangeClause.Append(rightKeyName); + } nsCAutoString query("SELECT value, "); query.Append(keyColumn); @@ -523,6 +567,7 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection) query.Append(table); query.AppendLiteral(" WHERE index_id = :"); query.Append(indexId); + query.Append(keyRangeClause); query.AppendLiteral(" ORDER BY value "); switch (mDirection) { @@ -551,6 +596,32 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection) nsresult rv = stmt->BindInt64ByName(indexId, mId); NS_ENSURE_SUCCESS(rv, nsIIDBDatabaseException::UNKNOWN_ERR); + if (!mLeftKey.IsUnset()) { + if (mLeftKey.IsString()) { + rv = stmt->BindStringByName(leftKeyName, mLeftKey.StringValue()); + } + else if (mLeftKey.IsInt()) { + rv = stmt->BindInt64ByName(leftKeyName, mLeftKey.IntValue()); + } + else { + NS_NOTREACHED("Bad key!"); + } + NS_ENSURE_SUCCESS(rv, nsIIDBDatabaseException::UNKNOWN_ERR); + } + + if (!mRightKey.IsUnset()) { + if (mRightKey.IsString()) { + rv = stmt->BindStringByName(rightKeyName, mRightKey.StringValue()); + } + else if (mRightKey.IsInt()) { + rv = stmt->BindInt64ByName(rightKeyName, mRightKey.IntValue()); + } + else { + NS_NOTREACHED("Bad key!"); + } + NS_ENSURE_SUCCESS(rv, nsIIDBDatabaseException::UNKNOWN_ERR); + } + PRBool hasResult; while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&hasResult))) && hasResult) { if (mData.Capacity() == mData.Length()) { @@ -620,5 +691,7 @@ OpenCursorHelper::GetSuccessResult(nsIWritableVariant* aResult) aResult->SetAsISupports(static_cast(cursor)); + mIndex = nsnull; + return OK; } diff --git a/dom/indexedDB/IDBKeyRange.h b/dom/indexedDB/IDBKeyRange.h index a25d44cd3f45..db03bb3ac307 100644 --- a/dom/indexedDB/IDBKeyRange.h +++ b/dom/indexedDB/IDBKeyRange.h @@ -64,7 +64,7 @@ protected: PRUint16 aFlags); IDBKeyRange() - : mFlags(nsIIDBKeyRange::SINGLE) + : mFlags(0) { } ~IDBKeyRange() { } diff --git a/dom/indexedDB/IDBObjectStoreRequest.cpp b/dom/indexedDB/IDBObjectStoreRequest.cpp index 7dbe4d41b1a4..21b3fd37ad3a 100644 --- a/dom/indexedDB/IDBObjectStoreRequest.cpp +++ b/dom/indexedDB/IDBObjectStoreRequest.cpp @@ -181,7 +181,7 @@ public: private: // In-params. - const nsRefPtr mObjectStore; + nsRefPtr mObjectStore; const Key mLeftKey; const Key mRightKey; const PRUint16 mKeyRangeFlags; @@ -1460,7 +1460,9 @@ AddHelper::UpdateIndexes(mozIStorageConnection* aConnection, NS_ENSURE_SUCCESS(rv, rv); rv = stmt->Execute(); - NS_ENSURE_SUCCESS(rv, rv); + if (NS_FAILED(rv)) { + return rv; + } } return NS_OK; @@ -1754,6 +1756,8 @@ OpenCursorHelper::GetSuccessResult(nsIWritableVariant* aResult) aResult->SetAsISupports(static_cast(cursor)); + mObjectStore = nsnull; + return OK; } diff --git a/dom/indexedDB/IndexedDatabaseRequest.cpp b/dom/indexedDB/IndexedDatabaseRequest.cpp index 9d3d7fbb9334..9974e2178dd2 100644 --- a/dom/indexedDB/IndexedDatabaseRequest.cpp +++ b/dom/indexedDB/IndexedDatabaseRequest.cpp @@ -566,7 +566,8 @@ IndexedDatabaseRequest::MakeSingleKeyRange(nsIVariant* aValue, } nsRefPtr range = - IDBKeyRange::Create(aValue, aValue, PRUint16(nsIIDBKeyRange::SINGLE)); + IDBKeyRange::Create(aValue, aValue, PRUint16(nsIIDBKeyRange::LEFT_BOUND | + nsIIDBKeyRange::RIGHT_BOUND)); NS_ASSERTION(range, "Out of memory?"); range.forget(_retval); diff --git a/dom/indexedDB/nsIIDBKeyRange.idl b/dom/indexedDB/nsIIDBKeyRange.idl index 9bff06cc4db7..03484bb5ac3d 100644 --- a/dom/indexedDB/nsIIDBKeyRange.idl +++ b/dom/indexedDB/nsIIDBKeyRange.idl @@ -49,7 +49,6 @@ interface nsIVariant; [scriptable, uuid(8e6b05f4-2358-420b-a6fd-03416543ed18)] interface nsIIDBKeyRange : nsISupports { - const unsigned short SINGLE = 0; const unsigned short LEFT_OPEN = 1 << 1; const unsigned short RIGHT_OPEN = 1 << 2; const unsigned short LEFT_BOUND = 1 << 3; diff --git a/dom/indexedDB/test/test_indexes.html b/dom/indexedDB/test/test_indexes.html index 8422c1c858b9..6366725aabca 100644 --- a/dom/indexedDB/test/test_indexes.html +++ b/dom/indexedDB/test/test_indexes.html @@ -232,6 +232,222 @@ is(keyIndex, -1, "Saw all the expected keys"); + keyIndex = 1; + let keyRange = moz_indexedDB.makeBoundKeyRange("Bob", "Ron"); + + request = objectStore.index("name").openCursor(keyRange); + request.onerror = errorHandler; + request.onsuccess = function (event) { + let cursor = event.result; + if (cursor) { + is(cursor.key, objectStoreDataNameSort[keyIndex].value.name, + "Correct key"); + is(cursor.value, objectStoreDataNameSort[keyIndex].key, + "Correct value"); + + cursor.continue(); + keyIndex++; + } + else { + testGenerator.next(); + } + } + yield; + + is(keyIndex, 5, "Saw all the expected keys"); + + keyIndex = 2; + let keyRange = moz_indexedDB.makeBoundKeyRange("Bob", "Ron", true); + + request = objectStore.index("name").openCursor(keyRange); + request.onerror = errorHandler; + request.onsuccess = function (event) { + let cursor = event.result; + if (cursor) { + is(cursor.key, objectStoreDataNameSort[keyIndex].value.name, + "Correct key"); + is(cursor.value, objectStoreDataNameSort[keyIndex].key, + "Correct value"); + + cursor.continue(); + keyIndex++; + } + else { + testGenerator.next(); + } + } + yield; + + is(keyIndex, 5, "Saw all the expected keys"); + + keyIndex = 1; + let keyRange = moz_indexedDB.makeBoundKeyRange("Bob", "Ron", false, true); + + request = objectStore.index("name").openCursor(keyRange); + request.onerror = errorHandler; + request.onsuccess = function (event) { + let cursor = event.result; + if (cursor) { + is(cursor.key, objectStoreDataNameSort[keyIndex].value.name, + "Correct key"); + is(cursor.value, objectStoreDataNameSort[keyIndex].key, + "Correct value"); + + cursor.continue(); + keyIndex++; + } + else { + testGenerator.next(); + } + } + yield; + + is(keyIndex, 4, "Saw all the expected keys"); + + keyIndex = 2; + keyRange = moz_indexedDB.makeBoundKeyRange("Bob", "Ron", true, true); + + request = objectStore.index("name").openCursor(keyRange); + request.onerror = errorHandler; + request.onsuccess = function (event) { + let cursor = event.result; + if (cursor) { + is(cursor.key, objectStoreDataNameSort[keyIndex].value.name, + "Correct key"); + is(cursor.value, objectStoreDataNameSort[keyIndex].key, + "Correct value"); + + cursor.continue(); + keyIndex++; + } + else { + testGenerator.next(); + } + } + yield; + + is(keyIndex, 4, "Saw all the expected keys"); + + keyIndex = 1; + keyRange = moz_indexedDB.makeLeftBoundKeyRange("Bob"); + + request = objectStore.index("name").openCursor(keyRange); + request.onerror = errorHandler; + request.onsuccess = function (event) { + let cursor = event.result; + if (cursor) { + is(cursor.key, objectStoreDataNameSort[keyIndex].value.name, + "Correct key"); + is(cursor.value, objectStoreDataNameSort[keyIndex].key, + "Correct value"); + + cursor.continue(); + keyIndex++; + } + else { + testGenerator.next(); + } + } + yield; + + is(keyIndex, objectStoreDataNameSort.length, "Saw all the expected keys"); + + keyIndex = 2; + keyRange = moz_indexedDB.makeLeftBoundKeyRange("Bob", true); + + request = objectStore.index("name").openCursor(keyRange); + request.onerror = errorHandler; + request.onsuccess = function (event) { + let cursor = event.result; + if (cursor) { + is(cursor.key, objectStoreDataNameSort[keyIndex].value.name, + "Correct key"); + is(cursor.value, objectStoreDataNameSort[keyIndex].key, + "Correct value"); + + cursor.continue(); + keyIndex++; + } + else { + testGenerator.next(); + } + } + yield; + + is(keyIndex, objectStoreDataNameSort.length, "Saw all the expected keys"); + + keyIndex = 0; + keyRange = moz_indexedDB.makeRightBoundKeyRange("Joe"); + + request = objectStore.index("name").openCursor(keyRange); + request.onerror = errorHandler; + request.onsuccess = function (event) { + let cursor = event.result; + if (cursor) { + is(cursor.key, objectStoreDataNameSort[keyIndex].value.name, + "Correct key"); + is(cursor.value, objectStoreDataNameSort[keyIndex].key, + "Correct value"); + + cursor.continue(); + keyIndex++; + } + else { + testGenerator.next(); + } + } + yield; + + is(keyIndex, 3, "Saw all the expected keys"); + + keyIndex = 0; + keyRange = moz_indexedDB.makeRightBoundKeyRange("Joe", true); + + request = objectStore.index("name").openCursor(keyRange); + request.onerror = errorHandler; + request.onsuccess = function (event) { + let cursor = event.result; + if (cursor) { + is(cursor.key, objectStoreDataNameSort[keyIndex].value.name, + "Correct key"); + is(cursor.value, objectStoreDataNameSort[keyIndex].key, + "Correct value"); + + cursor.continue(); + keyIndex++; + } + else { + testGenerator.next(); + } + } + yield; + + is(keyIndex, 2, "Saw all the expected keys"); + + keyIndex = 3; + keyRange = moz_indexedDB.makeSingleKeyRange("Pat"); + + request = objectStore.index("name").openCursor(keyRange); + request.onerror = errorHandler; + request.onsuccess = function (event) { + let cursor = event.result; + if (cursor) { + is(cursor.key, objectStoreDataNameSort[keyIndex].value.name, + "Correct key"); + is(cursor.value, objectStoreDataNameSort[keyIndex].key, + "Correct value"); + + cursor.continue(); + keyIndex++; + } + else { + testGenerator.next(); + } + } + yield; + + is(keyIndex, 4, "Saw all the expected keys"); + finishTest(); yield; }