private ClusteringIndexFilter makeIndexFilter(AbstractSimplePerColumnSecondaryIndex index, ReadCommand command)
    {
        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();
                NavigableSet<Clustering> clusterings = new TreeSet<>(index.getIndexComparator());
                for (Clustering c : requested)
                    clusterings.add(index.makeIndexClustering(pk, c, (Cell)null).takeAlias());
                return new ClusteringIndexNamesFilter(clusterings, filter.isReversed());
            }
            else
            {
                Slices requested = ((ClusteringIndexSliceFilter)filter).requestedSlices();
                Slices.Builder builder = new Slices.Builder(index.getIndexComparator());
                for (Slice slice : requested)
                    builder.add(index.makeIndexBound(pk, slice.start()), index.makeIndexBound(pk, slice.end()));
                return new ClusteringIndexSliceFilter(builder.build(), filter.isReversed());
            }
        }
        else
        {
            DataRange dataRange = ((PartitionRangeReadCommand)command).dataRange();
            AbstractBounds<PartitionPosition> range = dataRange.keyRange();
            Slice slice = Slice.ALL;
            /*
             * XXX: If the range requested is a token range, we'll have to start at the beginning (and stop at the end) of
             * the indexed row unfortunately (which will be inefficient), because we have no way to intuit the smallest possible
             * key having a given token. A potential fix would be to actually store the token along the key in the indexed row.
             */
            if (range.left instanceof DecoratedKey)
            {
                // the right hand side of the range may not be a DecoratedKey (for instance if we're paging),
                // but if it is, we can optimise slightly by restricting the slice
                if (range.right instanceof DecoratedKey)
                {
                    DecoratedKey startKey = (DecoratedKey) range.left;
                    DecoratedKey endKey = (DecoratedKey) range.right;
                    Slice.Bound start = Slice.Bound.BOTTOM;
                    Slice.Bound end = Slice.Bound.TOP;
                    /*
                     * For index queries over a range, we can't do a whole lot better than querying everything for the key range, though for
                     * slice queries where we can slightly restrict the beginning and end.
                     */
                    if (!dataRange.isNamesQuery())
                    {
                        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.
                        assert !startSliceFilter.isReversed() && !endSliceFilter.isReversed();
                        Slices startSlices = startSliceFilter.requestedSlices();
                        Slices endSlices = endSliceFilter.requestedSlices();
                        if (startSlices.size() > 0)
                            start = startSlices.get(0).start();
                        if (endSlices.size() > 0)
                            end = endSlices.get(endSlices.size() - 1).end();
                    }
                    slice = Slice.make(index.makeIndexBound(startKey.getKey(), start),
                                       index.makeIndexBound(endKey.getKey(), end));
                }
                else
                {
                   // otherwise, just start the index slice from the key we do have
                   slice = Slice.make(index.makeIndexBound(((DecoratedKey)range.left).getKey(), Slice.Bound.BOTTOM),
                                      Slice.Bound.TOP);
                }
            }
            return new ClusteringIndexSliceFilter(Slices.with(index.getIndexComparator(), slice), false);
        }
    }
private ClusteringIndexFilter makeIndexFilter(AbstractSimplePerColumnSecondaryIndex index, ReadCommand command)
    {
        if (command instanceof SinglePartitionReadCommand)
        {
           
           
           
            SinglePartitionReadCommand sprc = (SinglePartitionReadCommand)command;
            ByteBuffer pk = sprc.partitionKey().getKey();
            ClusteringIndexFilter filter = sprc.clusteringIndexFilter();
            if (filter instanceof ClusteringIndexNamesFilter)
            {
                NavigableSet<Clustering> requested = ((ClusteringIndexNamesFilter)filter).requestedRows();
                NavigableSet<Clustering> clusterings = new TreeSet<>(index.getIndexComparator());
                for (Clustering c : requested)
                    clusterings.add(index.makeIndexClustering(pk, c, (Cell)null).takeAlias());
                return new ClusteringIndexNamesFilter(clusterings, filter.isReversed());
            }
            else
            {
                Slices requested = ((ClusteringIndexSliceFilter)filter).requestedSlices();
                Slices.Builder builder = new Slices.Builder(index.getIndexComparator());
                for (Slice slice : requested)
                    builder.add(index.makeIndexBound(pk, slice.start()), index.makeIndexBound(pk, slice.end()));
                return new ClusteringIndexSliceFilter(builder.build(), filter.isReversed());
            }
        }
        else
        {
            DataRange dataRange = ((PartitionRangeReadCommand)command).dataRange();
            AbstractBounds<PartitionPosition> range = dataRange.keyRange();
            Slice slice = Slice.ALL;
           
            if (range.left instanceof DecoratedKey)
            {
               
               
                if (range.right instanceof DecoratedKey)
                {
                    DecoratedKey startKey = (DecoratedKey) range.left;
                    DecoratedKey endKey = (DecoratedKey) range.right;
                    Slice.Bound start = Slice.Bound.BOTTOM;
                    Slice.Bound end = Slice.Bound.TOP;
                   
                    if (!dataRange.isNamesQuery())
                    {
                        ClusteringIndexSliceFilter startSliceFilter = ((ClusteringIndexSliceFilter) dataRange.clusteringIndexFilter(startKey));
                        ClusteringIndexSliceFilter endSliceFilter = ((ClusteringIndexSliceFilter) dataRange.clusteringIndexFilter(endKey));
                       
                       
                        assert !startSliceFilter.isReversed() && !endSliceFilter.isReversed();
                        Slices startSlices = startSliceFilter.requestedSlices();
                        Slices endSlices = endSliceFilter.requestedSlices();
                        if (startSlices.size() > 0)
                            start = startSlices.get(0).start();
                        if (endSlices.size() > 0)
                            end = endSlices.get(endSlices.size() - 1).end();
                    }
                    slice = Slice.make(index.makeIndexBound(startKey.getKey(), start),
                                       index.makeIndexBound(endKey.getKey(), end));
                }
                else
                {
                  
                   slice = Slice.make(index.makeIndexBound(((DecoratedKey)range.left).getKey(), Slice.Bound.BOTTOM),
                                      Slice.Bound.TOP);
                }
            }
            return new ClusteringIndexSliceFilter(Slices.with(index.getIndexComparator(), slice), false);
        }
    }
private clusteringindexfilter makeindexfilter(abstractsimplepercolumnsecondaryindex index, readcommand command) { if (command instanceof singlepartitionreadcommand) { singlepartitionreadcommand sprc = (singlepartitionreadcommand)command; bytebuffer pk = sprc.partitionkey().getkey(); clusteringindexfilter filter = sprc.clusteringindexfilter(); if (filter instanceof clusteringindexnamesfilter) { navigableset<clustering> requested = ((clusteringindexnamesfilter)filter).requestedrows(); navigableset<clustering> clusterings = new treeset<>(index.getindexcomparator()); for (clustering c : requested) clusterings.add(index.makeindexclustering(pk, c, (cell)null).takealias()); return new clusteringindexnamesfilter(clusterings, filter.isreversed()); } else { slices requested = ((clusteringindexslicefilter)filter).requestedslices(); slices.builder builder = new slices.builder(index.getindexcomparator()); for (slice slice : requested) builder.add(index.makeindexbound(pk, slice.start()), index.makeindexbound(pk, slice.end())); return new clusteringindexslicefilter(builder.build(), filter.isreversed()); } } else { datarange datarange = ((partitionrangereadcommand)command).datarange(); abstractbounds<partitionposition> range = datarange.keyrange(); slice slice = slice.all; if (range.left instanceof decoratedkey) { if (range.right instanceof decoratedkey) { decoratedkey startkey = (decoratedkey) range.left; decoratedkey endkey = (decoratedkey) range.right; slice.bound start = slice.bound.bottom; slice.bound end = slice.bound.top; if (!datarange.isnamesquery()) { clusteringindexslicefilter startslicefilter = ((clusteringindexslicefilter) datarange.clusteringindexfilter(startkey)); clusteringindexslicefilter endslicefilter = ((clusteringindexslicefilter) datarange.clusteringindexfilter(endkey)); assert !startslicefilter.isreversed() && !endslicefilter.isreversed(); slices startslices = startslicefilter.requestedslices(); slices endslices = endslicefilter.requestedslices(); if (startslices.size() > 0) start = startslices.get(0).start(); if (endslices.size() > 0) end = endslices.get(endslices.size() - 1).end(); } slice = slice.make(index.makeindexbound(startkey.getkey(), start), index.makeindexbound(endkey.getkey(), end)); } else { slice = slice.make(index.makeindexbound(((decoratedkey)range.left).getkey(), slice.bound.bottom), slice.bound.top); } } return new clusteringindexslicefilter(slices.with(index.getindexcomparator(), slice), false); } }