mirror of https://github.com/apache/cassandra
Use SinglePartitionReadCommand for index queries that use strict filtering
patch by Caleb Rackliffe; reviewed by Ariel Weisberg for CASSANDRA-19968
This commit is contained in:
parent
176ce395bb
commit
019c9118d4
|
|
@ -1,4 +1,5 @@
|
|||
5.0.2
|
||||
* Use SinglePartitionReadCommand for index queries that use strict filtering (CASSANDRA-19968)
|
||||
* Always write local expiration time as an int to LivenessInfo digest (CASSANDRA-19989)
|
||||
* Enables IAuthenticator's to return own AuthenticateMessage (CASSANDRA-19984)
|
||||
* Use ParameterizedClass for all auth-related implementations (CASSANDRA-19946)
|
||||
|
|
|
|||
|
|
@ -398,17 +398,20 @@ public class SelectStatement implements CQLStatement.SingleKeyspaceCqlStatement
|
|||
long nowInSec,
|
||||
DataLimits limit)
|
||||
{
|
||||
boolean isPartitionRangeQuery = restrictions.isKeyRange() || restrictions.usesSecondaryIndexing();
|
||||
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,
|
||||
|
|
@ -708,7 +711,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())
|
||||
|
|
@ -723,8 +726,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)
|
||||
{
|
||||
|
|
@ -732,7 +733,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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -780,14 +787,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);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
|
|||
{
|
||||
protected static final SelectionDeserializer selectionDeserializer = new Deserializer();
|
||||
|
||||
protected final DataRange dataRange;
|
||||
protected final Slices requestedSlices;
|
||||
|
||||
@VisibleForTesting
|
||||
|
|
@ -79,8 +78,7 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
|
|||
Index.QueryPlan indexQueryPlan,
|
||||
boolean trackWarnings)
|
||||
{
|
||||
super(Kind.PARTITION_RANGE, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, indexQueryPlan, trackWarnings);
|
||||
this.dataRange = dataRange;
|
||||
super(Kind.PARTITION_RANGE, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, indexQueryPlan, trackWarnings, dataRange);
|
||||
this.requestedSlices = dataRange.clusteringIndexFilter.getSlices(metadata());
|
||||
|
||||
}
|
||||
|
|
@ -167,11 +165,6 @@ public class PartitionRangeReadCommand extends ReadCommand implements PartitionR
|
|||
false);
|
||||
}
|
||||
|
||||
public DataRange dataRange()
|
||||
{
|
||||
return dataRange;
|
||||
}
|
||||
|
||||
public ClusteringIndexFilter clusteringIndexFilter(DecoratedKey key)
|
||||
{
|
||||
return dataRange.clusteringIndexFilter(key);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -106,6 +106,8 @@ public abstract class ReadCommand extends AbstractReadQuery
|
|||
|
||||
private boolean trackWarnings;
|
||||
|
||||
protected final DataRange dataRange;
|
||||
|
||||
@Nullable
|
||||
private final Index.QueryPlan indexQueryPlan;
|
||||
|
||||
|
|
@ -147,7 +149,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)
|
||||
|
|
@ -159,6 +162,7 @@ public abstract class ReadCommand extends AbstractReadQuery
|
|||
this.acceptsTransient = acceptsTransient;
|
||||
this.indexQueryPlan = indexQueryPlan;
|
||||
this.trackWarnings = trackWarnings;
|
||||
this.dataRange = dataRange;
|
||||
}
|
||||
|
||||
public static ReadCommand getCommand()
|
||||
|
|
@ -290,6 +294,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.
|
||||
*
|
||||
|
|
@ -394,6 +404,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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -103,9 +104,10 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
|
|||
DecoratedKey partitionKey,
|
||||
ClusteringIndexFilter clusteringIndexFilter,
|
||||
Index.QueryPlan indexQueryPlan,
|
||||
boolean trackWarnings)
|
||||
boolean trackWarnings,
|
||||
DataRange dataRange)
|
||||
{
|
||||
super(Kind.SINGLE_PARTITION, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, indexQueryPlan, trackWarnings);
|
||||
super(Kind.SINGLE_PARTITION, isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, indexQueryPlan, trackWarnings, dataRange);
|
||||
assert partitionKey.getPartitioner() == metadata.partitioner;
|
||||
this.partitionKey = partitionKey;
|
||||
this.clusteringIndexFilter = clusteringIndexFilter;
|
||||
|
|
@ -124,6 +126,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,
|
||||
|
|
@ -137,7 +141,8 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
|
|||
partitionKey,
|
||||
clusteringIndexFilter,
|
||||
indexQueryPlan,
|
||||
trackWarnings);
|
||||
trackWarnings,
|
||||
dataRange);
|
||||
}
|
||||
return new SinglePartitionReadCommand(isDigest,
|
||||
digestVersion,
|
||||
|
|
@ -150,7 +155,8 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
|
|||
partitionKey,
|
||||
clusteringIndexFilter,
|
||||
indexQueryPlan,
|
||||
trackWarnings);
|
||||
trackWarnings,
|
||||
dataRange);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1361,9 +1367,11 @@ public class SinglePartitionReadCommand extends ReadCommand implements SinglePar
|
|||
DecoratedKey partitionKey,
|
||||
ClusteringIndexFilter clusteringIndexFilter,
|
||||
Index.QueryPlan indexQueryPlan,
|
||||
boolean trackWarnings)
|
||||
boolean trackWarnings,
|
||||
DataRange dataRange)
|
||||
{
|
||||
super(isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter, rowFilter, limits, partitionKey, clusteringIndexFilter, indexQueryPlan, trackWarnings);
|
||||
super(isDigest, digestVersion, acceptsTransient, metadata, nowInSec, columnFilter,
|
||||
rowFilter, limits, partitionKey, clusteringIndexFilter, indexQueryPlan, trackWarnings, dataRange);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -18,7 +18,18 @@
|
|||
*/
|
||||
package org.apache.cassandra.utils.btree;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.NoSuchElementException;
|
||||
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;
|
||||
|
||||
|
|
@ -648,10 +659,15 @@ public class BTreeSet<V> implements NavigableSet<V>, List<V>
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,8 +102,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)",
|
||||
|
|
@ -187,8 +186,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",
|
||||
|
|
@ -278,10 +276,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)",
|
||||
|
|
@ -425,10 +422,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)",
|
||||
|
|
@ -792,7 +787,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)
|
||||
|
|
|
|||
|
|
@ -210,7 +210,8 @@ public class ReadCommandVerbHandlerOutOfRangeTest
|
|||
key(tmd, key),
|
||||
null,
|
||||
null,
|
||||
false);
|
||||
false,
|
||||
null);
|
||||
|
||||
this.tmd = tmd;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,7 +171,8 @@ public class ReadCommandVerbHandlerTest
|
|||
KEY,
|
||||
new ClusteringIndexSliceFilter(Slices.ALL, false),
|
||||
null,
|
||||
false);
|
||||
false,
|
||||
null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -251,7 +251,8 @@ public class ReadResponseTest
|
|||
metadata.partitioner.decorateKey(ByteBufferUtil.bytes(key)),
|
||||
null,
|
||||
null,
|
||||
false);
|
||||
false,
|
||||
null);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ public class ReadExecutorTest
|
|||
|
||||
MockSinglePartitionReadCommand(long timeout)
|
||||
{
|
||||
super(false, 0, false, cfs.metadata(), 0, null, null, null, Util.dk("ry@n_luvs_teh_y@nk33z"), null, null, false);
|
||||
super(false, 0, false, cfs.metadata(), 0, null, null, null, Util.dk("ry@n_luvs_teh_y@nk33z"), null, null, false, null);
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -288,7 +288,8 @@ public class RepairedDataVerifierTest
|
|||
metadata.partitioner.decorateKey(ByteBufferUtil.bytes(key)),
|
||||
new ClusteringIndexSliceFilter(Slices.ALL, false),
|
||||
null,
|
||||
false);
|
||||
false,
|
||||
null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue