* This may be a deleted record or a rangeMatch, and in
* either case we should advance. We must determine
* whether the key changes when we advance.
*/
if (exactKeyMatch) {
KeyChangeStatus result =
dup.getNextWithKeyChangeStatus
(key, data, advanceLockType, true, rangeMatch);
status = result.status;
/*
* For BOTH_RANGE, advancing always causes a data
* change, which is considered a key change. For
* SET_RANGE, getNextWithKeyChangeStatus determined
* the key change status.
*/
keyChange = searchMode.isDataSearch() ?
(status == OperationStatus.SUCCESS) :
result.keyChange;
} else if (searchMode.isDataSearch() &&
!advanceAfterRangeSearch) {
/*
* If we did not match the key (exactly) for
* BOTH_RANGE, and advanceAfterSearchRangeBoth is
* false, then return NOTFOUND.
*/
status = OperationStatus.NOTFOUND;
} else {
/*
* If we didn't match the key, skip over duplicates
* to the next key with getNextNoDup.
*/
status = dup.getNextNoDup
(key, data, advanceLockType, true, rangeMatch);
/* getNextNoDup always causes a key change. */
keyChange = (status == OperationStatus.SUCCESS);
}
/*
* If we moved past the search key after a BOTH_RANGE
* search, return NOTFOUND. Leave the keyChange value
* intact, since we want to return this accurately
* regardless of the status return.
*/
if (status == OperationStatus.SUCCESS &&
searchMode.isDataSearch()) {
if (Key.compareKeys
(key.getData(), searchKey,
dbImpl.getDuplicateComparator()) != 0) {
status = OperationStatus.NOTFOUND;
}
}
}
}
}
} finally {
/*
* searchAndPosition returns with the target BIN latched, so it is
* the responsibility of this method to make sure the latches are
* released.
*/
cursorImpl.releaseBINs();
if (status != OperationStatus.SUCCESS && dup != cursorImpl) {
dup.releaseBINs();
}
}
return new KeyChangeStatus(status, keyChange);
}