You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by "Alex Petrov (Jira)" <ji...@apache.org> on 2026/03/25 16:13:00 UTC

[jira] [Created] (CASSANDRA-21255) Range selects return 0 rows after compaction purges an open-ended range tombstone;

Alex Petrov created CASSANDRA-21255:
---------------------------------------

             Summary: Range selects return 0 rows after compaction purges an open-ended range tombstone;
                 Key: CASSANDRA-21255
                 URL: https://issues.apache.org/jira/browse/CASSANDRA-21255
             Project: Apache Cassandra
          Issue Type: Bug
            Reporter: Alex Petrov
            Assignee: Alex Petrov


Minimal reproduction of a bug where range selects return 0 rows after compaction purges an open-ended range tombstone.

When column_index_size is small (1 KiB) and the partition spans multiple index blocks, an open-ended range delete whose lower bound falls in the last index block causes range selects that seek into later blocks to return empty results after compaction, even though the data is present (partition scans return correct results).
 
Reproduce:
{code}
   1. column_index_size_in_kb = 1
   2. Insert 30 rows with ~100-byte values (spans ~3 index blocks)
   3. DELETE WHERE ck >= 'r026' (open-ended, in last block)
   4. Flush both, major-compact (purges the tombstone with gc_grace=0)
   5. SELECT WHERE ck >= 'r023' AND ck <= 'r029'  →  returns 0 (expected 3)
{code}

{code}
public class RawRangeTombstoneReproTest extends CQLTester
{
    private int savedColumnIndexSizeInKiB;
    private int savedColumnIndexCacheSizeInKiB;

    @Before
    public void saveConfig()
    {
        savedColumnIndexSizeInKiB = DatabaseDescriptor.getColumnIndexSizeInKiB();
        savedColumnIndexCacheSizeInKiB = DatabaseDescriptor.getColumnIndexCacheSizeInKiB();
        DatabaseDescriptor.setColumnIndexSizeInKiB(1);
        DatabaseDescriptor.setColumnIndexCacheSize(1);
    }

    @After
    public void restoreConfig()
    {
        DatabaseDescriptor.setColumnIndexSizeInKiB(savedColumnIndexSizeInKiB);
        DatabaseDescriptor.setColumnIndexCacheSize(savedColumnIndexCacheSizeInKiB);
    }

    private ColumnFamilyStore getCfs()
    {
        return Keyspace.open(KEYSPACE).getColumnFamilyStore(currentTable());
    }

    @Test
    public void testRangeSelectReturnsEmptyAfterCompaction()
    {
        createTable("CREATE TABLE %s (pk text, ck text, v1 text, PRIMARY KEY (pk, ck))" +
                    " WITH gc_grace_seconds = 0" +
                    " AND compression = {'enabled': 'false'}" +
                    " AND compaction = {'class': 'SizeTieredCompactionStrategy', 'enabled': false}");

        // 30 rows with ~100-byte values → ~3 index blocks at 1 KiB each
        String pad = "x".repeat(80);
        for (int i = 0; i < 30; i++)
            execute("INSERT INTO %s (pk, ck, v1) VALUES (?, ?, ?)",
                    "p", String.format("r%03d", i), pad + i);

        getCfs().forceBlockingFlush(ColumnFamilyStore.FlushReason.UNIT_TESTS);

        // Open-ended delete: removes rows 26-29 (last block)
        execute("DELETE FROM %s WHERE pk = ? AND ck >= ?", "p", "r026");

        getCfs().forceBlockingFlush(ColumnFamilyStore.FlushReason.UNIT_TESTS);
        getCfs().forceMajorCompaction();

        // Partition scan sees all 26 surviving rows — data is present
        UntypedResultSet all = execute("SELECT * FROM %s WHERE pk = ?", "p");
        assertEquals("partition scan should see 26 rows", 26, all.size());

        // BUG: range select near end returns 0 instead of 3
        UntypedResultSet range = execute(
            "SELECT * FROM %s WHERE pk = ? AND ck >= ? AND ck <= ?",
            "p", "r023", "r029");
        assertEquals("range select [r023,r029] should return 3 rows (23,24,25)",
                     3, range.size());
    }
}
{code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org