This is an automated email from the ASF dual-hosted git repository.

aweisberg pushed a commit to branch cep-15-accord
in repository https://gitbox.apache.org/repos/asf/cassandra.git

commit a59536f105fea338d474299cd19bfbc6bb348600
Author: Caleb Rackliffe <[email protected]>
AuthorDate: Fri Sep 27 14:07:24 2024 -0500

    Use SinglePartitionReadCommand for index queries that use strict filtering
    
    patch by Caleb Rackliffe; reviewed by Ariel Weisberg for CASSANDRA-19968
---
 .../cassandra/cql3/statements/SelectStatement.java | 31 +++++++-----
 .../cassandra/db/PartitionRangeReadCommand.java    |  9 +---
 .../cassandra/db/PartitionRangeReadQuery.java      |  2 -
 src/java/org/apache/cassandra/db/ReadCommand.java  | 13 ++++-
 src/java/org/apache/cassandra/db/ReadQuery.java    |  9 +++-
 .../cassandra/db/SinglePartitionReadCommand.java   | 19 ++++---
 .../cassandra/db/SinglePartitionReadQuery.java     |  7 +++
 .../index/internal/CassandraIndexSearcher.java     | 59 ++++++++++++++++------
 .../cassandra/index/sai/plan/QueryController.java  |  8 +--
 .../cassandra/index/sasi/plan/QueryController.java |  6 +--
 .../index/sasi/plan/SASIIndexSearcher.java         |  2 +-
 .../org/apache/cassandra/utils/btree/BTreeSet.java |  8 ++-
 .../db/AbstractReadQueryToCQLStringTest.java       | 19 +++----
 .../db/ReadCommandVerbHandlerOutOfRangeTest.java   |  3 +-
 .../cassandra/db/ReadCommandVerbHandlerTest.java   |  3 +-
 .../org/apache/cassandra/db/ReadResponseTest.java  |  3 +-
 .../cassandra/service/reads/ReadExecutorTest.java  |  2 +-
 .../reads/repair/RepairedDataVerifierTest.java     |  3 +-
 18 files changed, 131 insertions(+), 75 deletions(-)

diff --git a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
index fea826d0ac..66a4797637 100644
--- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
@@ -453,19 +453,21 @@ public class SelectStatement implements 
CQLStatement.SingleKeyspaceCqlStatement,
                               long nowInSec,
                               DataLimits limit)
     {
-        boolean isPartitionRangeQuery = isPartitionRangeQuery();
+        RowFilter rowFilter = getRowFilter(options, state);
 
-        if (isPartitionRangeQuery)
+        if (restrictions.isKeyRange())
         {
-            if (restrictions.isKeyRange() && 
restrictions.usesSecondaryIndexing() && 
!SchemaConstants.isLocalSystemKeyspace(table.keyspace))
+            if (restrictions.usesSecondaryIndexing() && 
!SchemaConstants.isLocalSystemKeyspace(table.keyspace))
                 
Guardrails.nonPartitionRestrictedIndexQueryEnabled.ensureEnabled(state);
 
-            return getRangeCommand(options, state, columnFilter, limit, 
nowInSec);
+            return getRangeCommand(options, state, columnFilter, rowFilter, 
limit, nowInSec);
         }
 
-        return getSliceCommands(options, state, columnFilter, limit, nowInSec);
-    }
+        if (restrictions.usesSecondaryIndexing() && !rowFilter.isStrict())
+            return getRangeCommand(options, state, columnFilter, rowFilter, 
limit, nowInSec);
 
