Skip to content

Commit b77f2e8

Browse files
authored
fix: fix reverse iterator broken by seek (#2109)
Fixes #2108
1 parent d114b10 commit b77f2e8

File tree

2 files changed

+45
-5
lines changed

2 files changed

+45
-5
lines changed

db_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,44 @@ func runBadgerTest(t *testing.T, opts *Options, test func(t *testing.T, db *DB))
164164
test(t, db)
165165
}
166166

167+
func TestReverseIterator(t *testing.T) {
168+
runBadgerTest(t, nil, func(t *testing.T, db *DB) {
169+
key := make([]byte, 6)
170+
err := db.Update(func(txn *Txn) error {
171+
binary.BigEndian.PutUint16(key, 5)
172+
binary.BigEndian.PutUint32(key[2:], 1)
173+
err1 := txn.Set(key, []byte("value1"))
174+
require.NoError(t, err1)
175+
176+
binary.BigEndian.PutUint32(key[2:], 2)
177+
err1 = txn.Set(key, []byte("value2"))
178+
require.NoError(t, err1)
179+
return nil
180+
})
181+
182+
require.NoError(t, err)
183+
184+
err = db.View(func(txn *Txn) error {
185+
searchBuffer := make([]byte, 3)
186+
binary.BigEndian.PutUint16(searchBuffer, 5)
187+
searchBuffer[2] = 0xFF
188+
189+
iteratorOptions := DefaultIteratorOptions
190+
iteratorOptions.Reverse = true
191+
iteratorOptions.PrefetchValues = false
192+
iteratorOptions.Prefix = searchBuffer
193+
it := txn.NewIterator(iteratorOptions)
194+
defer it.Close()
195+
196+
it.Rewind()
197+
require.Equal(t, it.Item().Key(), key)
198+
return nil
199+
})
200+
201+
require.NoError(t, err)
202+
})
203+
}
204+
167205
func TestWrite(t *testing.T) {
168206
runBadgerTest(t, nil, func(t *testing.T, db *DB) {
169207
for i := 0; i < 100; i++ {

iterator.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ func (it *Iterator) Next() {
589589

590590
// Set next item to current
591591
it.item = it.data.pop()
592-
for it.iitr.Valid() && hasPrefix(it.iitr, it.opt.Prefix) {
592+
for it.iitr.Valid() && hasPrefix(it) {
593593
if it.parseItem() {
594594
// parseItem calls one extra next.
595595
// This is used to deal with the complexity of reverse iteration.
@@ -725,9 +725,11 @@ func (it *Iterator) fill(item *Item) {
725725
}
726726
}
727727

728-
func hasPrefix(it y.Iterator, prefix []byte) bool {
729-
if len(prefix) > 0 {
730-
return bytes.HasPrefix(y.ParseKey(it.Key()), prefix)
728+
func hasPrefix(it *Iterator) bool {
729+
// We shouldn't check prefix in case the iterator is going in reverse. Since in reverse we expect
730+
// people to append items to the end of prefix.
731+
if !it.opt.Reverse && len(it.opt.Prefix) > 0 {
732+
return bytes.HasPrefix(y.ParseKey(it.iitr.Key()), it.opt.Prefix)
731733
}
732734
return true
733735
}
@@ -741,7 +743,7 @@ func (it *Iterator) prefetch() {
741743
i := it.iitr
742744
var count int
743745
it.item = nil
744-
for i.Valid() && hasPrefix(i, it.opt.Prefix) {
746+
for i.Valid() && hasPrefix(it) {
745747
if !it.parseItem() {
746748
continue
747749
}

0 commit comments

Comments
 (0)