void testSetEndPosition_RestoreEndCursor_Reverse(bool unique) { auto harnessHelper = newHarnessHelper(); auto opCtx = harnessHelper->newOperationContext(); auto sorted = harnessHelper->newSortedDataInterface(unique, { {key1, loc1}, {key4, loc1}, }); auto cursor = sorted->newCursor(opCtx.get(), false); cursor->setEndPosition(key3, true); ASSERT_EQ(cursor->seek(key4, true), IndexKeyEntry(key4, loc1)); cursor->saveUnpositioned(); insertToIndex(opCtx, sorted, { {key2, loc1}, // in range {key3, loc1}, // out of range }); cursor->restore(); // must restore end cursor even with saveUnpositioned(). ASSERT_EQ(cursor->seek(key4, true), IndexKeyEntry(key4, loc1)); ASSERT_EQ(cursor->next(), IndexKeyEntry(key3, loc1)); ASSERT_EQ(cursor->next(), boost::none); }
void testSetEndPosition_Seek_Reverse(bool unique, bool inclusive) { auto harnessHelper = newHarnessHelper(); auto opCtx = harnessHelper->newOperationContext(); auto sorted = harnessHelper->newSortedDataInterface(unique, { {key1, loc1}, {key2, loc1}, // No key3 {key4, loc1}, }); auto cursor = sorted->newCursor(opCtx.get(), false); cursor->setEndPosition(key2, inclusive); // Directly seeking past end is considered out of range. ASSERT_EQ(cursor->seek(key1, true), boost::none); ASSERT_EQ(cursor->seekExact(key1), boost::none); // Seeking to key2 directly or indirectly is only returned if endPosition is inclusive. auto maybeKey2 = inclusive ? boost::make_optional(IndexKeyEntry(key2, loc1)) : boost::none; // direct ASSERT_EQ(cursor->seek(key2, true), maybeKey2); ASSERT_EQ(cursor->seekExact(key2), maybeKey2); // indirect ASSERT_EQ(cursor->seek(key3, true), maybeKey2); cursor->saveUnpositioned(); removeFromIndex(opCtx, sorted, {{key2, loc1}}); cursor->restore(); ASSERT_EQ(cursor->seek(key3, true), boost::none); ASSERT_EQ(cursor->seek(key2, true), boost::none); }
// Ensure that SaveUnpositioned allows later use of the cursor. TEST(SortedDataInterface, SaveUnpositionedAndRestore) { auto harnessHelper = newHarnessHelper(); auto opCtx = harnessHelper->newOperationContext(); auto sorted = harnessHelper->newSortedDataInterface(false, { {key1, loc1}, {key2, loc1}, {key3, loc1}, }); auto cursor = sorted->newCursor(opCtx.get()); ASSERT_EQ(cursor->seek(key2, true), IndexKeyEntry(key2, loc1)); cursor->saveUnpositioned(); removeFromIndex(opCtx, sorted, {{key2, loc1}}); cursor->restore(opCtx.get()); ASSERT_EQ(cursor->seek(key1, true), IndexKeyEntry(key1, loc1)); cursor->saveUnpositioned(); cursor->restore(opCtx.get()); ASSERT_EQ(cursor->seek(key3, true), IndexKeyEntry(key3, loc1)); }
void save() override { // Keep original position if we haven't moved since the last restore. _opCtx = nullptr; if (_lastMoveWasRestore) return; if (_isEOF) { saveUnpositioned(); return; } _savedAtEnd = false; _savedKey = _it->key.getOwned(); _savedLoc = _it->loc; // Doing nothing with end cursor since it will do full reseek on restore. }