+        return getSliceCommands(options, state, columnFilter, rowFilter, 
limit, nowInSec);
+    }
     private ResultMessage.Rows execute(ReadQuery query,
                                        QueryOptions options,
                                        ClientState state,
@@ -768,7 +770,7 @@ public class SelectStatement implements 
CQLStatement.SingleKeyspaceCqlStatement,
     }
 
     private ReadQuery getSliceCommands(QueryOptions options, ClientState 
state, ColumnFilter columnFilter,
-                                       DataLimits limit, long nowInSec)
+                                       RowFilter rowFilter, DataLimits limit, 
long nowInSec)
     {
         Collection<ByteBuffer> keys = restrictions.getPartitionKeys(options, 
state);
         if (keys.isEmpty())
@@ -783,8 +785,6 @@ public class SelectStatement implements 
CQLStatement.SingleKeyspaceCqlStatement,
         if (filter == null || filter.isEmpty(table.comparator))
             return ReadQuery.empty(table);
 
-        RowFilter rowFilter = getRowFilter(options, state);
-
         List<DecoratedKey> decoratedKeys = new ArrayList<>(keys.size());
         for (ByteBuffer key : keys)
         {
@@ -792,7 +792,13 @@ public class SelectStatement implements 
CQLStatement.SingleKeyspaceCqlStatement,
             
decoratedKeys.add(table.partitioner.decorateKey(ByteBufferUtil.clone(key)));
         }
 
-        return SinglePartitionReadQuery.createGroup(table, nowInSec, 
columnFilter, rowFilter, limit, decoratedKeys, filter);
+        SinglePartitionReadQuery.Group<? extends SinglePartitionReadQuery> 
group =
+            SinglePartitionReadQuery.createGroup(table, nowInSec, 
columnFilter, rowFilter, limit, decoratedKeys, filter);
+
+        // If there's a secondary index that the commands can use, have it 
validate the request parameters.
+        group.maybeValidateIndex();
+
+        return group;
     }
 
     /**
@@ -840,14 +846,13 @@ public class SelectStatement implements 
CQLStatement.SingleKeyspaceCqlStatement,
         return 
getRowFilter(QueryOptions.forInternalCalls(Collections.emptyList()), 
ClientState.forInternalCalls());
     }
 
-    private ReadQuery getRangeCommand(QueryOptions options, ClientState state, 
ColumnFilter columnFilter, DataLimits limit, long nowInSec)
+    private ReadQuery getRangeCommand(QueryOptions options, ClientState state, 
ColumnFilter columnFilter,
+                                      RowFilter rowFilter, DataLimits limit, 
long nowInSec)
     {
         ClusteringIndexFilter clusteringIndexFilter = 
makeClusteringIndexFilter(options, state, columnFilter);
         if (clusteringIndexFilter == null)
             return ReadQuery.empty(table);
 
-        RowFilter rowFilter = getRowFilter(options, state);
-
         // The LIMIT provided by the user is the number of CQL row he wants 
returned.
         // We want to have getRangeSlice to count the number of columns, not 
the number of keys.
         AbstractBounds<PartitionPosition> keyBounds = 
restrictions.getPartitionKeyBounds(options);
diff --git a/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java 
b/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java
index fccdc9e447..fb2888e13a 100644
--- a/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java
+++ b/src/java/org/apache/cassandra/db/PartitionRangeReadCommand.java
@@ -64,7 +64,6 @@ public class PartitionRangeReadCommand extends ReadCommand 
implements PartitionR
 {
     protected static final SelectionDeserializer selectionDeserializer = new 
Deserializer();
 
-    protected final DataRange dataRange;
     protected final Slices requestedSlices;
 
     @VisibleForTesting
@@ -82,8 +81,7 @@ public class PartitionRangeReadCommand extends ReadCommand 
implements PartitionR
                                         Index.QueryPlan indexQueryPlan,
                                         boolean trackWarnings)
     {
-        super(serializedAtEpoch, Kind.PARTITION_RANGE, isDigest, 
digestVersion, acceptsTransient, allowOutOfRangeReads, metadata, nowInSec, 
columnFilter, rowFilter, limits, indexQueryPlan, trackWarnings);
-        this.dataRange = dataRange;
+        super(serializedAtEpoch, Kind.PARTITION_RANGE, isDigest, 
digestVersion, acceptsTransient, allowOutOfRangeReads, metadata, nowInSec, 
columnFilter, rowFilter, limits, indexQueryPlan, trackWarnings, dataRange);
         this.requestedSlices = 
dataRange.clusteringIndexFilter.getSlices(metadata());
     }
 
@@ -177,11 +175,6 @@ public class PartitionRangeReadCommand extends ReadCommand 
implements PartitionR
                       false);
     }
 
-    public DataRange dataRange()
-    {
-        return dataRange;
-    }
-
     public ClusteringIndexFilter clusteringIndexFilter(DecoratedKey key)
     {
         return dataRange.clusteringIndexFilter(key);
diff --git a/src/java/org/apache/cassandra/db/PartitionRangeReadQuery.java 
b/src/java/org/apache/cassandra/db/PartitionRangeReadQuery.java
index d48277d41f..d91930125d 100644
--- a/src/java/org/apache/cassandra/db/PartitionRangeReadQuery.java
+++ b/src/java/org/apache/cassandra/db/PartitionRangeReadQuery.java
@@ -41,8 +41,6 @@ public interface PartitionRangeReadQuery extends ReadQuery
         return PartitionRangeReadCommand.create(table, nowInSec, columnFilter, 
rowFilter, limits, dataRange);
     }
 
-    DataRange dataRange();
-
     /**
      * Creates a new {@code PartitionRangeReadQuery} with the updated limits.
      *
diff --git a/src/java/org/apache/cassandra/db/ReadCommand.java 
b/src/java/org/apache/cassandra/db/ReadCommand.java
index 34069df1c4..9c0bfe7e8b 100644
--- a/src/java/org/apache/cassandra/db/ReadCommand.java
+++ b/src/java/org/apache/cassandra/db/ReadCommand.java
@@ -130,6 +130,8 @@ public abstract class ReadCommand extends AbstractReadQuery
 
     private boolean trackWarnings;
 
+    protected final DataRange dataRange;
+
     @Nullable
     private final Index.QueryPlan indexQueryPlan;
 
@@ -175,7 +177,8 @@ public abstract class ReadCommand extends AbstractReadQuery
                           RowFilter rowFilter,
                           DataLimits limits,
                           Index.QueryPlan indexQueryPlan,
-                          boolean trackWarnings)
+                          boolean trackWarnings,
+                          DataRange dataRange)
     {
         super(metadata, nowInSec, columnFilter, rowFilter, limits);
         if (acceptsTransient && isDigestQuery)
@@ -189,6 +192,7 @@ public abstract class ReadCommand extends AbstractReadQuery
         this.allowsOutOfRangeReads = allowsOutOfRangeReads;
         this.trackWarnings = trackWarnings;
         this.serializedAtEpoch = serializedAtEpoch;
+        this.dataRange = dataRange;
     }
 
     public static ReadCommand getCommand()
@@ -319,6 +323,12 @@ public abstract class ReadCommand extends AbstractReadQuery
      */
     public abstract ClusteringIndexFilter clusteringIndexFilter(DecoratedKey 
key);
 
