Implement NEXT_NO_DUPLICATE and PREV_NO_DUPLICATE for index cursors

This commit is contained in:
Ben Turner 2010-06-18 17:10:37 -07:00
parent 1e7079f23f
commit 258defbdbe
2 changed files with 241 additions and 26 deletions

View File

@ -477,12 +477,6 @@ IDBIndexRequest::OpenCursor(nsIIDBKeyRange* aKeyRange,
aDirection = nsIIDBCursor::NEXT;
}
if (aDirection == nsIIDBCursor::NEXT_NO_DUPLICATE ||
aDirection == nsIIDBCursor::PREV_NO_DUPLICATE) {
NS_NOTYETIMPLEMENTED("Implement me!");
return NS_ERROR_NOT_IMPLEMENTED;
}
if (aPreload) {
NS_NOTYETIMPLEMENTED("Implement me!");
return NS_ERROR_NOT_IMPLEMENTED;
@ -550,12 +544,6 @@ IDBIndexRequest::OpenObjectCursor(nsIIDBKeyRange* aKeyRange,
aDirection = nsIIDBCursor::NEXT;
}
if (aDirection == nsIIDBCursor::NEXT_NO_DUPLICATE ||
aDirection == nsIIDBCursor::PREV_NO_DUPLICATE) {
NS_NOTYETIMPLEMENTED("Implement me!");
return NS_ERROR_NOT_IMPLEMENTED;
}
if (aPreload) {
NS_NOTYETIMPLEMENTED("Implement me!");
return NS_ERROR_NOT_IMPLEMENTED;
@ -1019,13 +1007,30 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
keyRangeClause.Append(rightKeyName);
}
nsCString groupClause;
switch (mDirection) {
case nsIIDBCursor::NEXT:
case nsIIDBCursor::PREV:
break;
case nsIIDBCursor::NEXT_NO_DUPLICATE:
case nsIIDBCursor::PREV_NO_DUPLICATE:
groupClause = NS_LITERAL_CSTRING(" GROUP BY value");
break;
default:
NS_NOTREACHED("Unknown direction!");
}
nsCString directionClause;
switch (mDirection) {
case nsIIDBCursor::NEXT:
case nsIIDBCursor::NEXT_NO_DUPLICATE:
directionClause = NS_LITERAL_CSTRING("DESC");
break;
case nsIIDBCursor::PREV:
case nsIIDBCursor::PREV_NO_DUPLICATE:
directionClause = NS_LITERAL_CSTRING("ASC");
break;
@ -1036,8 +1041,8 @@ OpenCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
nsCString query = NS_LITERAL_CSTRING("SELECT value, ") + keyColumn +
NS_LITERAL_CSTRING(" FROM ") + table +
NS_LITERAL_CSTRING(" WHERE index_id = :") + indexId +
keyRangeClause + NS_LITERAL_CSTRING(" ORDER BY value ") +
directionClause;
keyRangeClause + groupClause +
NS_LITERAL_CSTRING(" ORDER BY value ") + directionClause;
nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
NS_ENSURE_TRUE(stmt, nsIIDBDatabaseException::UNKNOWN_ERR);
@ -1210,13 +1215,31 @@ OpenObjectCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
keyRangeClause.Append(rightKeyName);
}
nsCString groupClause;
switch (mDirection) {
case nsIIDBCursor::NEXT:
case nsIIDBCursor::PREV:
break;
case nsIIDBCursor::NEXT_NO_DUPLICATE:
case nsIIDBCursor::PREV_NO_DUPLICATE:
groupClause = NS_LITERAL_CSTRING(" GROUP BY ") + indexTable +
NS_LITERAL_CSTRING(".") + value;
break;
default:
NS_NOTREACHED("Unknown direction!");
}
nsCString directionClause;
switch (mDirection) {
case nsIIDBCursor::NEXT:
case nsIIDBCursor::NEXT_NO_DUPLICATE:
directionClause = NS_LITERAL_CSTRING(" DESC");
break;
case nsIIDBCursor::PREV:
case nsIIDBCursor::PREV_NO_DUPLICATE:
directionClause = NS_LITERAL_CSTRING(" ASC");
break;
@ -1224,18 +1247,19 @@ OpenObjectCursorHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
NS_NOTREACHED("Unknown direction!");
}
nsCAutoString query = NS_LITERAL_CSTRING("SELECT ") + indexTable +
NS_LITERAL_CSTRING(".") + value +
NS_LITERAL_CSTRING(",") + objectTable +
NS_LITERAL_CSTRING(".") + data +
NS_LITERAL_CSTRING(" FROM ") + objectTable +
NS_LITERAL_CSTRING(" INNER JOIN ") + indexTable +
NS_LITERAL_CSTRING(" ON ") + indexTable +
NS_LITERAL_CSTRING(".object_data_id = ") + objectTable +
NS_LITERAL_CSTRING(".id WHERE ") + indexId +
NS_LITERAL_CSTRING("= :") + indexId + keyRangeClause +
NS_LITERAL_CSTRING(" ORDER BY ") + indexTable +
NS_LITERAL_CSTRING(".") + value + directionClause;
nsCString query = NS_LITERAL_CSTRING("SELECT ") + indexTable +
NS_LITERAL_CSTRING(".") + value +
NS_LITERAL_CSTRING(",") + objectTable +
NS_LITERAL_CSTRING(".") + data +
NS_LITERAL_CSTRING(" FROM ") + objectTable +
NS_LITERAL_CSTRING(" INNER JOIN ") + indexTable +
NS_LITERAL_CSTRING(" ON ") + indexTable +
NS_LITERAL_CSTRING(".object_data_id = ") + objectTable +
NS_LITERAL_CSTRING(".id WHERE ") + indexId +
NS_LITERAL_CSTRING("= :") + indexId + keyRangeClause +
groupClause + NS_LITERAL_CSTRING(" ORDER BY ") +
indexTable + NS_LITERAL_CSTRING(".") + value +
directionClause;
nsCOMPtr<mozIStorageStatement> stmt = mTransaction->GetCachedStatement(query);
NS_ENSURE_TRUE(stmt, nsIIDBDatabaseException::UNKNOWN_ERR);

View File

@ -18,6 +18,10 @@
const READ_WRITE = Components.interfaces.nsIIDBTransaction.READ_WRITE;
const NEXT = Components.interfaces.nsIIDBCursor.NEXT;
const PREV = Components.interfaces.nsIIDBCursor.PREV;
const NEXT_NO_DUPLICATE =
Components.interfaces.nsIIDBCursor.NEXT_NO_DUPLICATE;
const PREV_NO_DUPLICATE =
Components.interfaces.nsIIDBCursor.PREV_NO_DUPLICATE;
const name = window.location.pathname;
const description = "My Test Database";
@ -56,6 +60,15 @@
{ key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
];
const objectStoreDataHeightSort = [
{ key: "237-23-7733", value: { name: "Ann", height: 52, weight: 110 } },
{ key: "237-23-7735", value: { name: "Sue", height: 58, weight: 130 } },
{ key: "237-23-7732", value: { name: "Bob", height: 60, weight: 120 } },
{ key: "237-23-7736", value: { name: "Joe", height: 65, weight: 150 } },
{ key: "237-23-7737", value: { name: "Pat", height: 65 } },
{ key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
];
let request = moz_indexedDB.open(name, description);
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;
@ -775,6 +788,184 @@
is(keyIndex, 0, "Saw all the expected keys");
// Test NEXT_NO_DUPLICATE
keyIndex = 3;
keyRange = moz_indexedDB.makeSingleKeyRange(65);
request = objectStore.index("height").openCursor(keyRange, NEXT);
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.result;
if (cursor) {
is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
"Correct key");
is(cursor.value, objectStoreDataHeightSort[keyIndex].key,
"Correct value");
cursor.continue();
keyIndex++;
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, 5, "Saw all the expected keys");
keyIndex = 4;
keyRange = moz_indexedDB.makeSingleKeyRange(65);
request = objectStore.index("height").openCursor(keyRange,
NEXT_NO_DUPLICATE);
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.result;
if (cursor) {
is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
"Correct key");
is(cursor.value, objectStoreDataHeightSort[keyIndex].key,
"Correct value");
cursor.continue();
keyIndex++;
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, 5, "Saw all the expected keys");
keyIndex = 5;
request = objectStore.index("height").openCursor(null,
PREV_NO_DUPLICATE);
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.result;
if (cursor) {
is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
"Correct key");
is(cursor.value, objectStoreDataHeightSort[keyIndex].key,
"Correct value");
cursor.continue();
if (keyIndex == 4) {
keyIndex--;
}
keyIndex--;
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, -1, "Saw all the expected keys");
// Test NEXT_NO_DUPLICATE
keyIndex = 3;
keyRange = moz_indexedDB.makeSingleKeyRange(65);
request = objectStore.index("height").openObjectCursor(keyRange, NEXT);
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.result;
if (cursor) {
is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
"Correct key");
is(cursor.value.name, objectStoreDataHeightSort[keyIndex].value.name,
"Correct name");
is(cursor.value.height,
objectStoreDataHeightSort[keyIndex].value.height,
"Correct height");
if ("weight" in cursor.value) {
is(cursor.value.weight,
objectStoreDataHeightSort[keyIndex].value.weight,
"Correct weight");
}
cursor.continue();
keyIndex++;
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, 5, "Saw all the expected keys");
keyIndex = 4;
keyRange = moz_indexedDB.makeSingleKeyRange(65);
request = objectStore.index("height").openObjectCursor(keyRange,
NEXT_NO_DUPLICATE);
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.result;
if (cursor) {
is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
"Correct key");
is(cursor.value.name, objectStoreDataHeightSort[keyIndex].value.name,
"Correct name");
is(cursor.value.height,
objectStoreDataHeightSort[keyIndex].value.height,
"Correct height");
if ("weight" in cursor.value) {
is(cursor.value.weight,
objectStoreDataHeightSort[keyIndex].value.weight,
"Correct weight");
}
cursor.continue();
keyIndex++;
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, 5, "Saw all the expected keys");
keyIndex = 5;
request = objectStore.index("height").openObjectCursor(null,
PREV_NO_DUPLICATE);
request.onerror = errorHandler;
request.onsuccess = function (event) {
let cursor = event.result;
if (cursor) {
is(cursor.key, objectStoreDataHeightSort[keyIndex].value.height,
"Correct key");
is(cursor.value.name, objectStoreDataHeightSort[keyIndex].value.name,
"Correct name");
is(cursor.value.height,
objectStoreDataHeightSort[keyIndex].value.height,
"Correct height");
if ("weight" in cursor.value) {
is(cursor.value.weight,
objectStoreDataHeightSort[keyIndex].value.weight,
"Correct weight");
}
cursor.continue();
if (keyIndex == 4) {
keyIndex--;
}
keyIndex--;
}
else {
testGenerator.next();
}
}
yield;
is(keyIndex, -1, "Saw all the expected keys");
finishTest();
yield;
}