diff --git a/db_test.go b/db_test.go index ca2803874..61ffe7c9d 100644 --- a/db_test.go +++ b/db_test.go @@ -164,6 +164,44 @@ func runBadgerTest(t *testing.T, opts *Options, test func(t *testing.T, db *DB)) test(t, db) } +func TestReverseIterator(t *testing.T) { + runBadgerTest(t, nil, func(t *testing.T, db *DB) { + key := make([]byte, 6) + err := db.Update(func(txn *Txn) error { + binary.BigEndian.PutUint16(key, 5) + binary.BigEndian.PutUint32(key[2:], 1) + err1 := txn.Set(key, []byte("value1")) + require.NoError(t, err1) + + binary.BigEndian.PutUint32(key[2:], 2) + err1 = txn.Set(key, []byte("value2")) + require.NoError(t, err1) + return nil + }) + + require.NoError(t, err) + + err = db.View(func(txn *Txn) error { + searchBuffer := make([]byte, 3) + binary.BigEndian.PutUint16(searchBuffer, 5) + searchBuffer[2] = 0xFF + + iteratorOptions := DefaultIteratorOptions + iteratorOptions.Reverse = true + iteratorOptions.PrefetchValues = false + iteratorOptions.Prefix = searchBuffer + it := txn.NewIterator(iteratorOptions) + defer it.Close() + + it.Rewind() + require.Equal(t, it.Item().Key(), key) + return nil + }) + + require.NoError(t, err) + }) +} + func TestWrite(t *testing.T) { runBadgerTest(t, nil, func(t *testing.T, db *DB) { for i := 0; i < 100; i++ { diff --git a/iterator.go b/iterator.go index a4a611001..8662a8593 100644 --- a/iterator.go +++ b/iterator.go @@ -589,7 +589,7 @@ func (it *Iterator) Next() { // Set next item to current it.item = it.data.pop() - for it.iitr.Valid() && hasPrefix(it.iitr, it.opt.Prefix) { + for it.iitr.Valid() && hasPrefix(it) { if it.parseItem() { // parseItem calls one extra next. // This is used to deal with the complexity of reverse iteration. @@ -725,9 +725,11 @@ func (it *Iterator) fill(item *Item) { } } -func hasPrefix(it y.Iterator, prefix []byte) bool { - if len(prefix) > 0 { - return bytes.HasPrefix(y.ParseKey(it.Key()), prefix) +func hasPrefix(it *Iterator) bool { + // We shouldn't check prefix in case the iterator is going in reverse. Since in reverse we expect + // people to append items to the end of prefix. + if !it.opt.Reverse && len(it.opt.Prefix) > 0 { + return bytes.HasPrefix(y.ParseKey(it.iitr.Key()), it.opt.Prefix) } return true } @@ -741,7 +743,7 @@ func (it *Iterator) prefetch() { i := it.iitr var count int it.item = nil - for i.Valid() && hasPrefix(i, it.opt.Prefix) { + for i.Valid() && hasPrefix(it) { if !it.parseItem() { continue }