+    @Override
+    public DataRange dataRange()
+    {
+        return dataRange;
+    }
+
     /**
      * Returns a copy of this command.
      *
@@ -423,6 +433,7 @@ public abstract class ReadCommand extends AbstractReadQuery
      * validation method to check that nothing in this command's parameters
      * violates the implementation specific validation rules.
      */
+    @Override
     public void maybeValidateIndex()
     {
         if (null != indexQueryPlan)
diff --git a/src/java/org/apache/cassandra/db/ReadQuery.java 
b/src/java/org/apache/cassandra/db/ReadQuery.java
index 798e0bc7d4..ee383b9631 100644
--- a/src/java/org/apache/cassandra/db/ReadQuery.java
+++ b/src/java/org/apache/cassandra/db/ReadQuery.java
@@ -126,10 +126,15 @@ public interface ReadQuery
      */
     public TableMetadata metadata();
 
+    default DataRange dataRange()
+    {
+        throw new UnsupportedOperationException("dataRange() must be 
implemented by implementation class");
+    }
+
     /**
      * Starts a new read operation.
      * <p>
-     * This must be called before {@link executeInternal} and passed to it to 
protect the read.
+     * This must be called before {@link #executeInternal} and passed to it to 
protect the read.
      * The returned object <b>must</b> be closed on all path and it is thus 
strongly advised to
      * use it in a try-with-ressource construction.
      *
@@ -142,7 +147,7 @@ public interface ReadQuery
      *
      * @param consistency the consistency level to achieve for the query.
      * @param state client state
-     * @param state request enqueue / and start times
+     * @param requestTime request enqueue / and start times
      * @return the result of the query.
      */
     public PartitionIterator execute(ConsistencyLevel consistency, ClientState 
state, Dispatcher.RequestTime requestTime) throws RequestExecutionException;
diff --git a/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java 
b/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java
index 91c85486aa..ea770b812f 100644
--- a/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java
+++ b/src/java/org/apache/cassandra/db/SinglePartitionReadCommand.java
@@ -63,6 +63,7 @@ import org.apache.cassandra.db.transform.RTBoundValidator;
 import org.apache.cassandra.db.transform.Transformation;
 import org.apache.cassandra.db.virtual.VirtualKeyspaceRegistry;
 import org.apache.cassandra.db.virtual.VirtualTable;
+import org.apache.cassandra.dht.Bounds;
 import org.apache.cassandra.exceptions.RequestExecutionException;
 import org.apache.cassandra.index.Index;
 import org.apache.cassandra.io.sstable.SSTableReadsListener;
@@ -106,9 +107,10 @@ public class SinglePartitionReadCommand extends 
ReadCommand implements SinglePar
                                          DecoratedKey partitionKey,
                                          ClusteringIndexFilter 
clusteringIndexFilter,
                                          Index.QueryPlan indexQueryPlan,
-                                         boolean trackWarnings)
+                                         boolean trackWarnings,
+                                         DataRange dataRange)
     {
-        super(serializedAtEpoch, Kind.SINGLE_PARTITION, isDigest, 
digestVersion, acceptsTransient, allowsOutOfRangeReads, metadata, nowInSec, 
columnFilter, rowFilter, limits, indexQueryPlan, trackWarnings);
+        super(serializedAtEpoch, Kind.SINGLE_PARTITION, isDigest, 
digestVersion, acceptsTransient, allowsOutOfRangeReads, metadata, nowInSec, 
columnFilter, rowFilter, limits, indexQueryPlan, trackWarnings, dataRange);
         assert partitionKey.getPartitioner() == metadata.partitioner;
         this.partitionKey = partitionKey;
         this.clusteringIndexFilter = clusteringIndexFilter;
@@ -129,6 +131,8 @@ public class SinglePartitionReadCommand extends ReadCommand 
implements SinglePar
                                                      Index.QueryPlan 
indexQueryPlan,
                                                      boolean trackWarnings)
     {
+        DataRange dataRange = new DataRange(new Bounds<>(partitionKey, 
partitionKey), clusteringIndexFilter);
+
         if (metadata.isVirtual())
         {
             return new VirtualTableSinglePartitionReadCommand(isDigest,
@@ -142,7 +146,8 @@ public class SinglePartitionReadCommand extends ReadCommand 
implements SinglePar
                                                               partitionKey,
                                                               
clusteringIndexFilter,
                                                               indexQueryPlan,
-                                                              trackWarnings);
+                                                              trackWarnings,
+                                                              dataRange);
         }
         return new SinglePartitionReadCommand(serializedAtEpoch,
                                               isDigest,
@@ -157,7 +162,8 @@ public class SinglePartitionReadCommand extends ReadCommand 
implements SinglePar
                                               partitionKey,
                                               clusteringIndexFilter,
                                               indexQueryPlan,
-                                              trackWarnings);
+                                              trackWarnings,
+                                              dataRange);
     }
 
     /**
@@ -1400,9 +1406,10 @@ public class SinglePartitionReadCommand extends 
ReadCommand implements SinglePar
                                                          DecoratedKey 
partitionKey,
                                                          ClusteringIndexFilter 
clusteringIndexFilter,
                                                          Index.QueryPlan 
indexQueryPlan,
-                                                         boolean trackWarnings)
+                                                         boolean trackWarnings,
+                                                         DataRange dataRange)
         {
-            super(metadata.epoch, isDigest, digestVersion, true, 
acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, 
partitionKey, clusteringIndexFilter, indexQueryPlan, trackWarnings);
+            super(metadata.epoch, isDigest, digestVersion, true, 
acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, 
partitionKey, clusteringIndexFilter, indexQueryPlan, trackWarnings, dataRange);
         }
 
         @Override
diff --git a/src/java/org/apache/cassandra/db/SinglePartitionReadQuery.java 
b/src/java/org/apache/cassandra/db/SinglePartitionReadQuery.java
index 5d65c7307a..5409cde8c4 100644
--- a/src/java/org/apache/cassandra/db/SinglePartitionReadQuery.java
+++ b/src/java/org/apache/cassandra/db/SinglePartitionReadQuery.java
@@ -176,6 +176,13 @@ public interface SinglePartitionReadQuery extends ReadQuery
                 assert queries.get(i).nowInSec() == nowInSec;
         }
 
+        @Override
+        public void maybeValidateIndex()
+        {
+            for (ReadQuery query : queries)
+                query.maybeValidateIndex();
+        }
+
         public long nowInSec()
         {
             return nowInSec;
diff --git 
a/src/java/org/apache/cassandra/index/internal/CassandraIndexSearcher.java 
b/src/java/org/apache/cassandra/index/internal/CassandraIndexSearcher.java
index 55bbab65b2..61d446674e 100644
--- a/src/java/org/apache/cassandra/index/internal/CassandraIndexSearcher.java
+++ b/src/java/org/apache/cassandra/index/internal/CassandraIndexSearcher.java
@@ -21,20 +21,36 @@
 package org.apache.cassandra.index.internal;
 
 import java.nio.ByteBuffer;
-import java.util.NavigableSet;
+import java.util.SortedSet;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.cassandra.schema.TableMetadata;
-import org.apache.cassandra.db.*;
-import org.apache.cassandra.db.filter.*;
+import org.apache.cassandra.db.BufferClusteringBound;
+import org.apache.cassandra.db.Clustering;
+import org.apache.cassandra.db.ClusteringBound;
+import org.apache.cassandra.db.ColumnFamilyStore;
+import org.apache.cassandra.db.DataRange;
+import org.apache.cassandra.db.DecoratedKey;
+import org.apache.cassandra.db.PartitionPosition;
+import org.apache.cassandra.db.ReadCommand;
+import org.apache.cassandra.db.ReadExecutionController;
+import org.apache.cassandra.db.SinglePartitionReadCommand;
+import org.apache.cassandra.db.Slice;
+import org.apache.cassandra.db.Slices;
+import org.apache.cassandra.db.filter.ClusteringIndexFilter;
+import org.apache.cassandra.db.filter.ClusteringIndexNamesFilter;
+import org.apache.cassandra.db.filter.ClusteringIndexSliceFilter;
+import org.apache.cassandra.db.filter.ColumnFilter;
+import org.apache.cassandra.db.filter.RowFilter;
 import org.apache.cassandra.db.partitions.UnfilteredPartitionIterator;
 import org.apache.cassandra.db.rows.RowIterator;
 import org.apache.cassandra.db.rows.UnfilteredRowIterator;
 import org.apache.cassandra.db.rows.UnfilteredRowIterators;
 import org.apache.cassandra.dht.AbstractBounds;
 import org.apache.cassandra.index.Index;
+import org.apache.cassandra.index.internal.composites.CollectionValueIndex;
+import org.apache.cassandra.schema.TableMetadata;
 import org.apache.cassandra.utils.btree.BTreeSet;
 
 public abstract class CassandraIndexSearcher implements Index.Searcher
@@ -90,17 +106,33 @@ public abstract class CassandraIndexSearcher implements 
Index.Searcher
     {
         if (command instanceof SinglePartitionReadCommand)
         {
-            // Note: as yet there's no route to get here - a 2i query *always* 
uses a
-            // PartitionRangeReadCommand. This is here in preparation for 
coming changes
-            // in SelectStatement.
             SinglePartitionReadCommand sprc = 
(SinglePartitionReadCommand)command;
             ByteBuffer pk = sprc.partitionKey().getKey();
             ClusteringIndexFilter filter = sprc.clusteringIndexFilter();
 
             if (filter instanceof ClusteringIndexNamesFilter)
             {
-                NavigableSet<Clustering<?>> requested = 
((ClusteringIndexNamesFilter)filter).requestedRows();
-                BTreeSet<Clustering<?>> clusterings = BTreeSet.copy(requested, 
index.getIndexComparator());
+                if (index instanceof CollectionValueIndex)
+                {
+                    // Collection value indexes have an extra clustering key 
for the path, but we cannot construct an
+                    // index names filter from the filter on the backing 
table, because it has no path information.
+                    // Instead, we construct a slice from the clustering keys 
that are provided.
+                    Slices slices = filter.getSlices(index.baseCfs.metadata());
+                    ClusteringBound<?> start = BufferClusteringBound.BOTTOM;
+                    ClusteringBound<?> end = BufferClusteringBound.TOP;
+
+                    if (slices.size() > 0)
+                        start = slices.get(0).start();
+                    if (slices.size() > 0)
+                        end = slices.get(slices.size() - 1).end();
+
+                    Slice slice = Slice.make(makeIndexBound(pk, start), 
makeIndexBound(pk, end));
+                    return new 
ClusteringIndexSliceFilter(Slices.with(index.getIndexComparator(), slice), 
filter.isReversed());
+                }
+
+                SortedSet<Clustering<?>> requested = 
((ClusteringIndexNamesFilter) filter).requestedRows();
+                // The partition key from the base table must be the first 
element of al clusterings of the index table.
+                BTreeSet<Clustering<?>> clusterings = BTreeSet.copy(requested, 
index.getIndexComparator(), clustering -> makeIndexClustering(pk, clustering));
                 return new ClusteringIndexNamesFilter(clusterings, 
filter.isReversed());
             }
             else
@@ -114,8 +146,7 @@ public abstract class CassandraIndexSearcher implements 
Index.Searcher
         }
         else
         {
-
-            DataRange dataRange = 
((PartitionRangeReadCommand)command).dataRange();
+            DataRange dataRange = command.dataRange();
             AbstractBounds<PartitionPosition> range = dataRange.keyRange();
 
             Slice slice = Slice.ALL;
@@ -145,10 +176,8 @@ public abstract class CassandraIndexSearcher implements 
Index.Searcher
                      */
                     if (!dataRange.isNamesQuery() && 
!index.indexedColumn.isStatic())
                     {
-                        ClusteringIndexSliceFilter startSliceFilter = 
((ClusteringIndexSliceFilter) dataRange.clusteringIndexFilter(
-                                                                               
                                                    startKey));
-                        ClusteringIndexSliceFilter endSliceFilter = 
((ClusteringIndexSliceFilter) dataRange.clusteringIndexFilter(
-                                                                               
                                                  endKey));
+                        ClusteringIndexSliceFilter startSliceFilter = 
((ClusteringIndexSliceFilter) dataRange.clusteringIndexFilter(startKey));
+                        ClusteringIndexSliceFilter endSliceFilter = 
((ClusteringIndexSliceFilter) dataRange.clusteringIndexFilter(endKey));
 
                         // We can't effectively support reversed queries when 
we have a range, so we don't support it
                         // (or through post-query reordering) and shouldn't 
get there.
diff --git a/src/java/org/apache/cassandra/index/sai/plan/QueryController.java 
b/src/java/org/apache/cassandra/index/sai/plan/QueryController.java
index 7b9b91c526..4f8efb8248 100644
--- a/src/java/org/apache/cassandra/index/sai/plan/QueryController.java
+++ b/src/java/org/apache/cassandra/index/sai/plan/QueryController.java
@@ -48,7 +48,6 @@ import org.apache.cassandra.db.guardrails.Guardrails;
 import org.apache.cassandra.db.rows.Row;
 import org.apache.cassandra.db.rows.UnfilteredRowIterator;
 import org.apache.cassandra.dht.AbstractBounds;
-import org.apache.cassandra.dht.Range;
 import org.apache.cassandra.index.sai.QueryContext;
 import org.apache.cassandra.index.sai.StorageAttachedIndex;
 import org.apache.cassandra.index.sai.VectorQueryContext;
@@ -437,14 +436,11 @@ public class QueryController
     {
         if (command instanceof SinglePartitionReadCommand)
         {
-            SinglePartitionReadCommand cmd = (SinglePartitionReadCommand) 
command;
-            DecoratedKey key = cmd.partitionKey();
-            return Lists.newArrayList(new DataRange(new Range<>(key, key), 
cmd.clusteringIndexFilter()));
+            return Lists.newArrayList(command.dataRange());
         }
         else if (command instanceof PartitionRangeReadCommand)
         {
-            PartitionRangeReadCommand cmd = (PartitionRangeReadCommand) 
command;
-            return Lists.newArrayList(cmd.dataRange());
+            return Lists.newArrayList(command.dataRange());
         }
         else
         {
diff --git a/src/java/org/apache/cassandra/index/sasi/plan/QueryController.java 
b/src/java/org/apache/cassandra/index/sasi/plan/QueryController.java
index 15865570ce..432dd80677 100644
--- a/src/java/org/apache/cassandra/index/sasi/plan/QueryController.java
+++ b/src/java/org/apache/cassandra/index/sasi/plan/QueryController.java
@@ -27,7 +27,7 @@ import com.google.common.collect.Sets;
 import org.apache.cassandra.db.ColumnFamilyStore;
 import org.apache.cassandra.db.DataRange;
 import org.apache.cassandra.db.DecoratedKey;
-import org.apache.cassandra.db.PartitionRangeReadCommand;
+import org.apache.cassandra.db.ReadCommand;
 import org.apache.cassandra.db.ReadExecutionController;
 import org.apache.cassandra.db.SinglePartitionReadCommand;
 import org.apache.cassandra.db.filter.DataLimits;
@@ -58,11 +58,11 @@ public class QueryController
     private final long executionStart;
 
     private final ColumnFamilyStore cfs;
-    private final PartitionRangeReadCommand command;
+    private final ReadCommand command;
     private final DataRange range;
     private final Map<Collection<Expression>, List<RangeIterator<Long, 
Token>>> resources = new HashMap<>();
 
-    public QueryController(ColumnFamilyStore cfs, PartitionRangeReadCommand 
command, long timeQuotaMs)
+    public QueryController(ColumnFamilyStore cfs, ReadCommand command, long 
timeQuotaMs)
     {
         this.cfs = cfs;
         this.command = command;
diff --git 
a/src/java/org/apache/cassandra/index/sasi/plan/SASIIndexSearcher.java 
b/src/java/org/apache/cassandra/index/sasi/plan/SASIIndexSearcher.java
index 10d2aab5c4..6da4f8a969 100644
--- a/src/java/org/apache/cassandra/index/sasi/plan/SASIIndexSearcher.java
+++ b/src/java/org/apache/cassandra/index/sasi/plan/SASIIndexSearcher.java
@@ -38,7 +38,7 @@ public class SASIIndexSearcher implements Index.Searcher
     public SASIIndexSearcher(ColumnFamilyStore cfs, ReadCommand command, long 
executionQuotaMs)
     {
         this.command = command;
-        this.controller = new QueryController(cfs, (PartitionRangeReadCommand) 
command, executionQuotaMs);
+        this.controller = new QueryController(cfs, command, executionQuotaMs);
     }
 
     @Override
diff --git a/src/java/org/apache/cassandra/utils/btree/BTreeSet.java 
b/src/java/org/apache/cassandra/utils/btree/BTreeSet.java
index 949c4c0721..20ee7cf044 100644
--- a/src/java/org/apache/cassandra/utils/btree/BTreeSet.java
+++ b/src/java/org/apache/cassandra/utils/btree/BTreeSet.java
@@ -30,6 +30,7 @@ import java.util.Objects;
 import java.util.SortedSet;
 import java.util.Spliterator;
 import java.util.Spliterators;
+import java.util.function.Function;
 
 import com.google.common.collect.Ordering;
 
@@ -680,10 +681,15 @@ public class BTreeSet<V> extends AbstractSet<V> 
implements NavigableSet<V>, List
     }
 
     public static <V> BTreeSet<V> copy(SortedSet<? extends V> copy, 
Comparator<? super V> comparator)
+    {
+        return copy(copy, comparator, v -> v);
+    }
+
+    public static <V> BTreeSet<V> copy(SortedSet<? extends V> copy, 
Comparator<? super V> comparator, Function<V, V> modifier)
     {
         try (BTree.FastBuilder<V> builder = BTree.fastBuilder())
         {
-            copy.forEach(builder::add);
+            copy.forEach(value -> builder.add(modifier.apply(value)));
             return wrap(builder.build(), comparator);
         }
     }
diff --git 
a/test/unit/org/apache/cassandra/db/AbstractReadQueryToCQLStringTest.java 
b/test/unit/org/apache/cassandra/db/AbstractReadQueryToCQLStringTest.java
index 7d3162413b..019a70e819 100644
--- a/test/unit/org/apache/cassandra/db/AbstractReadQueryToCQLStringTest.java
+++ b/test/unit/org/apache/cassandra/db/AbstractReadQueryToCQLStringTest.java
@@ -103,8 +103,7 @@ public class AbstractReadQueryToCQLStringTest extends 
CQLTester
         test("SELECT * FROM %s WHERE v2 = 2 ALLOW FILTERING");
         test("SELECT * FROM %s WHERE v1 = 1 AND v2 = 2 ALLOW FILTERING");
         test("SELECT * FROM %s WHERE token(k) > 0 AND v1 = 1");
-        test("SELECT * FROM %s WHERE k = 0 AND v1 = 1",
-             "SELECT * FROM %s WHERE token(k) >= token(0) AND token(k) <= 
token(0) AND v1 = 1");
+        test("SELECT * FROM %s WHERE k = 0 AND v1 = 1");
 
         // grouped partition-directed queries, maybe producing multiple queries
         test("SELECT * FROM %s WHERE k IN (0)",
@@ -188,8 +187,7 @@ public class AbstractReadQueryToCQLStringTest extends 
CQLTester
         test("SELECT * FROM %s WHERE token(k1, k2) > 0 AND k2 = 2");
         test("SELECT * FROM %s WHERE token(k1, k2) > 0 AND v1 = 1");
         test("SELECT * FROM %s WHERE token(k1, k2) > 0 AND v2 = 2");
-        test("SELECT * FROM %s WHERE k1 = 1 AND k2 = 2 AND v1 = 1",
-             "SELECT * FROM %s WHERE token(k1, k2) >= token(1, 2) AND 
token(k1, k2) <= token(1, 2) AND v1 = 1");
+        test("SELECT * FROM %s WHERE k1 = 1 AND k2 = 2 AND v1 = 1");
 
         // grouped partition-directed queries, maybe producing multiple queries
         test("SELECT * FROM %s WHERE k1 IN (1) AND k2 = 2",
@@ -279,10 +277,9 @@ public class AbstractReadQueryToCQLStringTest extends 
CQLTester
         test("SELECT * FROM %s WHERE v2 = 2 ALLOW FILTERING");
         test("SELECT * FROM %s WHERE v1 = 1 AND v2 = 2 ALLOW FILTERING");
         test("SELECT * FROM %s WHERE token(k) > 0 AND v1 = 1");
-        test("SELECT * FROM %s WHERE k = 0 AND v1 = 1",
-             "SELECT * FROM %s WHERE token(k) >= token(0) AND token(k) <= 
token(0) AND v1 = 1");
+        test("SELECT * FROM %s WHERE k = 0 AND v1 = 1");
         test("SELECT * FROM %s WHERE k = 0 AND v1 = 1 AND c = 1",
-             "SELECT * FROM %s WHERE token(k) >= token(0) AND token(k) <= 
token(0) AND c = 1 AND v1 = 1 ALLOW FILTERING");
+             "SELECT * FROM %s WHERE k = 0 AND c = 1 AND v1 = 1 ALLOW 
FILTERING");
 
         // grouped partition-directed queries, maybe producing multiple queries
         test("SELECT * FROM %s WHERE k IN (0)",
@@ -426,10 +423,8 @@ public class AbstractReadQueryToCQLStringTest extends 
CQLTester
              "SELECT * FROM %s WHERE (c1, c2, c3) = (1, 2, 3) ALLOW 
FILTERING");
         test("SELECT * FROM %s WHERE v1 = 1 AND v2 = 2 ALLOW FILTERING");
         test("SELECT * FROM %s WHERE token(k1, k2) > 0 AND v1 = 1");
-        test("SELECT * FROM %s WHERE k1 = 1 AND k2 = 2 AND v1 = 1",
-             "SELECT * FROM %s WHERE token(k1, k2) >= token(1, 2) AND 
token(k1, k2) <= token(1, 2) AND v1 = 1");
-        test("SELECT * FROM %s WHERE k1 = 1 AND k2 = 2 AND c1 = 1 AND v1 = 1",
-             "SELECT * FROM %s WHERE token(k1, k2) >= token(1, 2) AND 
token(k1, k2) <= token(1, 2) AND c1 = 1 AND v1 = 1 ALLOW FILTERING");
+        test("SELECT * FROM %s WHERE k1 = 1 AND k2 = 2 AND v1 = 1");
+        test("SELECT * FROM %s WHERE k1 = 1 AND k2 = 2 AND c1 = 1 AND v1 = 1");
 
         // grouped partition-directed queries, maybe producing multiple queries
         test("SELECT * FROM %s WHERE k1 IN (1) AND k2 IN (2)",
@@ -798,7 +793,7 @@ public class AbstractReadQueryToCQLStringTest extends 
CQLTester
         test(query, query);
     }
 
-    private void test(String query, String... expected) throws Throwable
+    private void test(String query, String... expected)
     {
         List<String> actual = toCQLString(query);
         List<String> fullExpected = Stream.of(expected)
diff --git 
a/test/unit/org/apache/cassandra/db/ReadCommandVerbHandlerOutOfRangeTest.java 
b/test/unit/org/apache/cassandra/db/ReadCommandVerbHandlerOutOfRangeTest.java
index 77ad4a6558..0462c6d61b 100644
--- 
a/test/unit/org/apache/cassandra/db/ReadCommandVerbHandlerOutOfRangeTest.java
+++ 
b/test/unit/org/apache/cassandra/db/ReadCommandVerbHandlerOutOfRangeTest.java
@@ -228,7 +228,8 @@ public class ReadCommandVerbHandlerOutOfRangeTest
                   key(tmd, key),
                   null,
                   null,
-                  false);
+                  false,
+                  null);
 
             this.tmd = tmd;
         }
diff --git a/test/unit/org/apache/cassandra/db/ReadCommandVerbHandlerTest.java 
b/test/unit/org/apache/cassandra/db/ReadCommandVerbHandlerTest.java
index 980f3e03c0..bc2b285d98 100644
--- a/test/unit/org/apache/cassandra/db/ReadCommandVerbHandlerTest.java
+++ b/test/unit/org/apache/cassandra/db/ReadCommandVerbHandlerTest.java
@@ -182,7 +182,8 @@ public class ReadCommandVerbHandlerTest
                   KEY,
                   new ClusteringIndexSliceFilter(Slices.ALL, false),
                   null,
-                  false);
+                  false,
+                  null);
         }
 
         @Override
diff --git a/test/unit/org/apache/cassandra/db/ReadResponseTest.java 
b/test/unit/org/apache/cassandra/db/ReadResponseTest.java
index 6a5d2e8ab4..e594369037 100644
--- a/test/unit/org/apache/cassandra/db/ReadResponseTest.java
+++ b/test/unit/org/apache/cassandra/db/ReadResponseTest.java
@@ -264,7 +264,8 @@ public class ReadResponseTest
                   metadata.partitioner.decorateKey(ByteBufferUtil.bytes(key)),
                   null,
                   null,
-                  false);
+                  false,
+                  null);
            
         }
 
diff --git a/test/unit/org/apache/cassandra/service/reads/ReadExecutorTest.java 
b/test/unit/org/apache/cassandra/service/reads/ReadExecutorTest.java
index 629df12a42..9dee28b16c 100644
--- a/test/unit/org/apache/cassandra/service/reads/ReadExecutorTest.java
+++ b/test/unit/org/apache/cassandra/service/reads/ReadExecutorTest.java
@@ -250,7 +250,7 @@ public class ReadExecutorTest
 
         MockSinglePartitionReadCommand(long timeout)
         {
-            super(cfs.metadata().epoch, false, 0, false, false, 
cfs.metadata(), 0, null, null, null, Util.dk("ry@n_luvs_teh_y@nk33z"), null, 
null, false);
+            super(cfs.metadata().epoch, false, 0, false, false, 
cfs.metadata(), 0, null, null, null, Util.dk("ry@n_luvs_teh_y@nk33z"), null, 
null, false, null);
             this.timeout = timeout;
         }
 
diff --git 
a/test/unit/org/apache/cassandra/service/reads/repair/RepairedDataVerifierTest.java
 
b/test/unit/org/apache/cassandra/service/reads/repair/RepairedDataVerifierTest.java
index a478573503..7bdd08349a 100644
--- 
a/test/unit/org/apache/cassandra/service/reads/repair/RepairedDataVerifierTest.java
+++ 
b/test/unit/org/apache/cassandra/service/reads/repair/RepairedDataVerifierTest.java
@@ -290,7 +290,8 @@ public class RepairedDataVerifierTest
                   metadata.partitioner.decorateKey(ByteBufferUtil.bytes(key)),
                   new ClusteringIndexSliceFilter(Slices.ALL, false),
                   null,
-                  false);
+                  false,
+                  null);
         }
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to