# Test a lazy-combined iteration edge case. Consider the LSM:
#
#   L5:  000003:[bar.DEL.3, foo.RANGEKEYSET.4]
#   L6:  000001:[bar.SET.1] 000002:[bax.RANGEKEYSET.2]
#
# A call to First() seeks the levels to files L5.000003 and L6.000001.
# The L5 levelIter observes that L5.000003 contains the range key with
# start key `foo`, and triggers a switch to combined iteration, setting
# `combinedIterState.key` = `foo`. While switching to combined iteration, the
# iterator must recognize that `foo` > `bar`, and there may yet exist range keys
# that begin before `foo` (in this case `bax`).

reset
----

batch commit
set bar bar
----
committed 1 keys

flush
----

batch commit
range-key-set bax zoo @1 foo
----
committed 1 keys

flush
----

batch commit
del bar
range-key-set foo zoo @2 bar
----
committed 2 keys

flush
----

lsm
----
0.1:
  000009:[bar#12,DEL-zoo#inf,RANGEKEYSET]
0.0:
  000005:[bar#10,SET-bar#10,SET]
  000007:[bax#11,RANGEKEYSET-zoo#inf,RANGEKEYSET]

# Assert that First correctly finds [bax,zoo), despite the discovery of
# [foo,zoo) triggering the switch to combined iteration.

combined-iter
first
next
----
bax: (., [bax-foo) @1=foo UPDATED)
foo: (., [foo-zoo) @2=bar, @1=foo UPDATED)

# Test seeking into the middle of a range key during lazy-combined iteration.
# The iterator should surface Key() = the seek key.

combined-iter
seek-ge bop
----
bop: (., [bax-foo) @1=foo UPDATED)

combined-iter
last
----
foo: (., [foo-zoo) @2=bar, @1=foo UPDATED)

# Test a lazy combined iterator that must next/prev through fileMetdata when
# skipping through a RANGEDEL.
#
# L5
#     b-----------------------y RANGEDEL
# L6
#  [a]   [[d,e)@1]  [[l,m)@1]   [z]
#
# A SeekGE(k) must surface [l,m)@1 and a SeekLT(k) must surface [d,e)@1.

reset
----

batch commit
set a a
----
committed 1 keys

flush
----

batch commit
set z z
----
committed 1 keys

flush
----

batch commit
range-key-set d e @1 foo
----
committed 1 keys

flush
----

batch commit
range-key-set l m @1 foo
----
committed 1 keys

flush
----

batch commit
del-range b y
----
committed 1 keys

flush
----

lsm
----
0.1:
  000013:[b#14,RANGEDEL-y#inf,RANGEDEL]
0.0:
  000005:[a#10,SET-a#10,SET]
  000009:[d#12,RANGEKEYSET-e#inf,RANGEKEYSET]
  000011:[l#13,RANGEKEYSET-m#inf,RANGEKEYSET]
  000007:[z#11,SET-z#11,SET]

combined-iter
seek-ge k
next
----
l: (., [l-m) @1=foo UPDATED)
z: (z, . UPDATED)

combined-iter
seek-lt k
prev
----
d: (., [d-e) @1=foo UPDATED)
a: (a, . UPDATED)


reset
----

batch commit
set a a
set b b
set c c
set e e
range-key-del a f
range-key-unset a f @5
----
committed 6 keys

flush
----

wait-table-stats
----

# The lazy iterator shouldn't switch to combined iteration when it encounters a
# file that is known to only contain RANGEKEYDELs and RANGEKEYUNSETs.

combined-iter
is-using-combined
seek-ge a
seek-ge b
is-using-combined
----
using lazy iterator
a: (a, .)
b: (b, .)
using lazy iterator

# Write a range key to the memtable. The combined iterator should be forced to
# use non-lazy iteration.

batch commit
range-key-set m z @5 foo
set s s
----
committed 2 keys

combined-iter
is-using-combined
seek-ge a
is-using-combined
seek-ge n
is-using-combined
----
using combined (non-lazy) iterator
a: (a, .)
using combined (non-lazy) iterator
n: (., [m-z) @5=foo UPDATED)
using combined (non-lazy) iterator

flush
----

# Now that the range key is flushed, a switch to combined iteration should only
# happen once the sstable containing the set is encountered.

combined-iter
is-using-combined
seek-ge a
is-using-combined
seek-ge n
is-using-combined
----
using lazy iterator
a: (a, .)
using lazy iterator
n: (., [m-z) @5=foo UPDATED)
using combined (non-lazy) iterator

# Regression tests for #2210 metamorphic test failure.
#
# Lazy-combined iteration depends on individual point level iterators triggering
# a switch to combined iteration when they observe a file containing relevant
# range keys. Previously, this switch did not happen if the observed range
# keys all lied outside the current iteration prefix.
#
# This made it possible for a level to become positioned beyond the file
# containing range keys, without ever triggering the switch to combined
# iteration. A subsequent seek that made use of the TrySeekUsingNext
# optimization would never observe the file containing range keys, and omit the
# range keys.

define
L6
  bax.DEL.9:
L6
  rangekey:c-d:{(#0,RANGEKEYSET,@1,foo)}
L6
  d@2.SET.2:v
----
6:
  000004:[bax#9,DEL-bax#9,DEL]
  000005:[c#0,RANGEKEYSET-d#inf,RANGEKEYSET]
  000006:[d@2#2,SET-d@2#2,SET]

combined-iter
seek-prefix-ge bax
seek-prefix-ge cat
----
.
cat: (., [cat-"cat\x00") @1=foo UPDATED)

# Another regression test for the #2210 metamorphic test failure, this one using
# a MERGE key to force the Iterator to step the internal iterator beyond the
# range key file.

define
L6
  bax.MERGE.9:v
L6
  rangekey:c-d:{(#0,RANGEKEYSET,@1,foo)}
L6
  d@2.SET.2:v
----
6:
  000004:[bax#9,MERGE-bax#9,MERGE]
  000005:[c#0,RANGEKEYSET-d#inf,RANGEKEYSET]
  000006:[d@2#2,SET-d@2#2,SET]

combined-iter
seek-prefix-ge bax
seek-prefix-ge cat
----
bax: (v, .)
cat: (., [cat-"cat\x00") @1=foo UPDATED)
