build
a.SET.1:a
----
point:    [a#1,SET-a#1,SET]
seqnums:  [1-1]

scan
----
a#1,SET:a

scan-range-del
----

scan-range-key
----

build props=(deletions,deleted)
a.SET.1:a
b.DEL.2:
c.MERGE.3:c
d.RANGEDEL.4:e
f.SET.5:f
g.DEL.6:
h.MERGE.7:h
i.RANGEDEL.8:j
Span: j-k:{(#9,RANGEKEYDEL)}
Span: k-l:{(#10,RANGEKEYUNSET,@5)}
Span: l-m:{(#11,RANGEKEYSET,@10,foo)}
----
point:    [a#1,SET-h#7,MERGE]
rangedel: [d#4,RANGEDEL-j#inf,RANGEDEL]
rangekey: [j#9,RANGEKEYDEL-m#inf,RANGEKEYSET]
seqnums:  [1-11]
props "deletions":
  rocksdb.num.range-deletions: 2
props "deleted":
  rocksdb.deleted.keys: 4


build props=(deletions,deleted)
a.SET.1:a
b.DEL.2:
c.MERGE.3:c
d.SINGLEDEL.4:
e.SINGLEDEL.5:
f.SET.6:f
g.DEL.7:
h.SINGLEDEL.8:
Span: j-k:{(#9,RANGEKEYDEL)}
Span: k-l:{(#10,RANGEKEYUNSET,@5)}
Span: l-m:{(#11,RANGEKEYSET,@10,foo)}
----
point:    [a#1,SET-h#8,SINGLEDEL]
rangekey: [j#9,RANGEKEYDEL-m#inf,RANGEKEYSET]
seqnums:  [1-11]
props "deletions":
props "deleted":
  rocksdb.deleted.keys: 5


build
a.SET.1:a
b.DEL.2:
c.MERGE.3:c
d.RANGEDEL.4:e
f.SET.5:f
g.DEL.6:
h.MERGE.7:h
i.RANGEDEL.8:j
----
point:    [a#1,SET-h#7,MERGE]
rangedel: [d#4,RANGEDEL-j#inf,RANGEDEL]
seqnums:  [1-8]

scan
----
a#1,SET:a
b#2,DEL:
c#3,MERGE:c
f#5,SET:f
g#6,DEL:
h#7,MERGE:h

scan-range-del
----
d-e:{(#4,RANGEDEL)}
i-j:{(#8,RANGEDEL)}

# 3: a-----------m
# 2:      f------------s
# 1:          j---------------z

build
Span: a-f:{(#3,RANGEDEL)}
Span: f-j:{(#3,RANGEDEL) (#2,RANGEDEL)}
Span: j-m:{(#3,RANGEDEL) (#2,RANGEDEL) (#1,RANGEDEL)}
Span: m-s:{(#2,RANGEDEL) (#1,RANGEDEL)}
Span: s-z:{(#1,RANGEDEL)}
----
rangedel: [a#3,RANGEDEL-z#inf,RANGEDEL]
seqnums:  [1-3]

scan
----

scan-range-del
----
a-f:{(#3,RANGEDEL)}
f-j:{(#3,RANGEDEL) (#2,RANGEDEL)}
j-m:{(#3,RANGEDEL) (#2,RANGEDEL) (#1,RANGEDEL)}
m-s:{(#2,RANGEDEL) (#1,RANGEDEL)}
s-z:{(#1,RANGEDEL)}

scan-range-key
----

# The range tombstone upper bound is exclusive, so a point operation
# on that same key will be the actual boundary.

build
a.RANGEDEL.3:b
b.SET.4:c
----
point:    [b#4,SET-b#4,SET]
rangedel: [a#3,RANGEDEL-b#inf,RANGEDEL]
seqnums:  [3-4]

build
a.RANGEDEL.3:b
b.SET.2:c
----
point:    [b#2,SET-b#2,SET]
rangedel: [a#3,RANGEDEL-b#inf,RANGEDEL]
seqnums:  [2-3]

build
a.RANGEDEL.3:c
b.SET.2:c
----
point:    [b#2,SET-b#2,SET]
rangedel: [a#3,RANGEDEL-c#inf,RANGEDEL]
seqnums:  [2-3]

# Keys must be added in order.

build
a.SET.1:b
a.SET.2:c
----
failed to write a#2,SET = c: pebble: keys must be added in strictly increasing order: a#1,SET, a#2,SET

build
b.SET.1:a
a.SET.2:b
----
failed to write a#2,SET = b: pebble: keys must be added in strictly increasing order: b#1,SET, a#2,SET

build
b.RANGEDEL.1:c
a.RANGEDEL.2:b
----
failed to write a#2,RANGEDEL = b: pebble: keys must be added in order: b#1,RANGEDEL, a#2,RANGEDEL

build-raw
.RANGEDEL.1:b
----
rangedel: [#1,RANGEDEL-b#inf,RANGEDEL]
seqnums:  [1-1]

build-raw
a.RANGEDEL.1:c
a.RANGEDEL.2:c
----
pebble: keys must be added in strictly increasing order: a#1,RANGEDEL, a#2,RANGEDEL

build-raw
a.RANGEDEL.1:c
b.RANGEDEL.2:d
----
pebble: overlapping tombstones must be fragmented: a-c:{(#1,RANGEDEL)} vs b-d:{(#2,RANGEDEL)}

build-raw
a.RANGEDEL.2:c
a.RANGEDEL.1:d
----
pebble: overlapping tombstones must be fragmented: a-c:{(#2,RANGEDEL)} vs a-d:{(#1,RANGEDEL)}

build-raw
a.RANGEDEL.1:c
c.RANGEDEL.2:d
----
rangedel: [a#1,RANGEDEL-d#inf,RANGEDEL]
seqnums:  [1-2]

build
Span: a-b:{(#2,RANGEKEYSET,@10,foo) (#1,RANGEKEYSET,@10,foo)}
----
rangekey: [a#2,RANGEKEYSET-b#inf,RANGEKEYSET]
seqnums:  [1-2]

build-raw
Span: b-c:{(#2,RANGEKEYSET,@10,foo)}
Span: a-b:{(#1,RANGEKEYSET,@10,foo)}
----
pebble: range keys starts must be added in increasing order: b#2,RANGEKEYSET, a#1,RANGEKEYSET

build-raw
Span: a-c:{(#1,RANGEKEYSET,@10,foo)}
Span: c-d:{(#2,RANGEKEYSET,@10,foo)}
----
rangekey: [a#1,RANGEKEYSET-d#inf,RANGEKEYSET]
seqnums:  [1-2]

# Range keys may have perfectly aligned spans (including sequence numbers),
# though the key kinds must be ordered (descending).

build-raw
Span: a-b:{(#1,RANGEKEYSET,@10,foo) (#1,RANGEKEYUNSET,@t10) (#1,RANGEKEYDEL)}
----
rangekey: [a#1,RANGEKEYSET-b#inf,RANGEKEYDEL]
seqnums:  [1-1]

# Setting a very small index-block-size results in a two-level index.

build block-size=1 index-block-size=1
a.SET.1:a
b.SET.1:b
c.SET.1:c
----
point:    [a#1,SET-c#1,SET]
seqnums:  [1-1]

layout
----
sstable
 ├── data  offset: 0  length: 21
 ├── data  offset: 26  length: 21
 ├── data  offset: 52  length: 21
 ├── index  offset: 78  length: 22
 ├── index  offset: 105  length: 22
 ├── index  offset: 132  length: 22
 ├── top-index  offset: 159  length: 48
 ├── properties  offset: 212  length: 451
 ├── meta-index  offset: 668  length: 33
 └── footer  offset: 706  length: 53

scan
----
a#1,SET:a
b#1,SET:b
c#1,SET:c

# Enabling leveldb format disables the creation of a two-level index
# (the input data here mirrors the test case above).

build table-format=LevelDB block-size=1 index-block-size=1
a.SET.1:a
b.SET.1:b
c.SET.1:c
----
point:    [a#1,SET-c#1,SET]
seqnums:  [1-1]

layout
----
sstable
 ├── data  offset: 0  length: 21
 ├── data  offset: 26  length: 21
 ├── data  offset: 52  length: 21
 ├── index  offset: 78  length: 45
 ├── properties  offset: 128  length: 549
 ├── meta-index  offset: 682  length: 33
 └── leveldb-footer  offset: 720  length: 48

# Range keys, if present, are shown in the layout.

build
Span: a-b:{(#3,RANGEKEYSET,@3,foo)}
Span: b-c:{(#2,RANGEKEYSET,@2,bar)}
Span: c-d:{(#1,RANGEKEYSET,@1,baz)}
----
rangekey: [a#3,RANGEKEYSET-d#inf,RANGEKEYSET]
seqnums:  [1-3]

layout
----
sstable
 ├── data  offset: 0  length: 8
 ├── index  offset: 13  length: 21
 ├── range-key  offset: 39  length: 79
 ├── properties  offset: 123  length: 499
 ├── meta-index  offset: 627  length: 57
 └── footer  offset: 689  length: 53
