mirror of https://github.com/siddontang/go.git
iterator add offset and limit, reviterator bug fix
This commit is contained in:
parent
8994b2aabd
commit
af4507fc51
|
@ -116,7 +116,7 @@ func (db *DB) Destroy() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) Clear() {
|
func (db *DB) Clear() {
|
||||||
it := db.Iterator(nil, nil, 0, -1)
|
it := db.Iterator(nil, nil, 0, 0, -1)
|
||||||
for ; it.Valid(); it.Next() {
|
for ; it.Valid(); it.Next() {
|
||||||
db.Delete(it.Key())
|
db.Delete(it.Key())
|
||||||
}
|
}
|
||||||
|
@ -142,13 +142,15 @@ func (db *DB) NewWriteBatch() *WriteBatch {
|
||||||
}
|
}
|
||||||
|
|
||||||
//limit < 0, unlimit
|
//limit < 0, unlimit
|
||||||
func (db *DB) Iterator(min []byte, max []byte, rangeType uint8, limit int) *Iterator {
|
//offset must >= 0, if < 0, will get nothing
|
||||||
return newIterator(db, db.iteratorOpts, NewRange(min, max, rangeType), limit, IteratorForward)
|
func (db *DB) Iterator(min []byte, max []byte, rangeType uint8, offset int, limit int) *Iterator {
|
||||||
|
return newIterator(db, db.iteratorOpts, NewRange(min, max, rangeType), offset, limit, IteratorForward)
|
||||||
}
|
}
|
||||||
|
|
||||||
//limit < 0, unlimit
|
//limit < 0, unlimit
|
||||||
func (db *DB) RevIterator(min []byte, max []byte, rangeType uint8, limit int) *Iterator {
|
//offset must >= 0, if < 0, will get nothing
|
||||||
return newIterator(db, db.iteratorOpts, NewRange(min, max, rangeType), limit, IteratorBackward)
|
func (db *DB) RevIterator(min []byte, max []byte, rangeType uint8, offset int, limit int) *Iterator {
|
||||||
|
return newIterator(db, db.iteratorOpts, NewRange(min, max, rangeType), offset, limit, IteratorBackward)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) NewSnapshot() *Snapshot {
|
func (db *DB) NewSnapshot() *Snapshot {
|
||||||
|
|
|
@ -39,6 +39,7 @@ type Iterator struct {
|
||||||
|
|
||||||
r *Range
|
r *Range
|
||||||
|
|
||||||
|
offset int
|
||||||
limit int
|
limit int
|
||||||
|
|
||||||
step int
|
step int
|
||||||
|
@ -47,16 +48,21 @@ type Iterator struct {
|
||||||
direction uint8
|
direction uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
func newIterator(db *DB, opts *levigo.ReadOptions, r *Range, limit int, direction uint8) *Iterator {
|
func newIterator(db *DB, opts *levigo.ReadOptions, r *Range, offset int, limit int, direction uint8) *Iterator {
|
||||||
it := new(Iterator)
|
it := new(Iterator)
|
||||||
it.it = db.db.NewIterator(opts)
|
it.it = db.db.NewIterator(opts)
|
||||||
|
|
||||||
it.r = r
|
it.r = r
|
||||||
|
it.offset = offset
|
||||||
it.limit = limit
|
it.limit = limit
|
||||||
it.direction = direction
|
it.direction = direction
|
||||||
|
|
||||||
it.step = 0
|
it.step = 0
|
||||||
|
|
||||||
|
if offset < 0 {
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
if direction == IteratorForward {
|
if direction == IteratorForward {
|
||||||
if r.Min == nil {
|
if r.Min == nil {
|
||||||
it.it.SeekToFirst()
|
it.it.SeekToFirst()
|
||||||
|
@ -64,7 +70,7 @@ func newIterator(db *DB, opts *levigo.ReadOptions, r *Range, limit int, directio
|
||||||
it.it.Seek(r.Min)
|
it.it.Seek(r.Min)
|
||||||
|
|
||||||
if r.Type&RangeLOpen > 0 {
|
if r.Type&RangeLOpen > 0 {
|
||||||
if it.Valid() && bytes.Equal(it.Key(), r.Min) {
|
if it.it.Valid() && bytes.Equal(it.it.Key(), r.Min) {
|
||||||
it.it.Next()
|
it.it.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,10 +80,14 @@ func newIterator(db *DB, opts *levigo.ReadOptions, r *Range, limit int, directio
|
||||||
it.it.SeekToLast()
|
it.it.SeekToLast()
|
||||||
} else {
|
} else {
|
||||||
it.it.Seek(r.Max)
|
it.it.Seek(r.Max)
|
||||||
if it.Valid() && !bytes.Equal(it.Key(), r.Max) {
|
|
||||||
//key must bigger than max, so we must go prev
|
if !it.it.Valid() {
|
||||||
|
it.it.SeekToLast()
|
||||||
|
} else {
|
||||||
|
if !bytes.Equal(it.it.Key(), r.Max) {
|
||||||
it.it.Prev()
|
it.it.Prev()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if r.Type&RangeROpen > 0 {
|
if r.Type&RangeROpen > 0 {
|
||||||
if it.Valid() && bytes.Equal(it.Key(), r.Max) {
|
if it.Valid() && bytes.Equal(it.Key(), r.Max) {
|
||||||
|
@ -87,15 +97,21 @@ func newIterator(db *DB, opts *levigo.ReadOptions, r *Range, limit int, directio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i := 0; i < offset; i++ {
|
||||||
|
if it.Valid() {
|
||||||
|
it.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *Iterator) Valid() bool {
|
func (it *Iterator) Valid() bool {
|
||||||
if !it.it.Valid() {
|
if it.offset < 0 {
|
||||||
return false
|
return false
|
||||||
}
|
} else if !it.it.Valid() {
|
||||||
|
return false
|
||||||
if it.limit >= 0 && it.step >= it.limit {
|
} else if it.limit >= 0 && it.step >= it.limit {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,14 +152,6 @@ func (it *Iterator) Next() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (it *Iterator) Skip(offset int64) {
|
|
||||||
for i := int64(0); i < offset; i++ {
|
|
||||||
if it.Valid() {
|
|
||||||
it.Next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (it *Iterator) Key() []byte {
|
func (it *Iterator) Key() []byte {
|
||||||
return it.it.Key()
|
return it.it.Key()
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,52 +146,52 @@ func TestIterator(t *testing.T) {
|
||||||
return []byte(fmt.Sprintf("key_%d", i))
|
return []byte(fmt.Sprintf("key_%d", i))
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.Iterator(k(1), k(5), RangeClose, -1)
|
it = db.Iterator(k(1), k(5), RangeClose, 0, -1)
|
||||||
if err := checkIterator(it, 1, 2, 3, 4, 5); err != nil {
|
if err := checkIterator(it, 1, 2, 3, 4, 5); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.Iterator(k(1), k(5), RangeClose, 3)
|
it = db.Iterator(k(1), k(5), RangeClose, 1, 3)
|
||||||
if err := checkIterator(it, 1, 2, 3); err != nil {
|
if err := checkIterator(it, 2, 3); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.Iterator(k(1), k(5), RangeLOpen, -1)
|
it = db.Iterator(k(1), k(5), RangeLOpen, 0, -1)
|
||||||
if err := checkIterator(it, 2, 3, 4, 5); err != nil {
|
if err := checkIterator(it, 2, 3, 4, 5); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.Iterator(k(1), k(5), RangeROpen, -1)
|
it = db.Iterator(k(1), k(5), RangeROpen, 0, -1)
|
||||||
if err := checkIterator(it, 1, 2, 3, 4); err != nil {
|
if err := checkIterator(it, 1, 2, 3, 4); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.Iterator(k(1), k(5), RangeOpen, -1)
|
it = db.Iterator(k(1), k(5), RangeOpen, 0, -1)
|
||||||
if err := checkIterator(it, 2, 3, 4); err != nil {
|
if err := checkIterator(it, 2, 3, 4); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.RevIterator(k(1), k(5), RangeClose, -1)
|
it = db.RevIterator(k(1), k(5), RangeClose, 0, -1)
|
||||||
if err := checkIterator(it, 5, 4, 3, 2, 1); err != nil {
|
if err := checkIterator(it, 5, 4, 3, 2, 1); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.RevIterator(k(1), k(5), RangeClose, 3)
|
it = db.RevIterator(k(1), k(5), RangeClose, 1, 3)
|
||||||
if err := checkIterator(it, 5, 4, 3); err != nil {
|
if err := checkIterator(it, 4, 3); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.RevIterator(k(1), k(5), RangeLOpen, -1)
|
it = db.RevIterator(k(1), k(5), RangeLOpen, 0, -1)
|
||||||
if err := checkIterator(it, 5, 4, 3, 2); err != nil {
|
if err := checkIterator(it, 5, 4, 3, 2); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.RevIterator(k(1), k(5), RangeROpen, -1)
|
it = db.RevIterator(k(1), k(5), RangeROpen, 0, -1)
|
||||||
if err := checkIterator(it, 4, 3, 2, 1); err != nil {
|
if err := checkIterator(it, 4, 3, 2, 1); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
it = db.RevIterator(k(1), k(5), RangeOpen, -1)
|
it = db.RevIterator(k(1), k(5), RangeOpen, 0, -1)
|
||||||
if err := checkIterator(it, 4, 3, 2); err != nil {
|
if err := checkIterator(it, 4, 3, 2); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,12 +37,12 @@ func (s *Snapshot) Get(key []byte) ([]byte, error) {
|
||||||
return s.db.db.Get(s.readOpts, key)
|
return s.db.db.Get(s.readOpts, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Snapshot) Iterator(min []byte, max []byte, rangeType uint8, limit int) *Iterator {
|
func (s *Snapshot) Iterator(min []byte, max []byte, rangeType uint8, offset int, limit int) *Iterator {
|
||||||
return newIterator(s.db, s.iteratorOpts, NewRange(min, max, rangeType), limit, IteratorForward)
|
return newIterator(s.db, s.iteratorOpts, NewRange(min, max, rangeType), offset, limit, IteratorForward)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Snapshot) RevIterator(min []byte, max []byte, rangeType uint8, limit int) *Iterator {
|
func (s *Snapshot) RevIterator(min []byte, max []byte, rangeType uint8, offset int, limit int) *Iterator {
|
||||||
return newIterator(s.db, s.iteratorOpts, NewRange(min, max, rangeType), limit, IteratorBackward)
|
return newIterator(s.db, s.iteratorOpts, NewRange(min, max, rangeType), offset, limit, IteratorBackward)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Snapshot) GetInt(key []byte) (int64, error) {
|
func (s *Snapshot) GetInt(key []byte) (int64, error) {
|
||||||
|
|
Loading…
Reference in New Issue