Merge branch 'cassandra-5.0' into trunk

* cassandra-5.0:
  Ensure RowFilter#isMutableIntersection() properly evaluates numeric ranges on a single column
This commit is contained in:
Caleb Rackliffe 2025-04-27 09:57:07 -05:00
commit 5b0956be4b
3 changed files with 48 additions and 7 deletions

View File

@ -182,6 +182,7 @@
* Add the ability to disable bulk loading of SSTables (CASSANDRA-18781)
* Clean up obsolete functions and simplify cql_version handling in cqlsh (CASSANDRA-18787)
Merged from 5.0:
* Ensure RowFilter#isMutableIntersection() properly evaluates numeric ranges on a single column (CASSANDRA-20566)
* SAI marks an index as non-empty when a partial partition/row modifications is flushed due to repair (CASSANDRA-20567)
* SAI fails queries when multiple columns exist and a non-indexed column is a composite with a map (CASSANDRA-19891)
* Avoid purging deletions in RowFilter when reconciliation is required (CASSANDRA-20541)

View File

@ -21,8 +21,10 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
@ -172,15 +174,21 @@ public class RowFilter implements Iterable<RowFilter.Expression>
*/
public boolean isMutableIntersection()
{
int count = 0;
Set<ColumnMetadata> columns = null;
for (Expression e : expressions)
{
if (e.column.isStatic() && expressions.size() > 1)
return true;
if (!e.column.isPrimaryKeyColumn())
if (++count > 1)
{
if (columns == null)
columns = new HashSet<>(expressions.size());
columns.add(e.column);
if (columns.size() > 1)
return true;
}
}
return false;
}

View File

@ -20,9 +20,10 @@ package org.apache.cassandra.db.filter;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Assert;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
import org.apache.cassandra.cql3.ColumnIdentifier;
@ -33,6 +34,7 @@ import org.apache.cassandra.db.DeletionTime;
import org.apache.cassandra.db.LivenessInfo;
import org.apache.cassandra.db.RegularAndStaticColumns;
import org.apache.cassandra.db.marshal.Int32Type;
import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.db.partitions.SingletonUnfilteredPartitionIterator;
import org.apache.cassandra.db.partitions.UnfilteredPartitionIterator;
import org.apache.cassandra.db.rows.BTreeRow;
@ -45,8 +47,12 @@ import org.apache.cassandra.db.rows.Unfiltered;
import org.apache.cassandra.db.rows.UnfilteredRowIterator;
import org.apache.cassandra.schema.ColumnMetadata;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.btree.BTree;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class RowFilterTest
{
@ -89,8 +95,8 @@ public class RowFilterTest
closed.set(true);
}
}), 1);
Assert.assertFalse(iter.hasNext());
Assert.assertTrue(closed.get());
assertFalse(iter.hasNext());
assertTrue(closed.get());
filter = RowFilter.none().withNewExpressions(new ArrayList<>());
filter.add(r, Operator.NEQ, one);
@ -123,9 +129,35 @@ public class RowFilterTest
closed.set(true);
}
}), 1);
Assert.assertFalse(iter.hasNext());
Assert.assertTrue(closed.get());
assertFalse(iter.hasNext());
assertTrue(closed.get());
}
@Test
public void testMutableIntersections()
{
TableMetadata metadata = TableMetadata.builder("testks", "testcf")
.addPartitionKeyColumn("pk", Int32Type.instance)
.addRegularColumn("r", Int32Type.instance)
.addRegularColumn("t", UTF8Type.instance)
.offline()
.build();
RowFilter filter = RowFilter.none().withNewExpressions(new ArrayList<>());
assertFalse(filter.isMutableIntersection());
ColumnMetadata r = metadata.getColumn(new ColumnIdentifier("r", true));
RowFilter.Expression gt = new RowFilter.SimpleExpression(r, Operator.GT, ByteBufferUtil.EMPTY_BYTE_BUFFER);
filter = filter.withNewExpressions(Collections.singletonList(gt));
assertFalse(filter.isMutableIntersection());
RowFilter.Expression lt = new RowFilter.SimpleExpression(r, Operator.LT, ByteBufferUtil.EMPTY_BYTE_BUFFER);
filter = filter.withNewExpressions(ImmutableList.of(gt, lt));
assertFalse(filter.isMutableIntersection());
ColumnMetadata t = metadata.getColumn(new ColumnIdentifier("t", true));
RowFilter.Expression eq = new RowFilter.SimpleExpression(t, Operator.EQ, ByteBufferUtil.EMPTY_BYTE_BUFFER);
filter = filter.withNewExpressions(ImmutableList.of(gt, lt, eq));
assertTrue(filter.isMutableIntersection());
}
}