diff --git a/db/db_iterator_test.cc b/db/db_iterator_test.cc index 997b38602..517ae3291 100644 --- a/db/db_iterator_test.cc +++ b/db/db_iterator_test.cc @@ -182,6 +182,33 @@ TEST_P(DBIteratorTest, IterSeekBeforePrev) { delete iter; } +TEST_P(DBIteratorTest, IterReseekNewUpperBound) { + Random rnd(301); + Options options = CurrentOptions(); + BlockBasedTableOptions table_options; + table_options.block_size = 1024; + table_options.block_size_deviation = 50; + options.table_factory.reset(NewBlockBasedTableFactory(table_options)); + options.compression = kNoCompression; + Reopen(options); + + ASSERT_OK(Put("a", RandomString(&rnd, 400))); + ASSERT_OK(Put("aabb", RandomString(&rnd, 400))); + ASSERT_OK(Put("aaef", RandomString(&rnd, 400))); + ASSERT_OK(Put("b", RandomString(&rnd, 400))); + dbfull()->Flush(FlushOptions()); + ReadOptions opts; + Slice ub = Slice("aa"); + opts.iterate_upper_bound = &ub; + auto iter = NewIterator(opts); + iter->Seek(Slice("a")); + ub = Slice("b"); + iter->Seek(Slice("aabc")); + ASSERT_TRUE(iter->Valid()); + ASSERT_EQ(iter->key().ToString(), "aaef"); + delete iter; +} + TEST_P(DBIteratorTest, IterSeekForPrevBeforeNext) { ASSERT_OK(Put("a", "b")); ASSERT_OK(Put("c", "d")); diff --git a/table/block_based/block_based_table_reader.cc b/table/block_based/block_based_table_reader.cc index fde11c0d3..7d3594bfd 100644 --- a/table/block_based/block_based_table_reader.cc +++ b/table/block_based/block_based_table_reader.cc @@ -2825,11 +2825,21 @@ void BlockBasedTableIterator::SeekImpl( // Index contains the first key of the block, and it's >= target. // We can defer reading the block. is_at_first_key_from_index_ = true; + // ResetDataIter() will invalidate block_iter_. Thus, there is no need to + // call CheckDataBlockWithinUpperBound() to check for iterate_upper_bound + // as that will be done later when the data block is actually read. ResetDataIter(); } else { // Need to use the data block. if (!same_block) { InitDataBlock(); + } else { + // When the user does a reseek, the iterate_upper_bound might have + // changed. CheckDataBlockWithinUpperBound() needs to be called + // explicitly if the reseek ends up in the same data block. + // If the reseek ends up in a different block, InitDataBlock() will do + // the iterator upper bound check. + CheckDataBlockWithinUpperBound(); } if (target) { @@ -2840,7 +2850,6 @@ void BlockBasedTableIterator::SeekImpl( FindKeyForward(); } - CheckDataBlockWithinUpperBound(); CheckOutOfBound(); if (target) {