Fix cursor compaction stats over-count for empty static rows

For a static-column table whose partition has no static values, both
compaction paths write an empty static row, but the iterator path only
collects row statistics for non-empty rows
(SortedTableWriter.addStaticRow guards Rows.collectStats with
!row.isEmpty()). The cursor writer counted every written row, inflating
totalRows and totalColumnsSet by one per such partition.

Found by randomized differential testing within its first examples;
the prior hand-written static-row scenario gave every partition static
data and could not produce the trigger.

writeRowEnd now skips row-stats collection when the row is empty by
the iterator's definition: no cells, no liveness timestamp or TTL, and
no row deletion.
This commit is contained in:
Jon Haddad 2026-06-09 20:32:24 -07:00
parent d3f797112a
commit 47e991e1c2
1 changed files with 10 additions and 2 deletions

View File

@ -516,9 +516,17 @@ public class SSTableCursorWriter implements AutoCloseable
long unfilteredEndPosition = getPosition();
/**
* Matching the: {@link org.apache.cassandra.db.rows.Rows#collectStats} along with above cell level metadata updates
* Matching the: {@link org.apache.cassandra.db.rows.Rows#collectStats} along with above cell level metadata updates.
* The iterator path only collects row stats for non-empty rows
* ({@link org.apache.cassandra.io.sstable.format.SortedTableWriter#addStaticRow} guards with
* !row.isEmpty()): an empty static row is still WRITTEN for static-column tables whose
* partition has no static values, but it must not count towards totalRows/totalColumnsSet.
* Empty == no cells, no liveness timestamp/TTL, no row deletion.
*/
metadataCollector.updateColumnSetPerRow(columnsWrittenCount);
boolean rowIsEmpty = columnsWrittenCount == 0
&& (rowFlags & (HAS_TIMESTAMP | HAS_TTL | HAS_DELETION)) == 0;
if (!rowIsEmpty)
metadataCollector.updateColumnSetPerRow(columnsWrittenCount);
if (isStatic)
{