batch
set a 1
set b 2
del c
----

flush
----
0.0:
  000005:[a#1,SET-c#3,DEL]

wait-pending-table-stats
000005
----
num-entries: 3
num-deletions: 1
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 0

compact a-c
----
6:
  000005:[a#1,SET-c#3,DEL]

batch
del-range a c
----

flush
----
0.0:
  000007:[a#4,RANGEDEL-c#inf,RANGEDEL]
6:
  000005:[a#1,SET-c#3,DEL]

wait-pending-table-stats
000007
----
num-entries: 1
num-deletions: 1
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 51

reopen
----

# After re-opening the database, the table stats collector should eventually
# load 000007's stats.

wait-loaded-initial
----
[JOB 2] all initial table stats loaded

wait-pending-table-stats
000007
----
num-entries: 1
num-deletions: 1
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 51

compact a-c
----

# Test a file that is moved by a compaction before its table stats are
# collected. The stats collector should silently skip the first pending file,
# but the second entry from the move compaction should cause the file's stats
# to be loaded.

disable
----

batch
set a 1
set b 2
----

flush
----
0.0:
  000012:[a#5,SET-b#6,SET]

compact a-c
----
6:
  000012:[a#5,SET-b#6,SET]

enable
----

wait-pending-table-stats
000012
----
num-entries: 2
num-deletions: 0
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 0

# Test a file that is deleted by a compaction before its table stats are
# collected. The stats collector should just silently skip the pending file.

disable
----

batch
del-range a c
----

flush
----
0.0:
  000014:[a#7,RANGEDEL-c#inf,RANGEDEL]
6:
  000012:[a#5,SET-b#6,SET]

compact a-c
----

enable
----

wait-pending-table-stats
000014
----
(not found)

# Test range tombstones that need to be truncated to file bounds. The
# grandparent limit and small target file size ensures that our manual
# compaction of L4->L5 will split the range tombstone across several files.

define target-file-sizes=(100, 1)
L4
  a.RANGEDEL.8:f
L5
  b.SET.7:v
L6
  a.SET.1:v
L6
  b.SET.2:v
L6
  c.SET.3:v
L6
  d.SET.4:v
L6
  e.SET.5:v
----
4:
  000004:[a#8,RANGEDEL-f#inf,RANGEDEL]
5:
  000005:[b#7,SET-b#7,SET]
6:
  000006:[a#1,SET-a#1,SET]
  000007:[b#2,SET-b#2,SET]
  000008:[c#3,SET-c#3,SET]
  000009:[d#4,SET-d#4,SET]
  000010:[e#5,SET-e#5,SET]

compact a-b L4
----
5:
  000011:[a#8,RANGEDEL-b#inf,RANGEDEL]
  000012:[b#8,RANGEDEL-c#inf,RANGEDEL]
  000013:[c#8,RANGEDEL-d#inf,RANGEDEL]
  000014:[d#8,RANGEDEL-e#inf,RANGEDEL]
  000015:[e#8,RANGEDEL-f#inf,RANGEDEL]
6:
  000006:[a#1,SET-a#1,SET]
  000007:[b#2,SET-b#2,SET]
  000008:[c#3,SET-c#3,SET]
  000009:[d#4,SET-d#4,SET]
  000010:[e#5,SET-e#5,SET]

wait-pending-table-stats
000011
----
num-entries: 1
num-deletions: 1
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 769

wait-pending-table-stats
000012
----
num-entries: 1
num-deletions: 1
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 769

# A table in L6 with two point keys blocks, each covered by distinct range dels.
# The deletion estimate takes into account the contribution from both deleted
# blocks. Note that the snapshot is required to allow the hint to be computed.
define block-size=1 snapshots=(10)
L6
  e.SET.5:e a.RANGEDEL.15:f m.SET.5:m g.RANGEDEL.15:z
----
6:
  000004:[a#15,RANGEDEL-z#inf,RANGEDEL]

wait-pending-table-stats
000004
----
num-entries: 4
num-deletions: 2
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 68

# Hints that partially overlap tables in lower levels only count blocks that are
# contained within the hint.
#
#  L0 |-|              000004: a.RANGEDEL:b
#  L1        |---|     000005: d.RANGEDEL:f
#  L2  x     x         000006: Two blocks [a, d]
#  L2          x     x 000007: Two blocks [e, h]
#  -------------------
#      a b c d e f g h

define block-size=1
L0
  a.RANGEDEL.2:b
L1
  d.RANGEDEL.1:f
L2
  a.SET.0:a d.SET.0:d
L2
  e.SET.0:e h.SET.0:h
----
0.0:
  000004:[a#2,RANGEDEL-b#inf,RANGEDEL]
1:
  000005:[d#1,RANGEDEL-f#inf,RANGEDEL]
2:
  000006:[a#0,SET-d#0,SET]
  000007:[e#0,SET-h#0,SET]

# Table 000004 deletes the first block in table 000006.
wait-pending-table-stats
000004
----
num-entries: 1
num-deletions: 1
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 33

# Table 000005 deletes the second block in table 000006 (containing 'd') and the
# first block in table 000007 (containing 'e').
wait-pending-table-stats
000005
----
num-entries: 1
num-deletions: 1
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 66

# Test the interaction between point and range key deletions.

define
----

# Start with a table that contains point and range keys, but no range dels or
# range key dels.
batch
set a a
range-key-set a b @1 foo
range-key-unset a b @2
----

flush
----
0.0:
  000005:[a#3,RANGEKEYUNSET-b#inf,RANGEKEYSET]

# Add a table that contains only point keys, to the right of the existing table.
batch
set c c
----

flush
----
0.0:
  000005:[a#3,RANGEKEYUNSET-b#inf,RANGEKEYSET]
  000007:[c#4,SET-c#4,SET]

compact a-c
----
6:
  000008:[a#2,RANGEKEYSET-b#inf,RANGEKEYSET]
  000009:[c#0,SET-c#0,SET]

# Add a table that contains a RANGEKEYDEL covering the first table in L6.
batch
range-key-del a b
----

flush
----
0.0:
  000011:[a#5,RANGEKEYDEL-b#inf,RANGEKEYDEL]
6:
  000008:[a#2,RANGEKEYSET-b#inf,RANGEKEYSET]
  000009:[c#0,SET-c#0,SET]

# Add one more table containing a RANGEDEL.
batch
del-range a c
----

flush
----
0.1:
  000013:[a#6,RANGEDEL-c#inf,RANGEDEL]
0.0:
  000011:[a#5,RANGEKEYDEL-b#inf,RANGEKEYDEL]
6:
  000008:[a#2,RANGEKEYSET-b#inf,RANGEKEYSET]
  000009:[c#0,SET-c#0,SET]

# Compute stats on the table containing range key del. It should not show an
# estimate for deleted point keys as there are no tables below it that contain
# only range keys.
wait-pending-table-stats
000011
----
num-entries: 0
num-deletions: 0
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 0

# Compute stats on the table containing the range del. It should show an
# estimate for deleted point keys, as a table below it (000008) contains point
# keys. Note that even though table 000008 contains range keys, the range del
# estimates are non-zero, as this number is agnostic of range keys.
wait-pending-table-stats
000013
----
num-entries: 1
num-deletions: 1
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 915

# Drop a range del and a range key del over the entire keyspace. This table can
# delete everything underneath it.
ingest ext1
del-range a z
range-key-del a z
----
0.2:
  000014:[a#7,RANGEKEYDEL-z#inf,RANGEDEL]
0.1:
  000013:[a#6,RANGEDEL-c#inf,RANGEDEL]
0.0:
  000011:[a#5,RANGEKEYDEL-b#inf,RANGEKEYDEL]
6:
  000008:[a#2,RANGEKEYSET-b#inf,RANGEKEYSET]
  000009:[c#0,SET-c#0,SET]

compact a-z
----

# A hint for exclusively range key deletions that covers a table with point keys
# should not contain an estimate for point keys.

define
----

# A table with point keys.
batch
set b b
----

flush
----
0.0:
  000005:[b#1,SET-b#1,SET]

# A table with a mixture of point and range keys.
batch
set c c
range-key-set d d @1 foo
----

flush
----
0.0:
  000005:[b#1,SET-b#1,SET]
  000007:[c#2,SET-c#2,SET]

compact a-z
----
6:
  000008:[b#0,SET-b#0,SET]
  000009:[c#0,SET-c#0,SET]

# The table with the range key del, that spans the previous two tables.
batch
range-key-del a z
----

flush
----
0.0:
  000011:[a#4,RANGEKEYDEL-z#inf,RANGEKEYDEL]
6:
  000008:[b#0,SET-b#0,SET]
  000009:[c#0,SET-c#0,SET]

# The hint on table 000011 does estimates zero size for range deleted point
# keys.
wait-pending-table-stats
000011
----
num-entries: 0
num-deletions: 0
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 0

# A hint from a range del that covers a table with only range keys should not
# contain an estimate for the range keys.

define
L4
  a.RANGEDEL.4:c
L5
  a.RANGEDEL.2:e
  b.SET.3:b
L6
  rangekey:c-d:{(#1,RANGEKEYSET,@1,foo)}
----
4:
  000004:[a#4,RANGEDEL-c#inf,RANGEDEL]
5:
  000005:[a#2,RANGEDEL-e#inf,RANGEDEL]
6:
  000006:[c#1,RANGEKEYSET-d#inf,RANGEKEYSET]

# The table in L5 should not contain an estimate for the table below it, which
# contains only range keys.
wait-pending-table-stats
000005
----
num-entries: 2
num-deletions: 1
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 0

# The table in L4 can delete the table in L5, which contains point keys. The
# estimate is only partial, as the range del does not fully overlap the table.
wait-pending-table-stats
000004
----
num-entries: 1
num-deletions: 1
num-range-key-sets: 0
point-deletions-bytes-estimate: 0
range-deletions-bytes-estimate: 26
