diff --git a/pkg/storage/engine.go b/pkg/storage/engine.go index d0a4041a4972..eaf825a7e7ad 100644 --- a/pkg/storage/engine.go +++ b/pkg/storage/engine.go @@ -364,6 +364,17 @@ type IterOptions struct { // MVCCIterators from them. Range key behavior for EngineIterators is // undefined. KeyTypes IterKeyType + // RangeKeyMaskingBelow enables masking (hiding) of point keys by range keys. + // Any range key with a timestamp at or below the RangeKeyMaskingBelow + // timestamp will mask point keys below it, preventing them from being + // surfaced. Consider the following example: + // + // 4 o---------------o RangeKeyMaskingBelow=4 emits b3 + // 3 b3 d3 RangeKeyMaskingBelow=3 emits b3,d3,f2 + // 2 o---------------o f2 RangeKeyMaskingBelow=2 emits b3,d3,f2 + // 1 a1 b1 o-------o RangeKeyMaskingBelow=1 emits a1,b3,b1,d3,f2 + // a b c d e f g + RangeKeyMaskingBelow hlc.Timestamp } // IterKeyType configures which types of keys an iterator should surface. diff --git a/pkg/storage/mvcc_history_test.go b/pkg/storage/mvcc_history_test.go index 2bcdd0689935..a7a5da438e73 100644 --- a/pkg/storage/mvcc_history_test.go +++ b/pkg/storage/mvcc_history_test.go @@ -70,7 +70,7 @@ import ( // put_rangekey k= end= ts=[,] // scan [t=] [ts=[,]] [resolve [status=]] k= [end=] [inconsistent] [tombstones] [reverse] [failOnMoreRecent] [localUncertaintyLimit=[,]] [globalUncertaintyLimit=[,]] [max=] [targetbytes=] [avoidExcess] [allowEmpty] // -// iter [k=] [end=] [kind=key|keyAndIntents] [types=pointsOnly|pointsWithRanges|pointsAndRanges|rangesOnly] +// iter [k=] [end=] [kind=key|keyAndIntents] [types=pointsOnly|pointsWithRanges|pointsAndRanges|rangesOnly] [maskBelow=[,]] // iter_seek_ge k= [ts=[,]] // iter_seek_lt k= [ts=[,]] // iter_seek_intent_ge k= txn= @@ -974,6 +974,9 @@ func cmdIterNew(e *evalCtx) error { return errors.Errorf("unknown key type %s", arg) } } + if e.hasArg("maskBelow") { + opts.RangeKeyMaskingBelow = e.getTsWithName(nil, "maskBelow") + } var r, closeReader Reader rType := util.ConstantWithMetamorphicTestChoice( diff --git a/pkg/storage/pebble.go b/pkg/storage/pebble.go index 29fdb86b3ca8..8d46c5867eac 100644 --- a/pkg/storage/pebble.go +++ b/pkg/storage/pebble.go @@ -1946,7 +1946,8 @@ func (p *pebbleReadOnly) NewMVCCIterator(iterKind MVCCIterKind, opts IterOptions } // TODO(erikgrinaker): We should generalize and consolidate iterator reuse. - reusable := opts.MinTimestampHint.IsEmpty() && opts.KeyTypes == IterKeyTypePointsOnly + reusable := opts.MinTimestampHint.IsEmpty() && opts.KeyTypes == IterKeyTypePointsOnly && + opts.RangeKeyMaskingBelow.IsEmpty() if !reusable { iter := MVCCIterator(newPebbleIterator( p.parent.db, nil, opts, p.durability, p.parent.db.FormatMajorVersion())) @@ -1991,7 +1992,7 @@ func (p *pebbleReadOnly) NewEngineIterator(opts IterOptions) EngineIterator { panic("using a closed pebbleReadOnly") } - reusable := opts.KeyTypes == IterKeyTypePointsOnly + reusable := opts.KeyTypes == IterKeyTypePointsOnly && opts.RangeKeyMaskingBelow.IsEmpty() if !reusable { return newPebbleIterator( p.parent.db, nil, opts, StandardDurability, p.parent.db.FormatMajorVersion()) @@ -2033,6 +2034,9 @@ func checkOptionsForIterReuse(opts IterOptions) { if opts.KeyTypes != IterKeyTypePointsOnly { panic("iterators with range keys cannot be reused") } + if opts.RangeKeyMaskingBelow.IsSet() { + panic("iterators with range key masking cannot be reused") + } if !opts.Prefix && len(opts.UpperBound) == 0 && len(opts.LowerBound) == 0 { panic("iterator must set prefix or upper bound or lower bound") } diff --git a/pkg/storage/pebble_batch.go b/pkg/storage/pebble_batch.go index 40b8577c83d2..43ccd74eed4a 100644 --- a/pkg/storage/pebble_batch.go +++ b/pkg/storage/pebble_batch.go @@ -207,7 +207,8 @@ func (p *pebbleBatch) NewMVCCIterator(iterKind MVCCIterKind, opts IterOptions) M return iter } - reusable := opts.MinTimestampHint.IsEmpty() && opts.KeyTypes == IterKeyTypePointsOnly + reusable := opts.MinTimestampHint.IsEmpty() && opts.KeyTypes == IterKeyTypePointsOnly && + opts.RangeKeyMaskingBelow.IsEmpty() if !reusable { iter := MVCCIterator(newPebbleIterator( p.batch, nil, opts, StandardDurability, p.db.FormatMajorVersion())) @@ -259,7 +260,7 @@ func (p *pebbleBatch) NewEngineIterator(opts IterOptions) EngineIterator { panic("write-only batch") } - reusable := opts.KeyTypes == IterKeyTypePointsOnly + reusable := opts.KeyTypes == IterKeyTypePointsOnly && opts.RangeKeyMaskingBelow.IsEmpty() if !reusable { return newPebbleIterator(p.batch, nil, opts, StandardDurability, p.db.FormatMajorVersion()) } diff --git a/pkg/storage/pebble_iterator.go b/pkg/storage/pebble_iterator.go index f7af9675e4e4..7599e2069996 100644 --- a/pkg/storage/pebble_iterator.go +++ b/pkg/storage/pebble_iterator.go @@ -217,6 +217,12 @@ func (p *pebbleIterator) init( } } + if opts.RangeKeyMaskingBelow.IsSet() { + p.options.RangeKeyMasking = pebble.RangeKeyMasking{ + Suffix: EncodeMVCCTimestampSuffix(opts.RangeKeyMaskingBelow), + } + } + if doClone { var err error if p.iter, err = iterToClone.Clone(); err != nil { diff --git a/pkg/storage/testdata/mvcc_histories/range_key_iter b/pkg/storage/testdata/mvcc_histories/range_key_iter index a88c822bf33c..c61ea07de87f 100644 --- a/pkg/storage/testdata/mvcc_histories/range_key_iter +++ b/pkg/storage/testdata/mvcc_histories/range_key_iter @@ -6,9 +6,9 @@ # 7 [d7] [j7] # 6 f6 # 5 o---------------o k5 -# 4 x x d4 g4 +# 4 x x d4 f4 g4 # 3 o-------o e3 o-------oh3 -# 2 a2 g2 +# 2 a2 f2 g2 # 1 o---------------------------------------o # a b c d e f g h i j k # @@ -22,6 +22,8 @@ del k=a ts=4 del k=b ts=4 put k=d ts=4 v=d4 put k=e ts=3 v=e3 +put k=f ts=2 v=f2 +put k=f ts=4 v=f4 put k=f ts=6 v=f6 put k=g ts=2 v=g2 put k=g ts=4 v=g4 @@ -49,6 +51,8 @@ data: "d"/7.000000000,0 -> /BYTES/d7 data: "d"/4.000000000,0 -> /BYTES/d4 data: "e"/3.000000000,0 -> /BYTES/e3 data: "f"/6.000000000,0 -> /BYTES/f6 +data: "f"/4.000000000,0 -> /BYTES/f4 +data: "f"/2.000000000,0 -> /BYTES/f2 data: "g"/4.000000000,0 -> /BYTES/g4 data: "g"/2.000000000,0 -> /BYTES/g2 data: "h"/3.000000000,0 -> /BYTES/h3 @@ -71,6 +75,8 @@ iter_scan: "d"/7.000000000,0=/BYTES/d7 iter_scan: "d"/4.000000000,0=/BYTES/d4 iter_scan: "e"/3.000000000,0=/BYTES/e3 iter_scan: "f"/6.000000000,0=/BYTES/f6 +iter_scan: "f"/4.000000000,0=/BYTES/f4 +iter_scan: "f"/2.000000000,0=/BYTES/f2 iter_scan: "g"/4.000000000,0=/BYTES/g4 iter_scan: "g"/2.000000000,0=/BYTES/g2 iter_scan: "h"/3.000000000,0=/BYTES/h3 @@ -93,6 +99,8 @@ iter_scan: "d"/7.000000000,0=/BYTES/d7 {d-f}/[5.000000000,0 1.000000000,0] iter_scan: "d"/4.000000000,0=/BYTES/d4 {d-f}/[5.000000000,0 1.000000000,0] iter_scan: "e"/3.000000000,0=/BYTES/e3 {d-f}/[5.000000000,0 1.000000000,0] iter_scan: "f"/6.000000000,0=/BYTES/f6 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/4.000000000,0=/BYTES/f4 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/2.000000000,0=/BYTES/f2 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: "g"/4.000000000,0=/BYTES/g4 {g-h}/[3.000000000,0 1.000000000,0] iter_scan: "g"/2.000000000,0=/BYTES/g2 {g-h}/[3.000000000,0 1.000000000,0] iter_scan: "h"/3.000000000,0=/BYTES/h3 {h-k}/[1.000000000,0] @@ -120,6 +128,8 @@ iter_scan: "d"/4.000000000,0=/BYTES/d4 {d-f}/[5.000000000,0 1.000000000,0] iter_scan: "e"/3.000000000,0=/BYTES/e3 {d-f}/[5.000000000,0 1.000000000,0] iter_scan: {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: "f"/6.000000000,0=/BYTES/f6 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/4.000000000,0=/BYTES/f4 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/2.000000000,0=/BYTES/f2 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: {g-h}/[3.000000000,0 1.000000000,0] iter_scan: "g"/4.000000000,0=/BYTES/g4 {g-h}/[3.000000000,0 1.000000000,0] iter_scan: "g"/2.000000000,0=/BYTES/g2 {g-h}/[3.000000000,0 1.000000000,0] @@ -163,6 +173,8 @@ iter_scan: "d"/4.000000000,0=/BYTES/d4 {d-f}/[5.000000000,0 1.000000000,0] iter_scan: "e"/3.000000000,0=/BYTES/e3 {d-f}/[5.000000000,0 1.000000000,0] iter_scan: {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: "f"/6.000000000,0=/BYTES/f6 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/4.000000000,0=/BYTES/f4 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/2.000000000,0=/BYTES/f2 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: {g-h}/[3.000000000,0 1.000000000,0] iter_scan: "g"/4.000000000,0=/BYTES/g4 {g-h}/[3.000000000,0 1.000000000,0] iter_scan: "g"/2.000000000,0=/BYTES/g2 {g-h}/[3.000000000,0 1.000000000,0] @@ -185,6 +197,8 @@ iter_scan: "j"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000 iter_scan: "h"/3.000000000,0=/BYTES/h3 iter_scan: "g"/2.000000000,0=/BYTES/g2 iter_scan: "g"/4.000000000,0=/BYTES/g4 +iter_scan: "f"/2.000000000,0=/BYTES/f2 +iter_scan: "f"/4.000000000,0=/BYTES/f4 iter_scan: "f"/6.000000000,0=/BYTES/f6 iter_scan: "e"/3.000000000,0=/BYTES/e3 iter_scan: "d"/4.000000000,0=/BYTES/d4 @@ -207,6 +221,8 @@ iter_scan: "j"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000 iter_scan: "h"/3.000000000,0=/BYTES/h3 {h-k}/[1.000000000,0] iter_scan: "g"/2.000000000,0=/BYTES/g2 {g-h}/[3.000000000,0 1.000000000,0] iter_scan: "g"/4.000000000,0=/BYTES/g4 {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: "f"/2.000000000,0=/BYTES/f2 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/4.000000000,0=/BYTES/f4 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: "f"/6.000000000,0=/BYTES/f6 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: "e"/3.000000000,0=/BYTES/e3 {d-f}/[5.000000000,0 1.000000000,0] iter_scan: "d"/4.000000000,0=/BYTES/d4 {d-f}/[5.000000000,0 1.000000000,0] @@ -231,6 +247,8 @@ iter_scan: {h-k}/[1.000000000,0] iter_scan: "g"/2.000000000,0=/BYTES/g2 {g-h}/[3.000000000,0 1.000000000,0] iter_scan: "g"/4.000000000,0=/BYTES/g4 {g-h}/[3.000000000,0 1.000000000,0] iter_scan: {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: "f"/2.000000000,0=/BYTES/f2 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/4.000000000,0=/BYTES/f4 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: "f"/6.000000000,0=/BYTES/f6 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: "e"/3.000000000,0=/BYTES/e3 {d-f}/[5.000000000,0 1.000000000,0] @@ -274,6 +292,8 @@ iter_scan: {h-k}/[1.000000000,0] iter_scan: "g"/2.000000000,0=/BYTES/g2 {g-h}/[3.000000000,0 1.000000000,0] iter_scan: "g"/4.000000000,0=/BYTES/g4 {g-h}/[3.000000000,0 1.000000000,0] iter_scan: {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: "f"/2.000000000,0=/BYTES/f2 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/4.000000000,0=/BYTES/f4 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: "f"/6.000000000,0=/BYTES/f6 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: "e"/3.000000000,0=/BYTES/e3 {d-f}/[5.000000000,0 1.000000000,0] @@ -306,8 +326,12 @@ iter_scan: "d"/4.000000000,0=/BYTES/d4 {d-f}/[5.000000000,0 1.000000000,0] iter_scan: "e"/3.000000000,0=/BYTES/e3 {d-f}/[5.000000000,0 1.000000000,0] iter_scan: f{-ff}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: "f"/6.000000000,0=/BYTES/f6 f{-ff}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/4.000000000,0=/BYTES/f4 f{-ff}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/2.000000000,0=/BYTES/f2 f{-ff}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: . -iter_seek_lt: "f"/6.000000000,0=/BYTES/f6 f{-ff}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_seek_lt: "f"/2.000000000,0=/BYTES/f2 f{-ff}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/2.000000000,0=/BYTES/f2 f{-ff}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/4.000000000,0=/BYTES/f4 f{-ff}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: "f"/6.000000000,0=/BYTES/f6 f{-ff}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: f{-ff}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: "e"/3.000000000,0=/BYTES/e3 {d-f}/[5.000000000,0 1.000000000,0] @@ -319,6 +343,179 @@ iter_scan: {c-d}/[5.000000000,0 3.000000000,0 1.000000000,0] iter_scan: {bbb-c}/[3.000000000,0 1.000000000,0] iter_scan: . +# Try some masked scans at increasing timestamps. +run ok +iter_new types=pointsAndRanges maskBelow=1 +iter_seek_ge k=a +iter_scan +---- +iter_seek_ge: {a-b}/[1.000000000,0] +iter_scan: {a-b}/[1.000000000,0] +iter_scan: "a"/4.000000000,0=/ {a-b}/[1.000000000,0] +iter_scan: "a"/2.000000000,0=/BYTES/a2 {a-b}/[1.000000000,0] +iter_scan: {b-c}/[3.000000000,0 1.000000000,0] +iter_scan: "b"/4.000000000,0=/ {b-c}/[3.000000000,0 1.000000000,0] +iter_scan: {c-d}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000,0 min=0,0 seq=0} ts=7.000000000,0 del=false klen=12 vlen=7 mergeTs= txnDidNotUpdateMeta=true {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/7.000000000,0=/BYTES/d7 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/4.000000000,0=/BYTES/d4 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "e"/3.000000000,0=/BYTES/e3 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/6.000000000,0=/BYTES/f6 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/4.000000000,0=/BYTES/f4 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/2.000000000,0=/BYTES/f2 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: "g"/4.000000000,0=/BYTES/g4 {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: "g"/2.000000000,0=/BYTES/g2 {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: {h-k}/[1.000000000,0] +iter_scan: "h"/3.000000000,0=/BYTES/h3 {h-k}/[1.000000000,0] +iter_scan: "j"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000,0 min=0,0 seq=0} ts=7.000000000,0 del=false klen=12 vlen=7 mergeTs= txnDidNotUpdateMeta=true {h-k}/[1.000000000,0] +iter_scan: "j"/7.000000000,0=/BYTES/j7 {h-k}/[1.000000000,0] +iter_scan: "k"/5.000000000,0=/BYTES/k5 +iter_scan: . + +run ok +iter_new types=pointsAndRanges maskBelow=2 +iter_seek_ge k=a +iter_scan +---- +iter_seek_ge: {a-b}/[1.000000000,0] +iter_scan: {a-b}/[1.000000000,0] +iter_scan: "a"/4.000000000,0=/ {a-b}/[1.000000000,0] +iter_scan: "a"/2.000000000,0=/BYTES/a2 {a-b}/[1.000000000,0] +iter_scan: {b-c}/[3.000000000,0 1.000000000,0] +iter_scan: "b"/4.000000000,0=/ {b-c}/[3.000000000,0 1.000000000,0] +iter_scan: {c-d}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000,0 min=0,0 seq=0} ts=7.000000000,0 del=false klen=12 vlen=7 mergeTs= txnDidNotUpdateMeta=true {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/7.000000000,0=/BYTES/d7 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/4.000000000,0=/BYTES/d4 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "e"/3.000000000,0=/BYTES/e3 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/6.000000000,0=/BYTES/f6 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/4.000000000,0=/BYTES/f4 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/2.000000000,0=/BYTES/f2 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: "g"/4.000000000,0=/BYTES/g4 {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: "g"/2.000000000,0=/BYTES/g2 {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: {h-k}/[1.000000000,0] +iter_scan: "h"/3.000000000,0=/BYTES/h3 {h-k}/[1.000000000,0] +iter_scan: "j"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000,0 min=0,0 seq=0} ts=7.000000000,0 del=false klen=12 vlen=7 mergeTs= txnDidNotUpdateMeta=true {h-k}/[1.000000000,0] +iter_scan: "j"/7.000000000,0=/BYTES/j7 {h-k}/[1.000000000,0] +iter_scan: "k"/5.000000000,0=/BYTES/k5 +iter_scan: . + +run ok +iter_new types=pointsAndRanges maskBelow=3 +iter_seek_ge k=a +iter_scan +---- +iter_seek_ge: {a-b}/[1.000000000,0] +iter_scan: {a-b}/[1.000000000,0] +iter_scan: "a"/4.000000000,0=/ {a-b}/[1.000000000,0] +iter_scan: "a"/2.000000000,0=/BYTES/a2 {a-b}/[1.000000000,0] +iter_scan: {b-c}/[3.000000000,0 1.000000000,0] +iter_scan: "b"/4.000000000,0=/ {b-c}/[3.000000000,0 1.000000000,0] +iter_scan: {c-d}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000,0 min=0,0 seq=0} ts=7.000000000,0 del=false klen=12 vlen=7 mergeTs= txnDidNotUpdateMeta=true {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/7.000000000,0=/BYTES/d7 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/4.000000000,0=/BYTES/d4 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "e"/3.000000000,0=/BYTES/e3 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/6.000000000,0=/BYTES/f6 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/4.000000000,0=/BYTES/f4 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: "g"/4.000000000,0=/BYTES/g4 {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: {h-k}/[1.000000000,0] +iter_scan: "h"/3.000000000,0=/BYTES/h3 {h-k}/[1.000000000,0] +iter_scan: "j"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000,0 min=0,0 seq=0} ts=7.000000000,0 del=false klen=12 vlen=7 mergeTs= txnDidNotUpdateMeta=true {h-k}/[1.000000000,0] +iter_scan: "j"/7.000000000,0=/BYTES/j7 {h-k}/[1.000000000,0] +iter_scan: "k"/5.000000000,0=/BYTES/k5 +iter_scan: . + +run ok +iter_new types=pointsAndRanges maskBelow=4 +iter_seek_ge k=a +iter_scan +---- +iter_seek_ge: {a-b}/[1.000000000,0] +iter_scan: {a-b}/[1.000000000,0] +iter_scan: "a"/4.000000000,0=/ {a-b}/[1.000000000,0] +iter_scan: "a"/2.000000000,0=/BYTES/a2 {a-b}/[1.000000000,0] +iter_scan: {b-c}/[3.000000000,0 1.000000000,0] +iter_scan: "b"/4.000000000,0=/ {b-c}/[3.000000000,0 1.000000000,0] +iter_scan: {c-d}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000,0 min=0,0 seq=0} ts=7.000000000,0 del=false klen=12 vlen=7 mergeTs= txnDidNotUpdateMeta=true {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/7.000000000,0=/BYTES/d7 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/4.000000000,0=/BYTES/d4 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "e"/3.000000000,0=/BYTES/e3 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/6.000000000,0=/BYTES/f6 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/4.000000000,0=/BYTES/f4 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: "g"/4.000000000,0=/BYTES/g4 {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: {h-k}/[1.000000000,0] +iter_scan: "h"/3.000000000,0=/BYTES/h3 {h-k}/[1.000000000,0] +iter_scan: "j"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000,0 min=0,0 seq=0} ts=7.000000000,0 del=false klen=12 vlen=7 mergeTs= txnDidNotUpdateMeta=true {h-k}/[1.000000000,0] +iter_scan: "j"/7.000000000,0=/BYTES/j7 {h-k}/[1.000000000,0] +iter_scan: "k"/5.000000000,0=/BYTES/k5 +iter_scan: . + +run ok +iter_new types=pointsAndRanges maskBelow=5 +iter_seek_ge k=a +iter_scan +---- +iter_seek_ge: {a-b}/[1.000000000,0] +iter_scan: {a-b}/[1.000000000,0] +iter_scan: "a"/4.000000000,0=/ {a-b}/[1.000000000,0] +iter_scan: "a"/2.000000000,0=/BYTES/a2 {a-b}/[1.000000000,0] +iter_scan: {b-c}/[3.000000000,0 1.000000000,0] +iter_scan: "b"/4.000000000,0=/ {b-c}/[3.000000000,0 1.000000000,0] +iter_scan: {c-d}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000,0 min=0,0 seq=0} ts=7.000000000,0 del=false klen=12 vlen=7 mergeTs= txnDidNotUpdateMeta=true {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/7.000000000,0=/BYTES/d7 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/6.000000000,0=/BYTES/f6 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: "g"/4.000000000,0=/BYTES/g4 {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: {h-k}/[1.000000000,0] +iter_scan: "h"/3.000000000,0=/BYTES/h3 {h-k}/[1.000000000,0] +iter_scan: "j"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000,0 min=0,0 seq=0} ts=7.000000000,0 del=false klen=12 vlen=7 mergeTs= txnDidNotUpdateMeta=true {h-k}/[1.000000000,0] +iter_scan: "j"/7.000000000,0=/BYTES/j7 {h-k}/[1.000000000,0] +iter_scan: "k"/5.000000000,0=/BYTES/k5 +iter_scan: . + +run ok +iter_new types=pointsAndRanges maskBelow=6 +iter_seek_ge k=a +iter_scan +---- +iter_seek_ge: {a-b}/[1.000000000,0] +iter_scan: {a-b}/[1.000000000,0] +iter_scan: "a"/4.000000000,0=/ {a-b}/[1.000000000,0] +iter_scan: "a"/2.000000000,0=/BYTES/a2 {a-b}/[1.000000000,0] +iter_scan: {b-c}/[3.000000000,0 1.000000000,0] +iter_scan: "b"/4.000000000,0=/ {b-c}/[3.000000000,0 1.000000000,0] +iter_scan: {c-d}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000,0 min=0,0 seq=0} ts=7.000000000,0 del=false klen=12 vlen=7 mergeTs= txnDidNotUpdateMeta=true {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: "d"/7.000000000,0=/BYTES/d7 {d-f}/[5.000000000,0 1.000000000,0] +iter_scan: {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: "f"/6.000000000,0=/BYTES/f6 {f-g}/[5.000000000,0 3.000000000,0 1.000000000,0] +iter_scan: {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: "g"/4.000000000,0=/BYTES/g4 {g-h}/[3.000000000,0 1.000000000,0] +iter_scan: {h-k}/[1.000000000,0] +iter_scan: "h"/3.000000000,0=/BYTES/h3 {h-k}/[1.000000000,0] +iter_scan: "j"/0,0=txn={id=00000000 key=/Min pri=0.00000000 epo=0 ts=7.000000000,0 min=0,0 seq=0} ts=7.000000000,0 del=false klen=12 vlen=7 mergeTs= txnDidNotUpdateMeta=true {h-k}/[1.000000000,0] +iter_scan: "j"/7.000000000,0=/BYTES/j7 {h-k}/[1.000000000,0] +iter_scan: "k"/5.000000000,0=/BYTES/k5 +iter_scan: . + # Seek to d, iterate a few times, then reverse direction and iterate beyond seek point. run ok iter_new types=pointsAndRanges