diff --git a/pkg/storage/engine.go b/pkg/storage/engine.go index f2892bde4c0d..f5454a7502f3 100644 --- a/pkg/storage/engine.go +++ b/pkg/storage/engine.go @@ -341,6 +341,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/engine_test.go b/pkg/storage/engine_test.go index a3314ceae4a7..911d44f1dce0 100644 --- a/pkg/storage/engine_test.go +++ b/pkg/storage/engine_test.go @@ -2043,8 +2043,9 @@ func TestEngineRangeKeysUnsupported(t *testing.T) { require.False(t, r.SupportsRangeKeys()) iter := r.NewMVCCIterator(MVCCKeyAndIntentsIterKind, IterOptions{ - KeyTypes: keyType, - UpperBound: keys.MaxKey, + KeyTypes: keyType, + UpperBound: keys.MaxKey, + RangeKeyMaskingBelow: hlc.Timestamp{WallTime: 1}, // should disable when unsupported }) defer iter.Close() diff --git a/pkg/storage/mvcc_history_test.go b/pkg/storage/mvcc_history_test.go index e27a57508d97..3c7bcef120eb 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= @@ -972,6 +972,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_iterator.go b/pkg/storage/pebble_iterator.go index 4a1e21ab5d09..621628d88aff 100644 --- a/pkg/storage/pebble_iterator.go +++ b/pkg/storage/pebble_iterator.go @@ -18,6 +18,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/keys" "github.com/cockroachdb/cockroach/pkg/roachpb" "github.com/cockroachdb/cockroach/pkg/storage/enginepb" + "github.com/cockroachdb/cockroach/pkg/util/hlc" "github.com/cockroachdb/cockroach/pkg/util/protoutil" "github.com/cockroachdb/cockroach/pkg/util/uuid" "github.com/cockroachdb/errors" @@ -159,6 +160,7 @@ func (p *pebbleIterator) setOptions(opts IterOptions, durability DurabilityRequi opts.UpperBound = []byte{0} } opts.KeyTypes = IterKeyTypePointsOnly + opts.RangeKeyMaskingBelow = hlc.Timestamp{} } // Generate new Pebble iterator options. @@ -168,6 +170,10 @@ func (p *pebbleIterator) setOptions(opts IterOptions, durability DurabilityRequi newOptions := pebble.IterOptions{ OnlyReadGuaranteedDurable: durability == GuaranteedDurability, KeyTypes: opts.KeyTypes, + RangeKeyMasking: pebble.RangeKeyMasking{ + // TODO(erikgrinaker): Consider reusing a buffer if necessary. + Suffix: EncodeMVCCTimestampSuffix(opts.RangeKeyMaskingBelow), + }, } newBuf := 1 - p.curBuf @@ -236,6 +242,7 @@ func (p *pebbleIterator) setOptions(opts IterOptions, durability DurabilityRequi newOptions.KeyTypes != p.options.KeyTypes || !bytes.Equal(newOptions.UpperBound, p.options.UpperBound) || !bytes.Equal(newOptions.LowerBound, p.options.LowerBound) || + !bytes.Equal(newOptions.RangeKeyMasking.Suffix, p.options.RangeKeyMasking.Suffix) || // We can't compare these filters, so if any existing or new filters are set // we consider them changed. newOptions.TableFilter != nil || p.options.TableFilter != nil || diff --git a/pkg/storage/testdata/mvcc_histories/range_key_iter b/pkg/storage/testdata/mvcc_histories/range_key_iter index e26ebe983d10..369d6b633e29 100644 --- a/pkg/storage/testdata/mvcc_histories/range_key_iter +++ b/pkg/storage/testdata/mvcc_histories/range_key_iter @@ -6,11 +6,11 @@ # 7 [a7] [d7] [j7] [l7] # 6 f6 # 5 o---------------o k5 -# 4 x x d4 g4 x +# 4 x x d4 f4 g4 # 3 o-------o e3 o-------oh3 -# 2 a2 g2 -# 1 o---------------------------------------o o---o -# a b c d e f g h i j k l m +# 2 a2 f2 g2 +# 1 o---------------------------------------o +# a b c d e f g h i j k # run ok put_rangekey k=a end=k ts=1 @@ -23,6 +23,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 @@ -56,6 +58,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"/4.000000000,0 -> / @@ -83,6 +87,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"/4.000000000,0=/ @@ -113,6 +119,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] @@ -161,6 +169,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] @@ -189,6 +199,8 @@ iter_scan: "h"/3.000000000,0=/BYTES/h3 iter_scan: "h"/4.000000000,0=/ 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 @@ -218,6 +230,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] @@ -265,6 +279,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] @@ -297,8 +313,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] @@ -309,6 +329,197 @@ 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"/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 {a-b}/[1.000000000,0] +iter_scan: "a"/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 {a-b}/[1.000000000,0] +iter_scan: "a"/7.000000000,0=/BYTES/a7 {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"/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"/4.000000000,0=/ {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: "l"/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 {l-m}/[1.000000000,0] +iter_scan: "l"/7.000000000,0=/BYTES/l7 {l-m}/[1.000000000,0] +iter_scan: . + +run ok +iter_new types=pointsAndRanges maskBelow=2 +iter_seek_ge k=a +iter_scan +---- +iter_seek_ge: "a"/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 {a-b}/[1.000000000,0] +iter_scan: "a"/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 {a-b}/[1.000000000,0] +iter_scan: "a"/7.000000000,0=/BYTES/a7 {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"/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"/4.000000000,0=/ {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: "l"/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 {l-m}/[1.000000000,0] +iter_scan: "l"/7.000000000,0=/BYTES/l7 {l-m}/[1.000000000,0] +iter_scan: . + +run ok +iter_new types=pointsAndRanges maskBelow=3 +iter_seek_ge k=a +iter_scan +---- +iter_seek_ge: "a"/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 {a-b}/[1.000000000,0] +iter_scan: "a"/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 {a-b}/[1.000000000,0] +iter_scan: "a"/7.000000000,0=/BYTES/a7 {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"/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"/4.000000000,0=/ {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: "l"/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 {l-m}/[1.000000000,0] +iter_scan: "l"/7.000000000,0=/BYTES/l7 {l-m}/[1.000000000,0] +iter_scan: . + +run ok +iter_new types=pointsAndRanges maskBelow=4 +iter_seek_ge k=a +iter_scan +---- +iter_seek_ge: "a"/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 {a-b}/[1.000000000,0] +iter_scan: "a"/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 {a-b}/[1.000000000,0] +iter_scan: "a"/7.000000000,0=/BYTES/a7 {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"/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"/4.000000000,0=/ {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: "l"/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 {l-m}/[1.000000000,0] +iter_scan: "l"/7.000000000,0=/BYTES/l7 {l-m}/[1.000000000,0] +iter_scan: . + +run ok +iter_new types=pointsAndRanges maskBelow=5 +iter_seek_ge k=a +iter_scan +---- +iter_seek_ge: "a"/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 {a-b}/[1.000000000,0] +iter_scan: "a"/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 {a-b}/[1.000000000,0] +iter_scan: "a"/7.000000000,0=/BYTES/a7 {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"/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"/4.000000000,0=/ {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: "l"/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 {l-m}/[1.000000000,0] +iter_scan: "l"/7.000000000,0=/BYTES/l7 {l-m}/[1.000000000,0] +iter_scan: . + +run ok +iter_new types=pointsAndRanges maskBelow=6 +iter_seek_ge k=a +iter_scan +---- +iter_seek_ge: "a"/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 {a-b}/[1.000000000,0] +iter_scan: "a"/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 {a-b}/[1.000000000,0] +iter_scan: "a"/7.000000000,0=/BYTES/a7 {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"/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"/4.000000000,0=/ {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: "l"/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 {l-m}/[1.000000000,0] +iter_scan: "l"/7.000000000,0=/BYTES/l7 {l-m}/[1.000000000,0] +iter_scan: . + # Seek to d, iterate a few times, then reverse direction and iterate beyond seek point. run ok iter_new types=pointsAndRanges