db-07 Observation

The canonical scenario

We build two SSTables (call them newer.sst and older.sst) and compact them in the order [newer, older].

newer.sst — produced from this MemTable scenario

memtable new
memtable bulk 50            # key0..key49 -> val0..val49
memtable put  "key10" "NEW-10"
memtable del  "key5"

So newer.sst contains 50 distinct keys, of which key10 has value "NEW-10", key5 is a tombstone, and the other 48 are val<i>.

older.sst — produced from this MemTable scenario

memtable new
memtable bulk 100           # key0..key99 -> val0..val99
memtable put  "key50" "OLD-50"

So older.sst contains 100 distinct keys, of which key50 is "OLD-50" and the others are val<i>.

Expected merged output

For every key the table picks the first input that contains it:

Key range / specific keyWinnerValue
key0..key4newerval0..val4
key5newerTombstone
key6..key9newerval6..val9
key10newer"NEW-10"
key11..key49newerval11..val49
key50older"OLD-50"
key51..key99olderval51..val99

Total distinct keys: 100. Tombstones: 1 (key5). Values: 99.

"What broken looks like"

BugSymptom
Tiebreaker swapped (older wins)key10 → "val10" instead of "NEW-10"; key5 → "val5" instead of tombstone.
Forget to drain duplicatesSstWriter::add returns Unsorted error (or "keys not strictly ascending").
Byte-vs-string comparisonOutput sha256 differs across languages on ASCII-only input only if a sort breaks.
Tombstone dropped when drop_tombstones=falseOutput has 99 keys instead of 100; key5 missing.
Tombstone kept when drop_tombstones=true at botOutput has 100 keys instead of 99; key5 still present as tombstone.

With drop_tombstones=true

Same inputs, run as bottom-level compaction:

  • key5 disappears entirely (newer's only entry for key5 was a tombstone).
  • 99 keys total, all values.

Hex of the absolute simplest compaction

Compacting [A, B] where A = [("k", T)] and B = [("k", V, "v")]:

  • drop_tombstones=false: output is an SSTable with one entry ("k", T). File size = 4 (block hdr) + 4+4+1 (entry hdr) + 1 (key) + 0 (value) + 4 (index count) + 4+8+8+1 (one index entry) + 32 (footer) = 79 bytes. This is the same as sstable build of a MemTable containing only ("k", T).
  • drop_tombstones=true: output is the empty SSTable, exactly 36 bytes.

Cross-language sha256 must match for both cases.