Merge branch 'cassandra-2.0' into trunk Conflicts: src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/c36656c0 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/c36656c0 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/c36656c0 Branch: refs/heads/trunk Commit: c36656c06bc10bccace324d40adc7d038de2f74f Parents: 5b0eb01 44f9c86 Author: Sylvain Lebresne <sylv...@datastax.com> Authored: Fri Feb 14 13:52:57 2014 +0100 Committer: Sylvain Lebresne <sylv...@datastax.com> Committed: Fri Feb 14 13:52:57 2014 +0100 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../apache/cassandra/cql3/statements/SelectStatement.java | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/c36656c0/CHANGES.txt ---------------------------------------------------------------------- diff --cc CHANGES.txt index 42c8bd9,57eefac..d08cb93 --- a/CHANGES.txt +++ b/CHANGES.txt @@@ -56,8 -21,8 +56,9 @@@ Merged from 1.2 * Log USING TTL/TIMESTAMP in a counter update warning (CASSANDRA-6649) * Don't exchange schema between nodes with different versions (CASSANDRA-6695) * Use real node messaging versions for schema exchange decisions (CASSANDRA-6700) + * IN on the last clustering columns + ORDER BY DESC yield no results (CASSANDRA-6701) + 2.0.5 * Reduce garbage generated by bloom filter lookups (CASSANDRA-6609) * Add ks.cf names to tombstone logging (CASSANDRA-6597) http://git-wip-us.apache.org/repos/asf/cassandra/blob/c36656c0/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java ---------------------------------------------------------------------- diff --cc src/java/org/apache/cassandra/cql3/statements/SelectStatement.java index 3bf5906,307e668..60d13f4 --- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java @@@ -694,12 -706,12 +694,12 @@@ public class SelectStatement implement for (ByteBuffer val : values) { if (val == null) - throw new InvalidRequestException(String.format("Invalid null clustering key part %s", name)); - ColumnNameBuilder copy = builder.copy().add(val); + throw new InvalidRequestException(String.format("Invalid null clustering key part %s", def.name)); + Composite prefix = builder.buildWith(val); // See below for why this - s.add((bound == Bound.END && builder.remainingCount() > 0) ? prefix.end() : prefix); - s.add((b == Bound.END && copy.remainingCount() > 0) ? copy.buildAsEndOfRange() : copy.build()); ++ s.add((b == Bound.END && builder.remainingCount() > 0) ? prefix.end() : prefix); } - return new ArrayList<ByteBuffer>(s); + return new ArrayList<Composite>(s); } ByteBuffer val = values.get(0); @@@ -947,64 -986,70 +947,66 @@@ assert orderingIndexes != null; - // optimization when only *one* order condition was given - // because there is no point of using composite comparator if there is only one order condition - if (parameters.orderings.size() == 1) + List<Integer> idToSort = new ArrayList<Integer>(); + List<Comparator<ByteBuffer>> sorters = new ArrayList<Comparator<ByteBuffer>>(); + + // If the restriction for the last clustering key is an IN, respect requested order + if (lastClusteringIsIn) { - CFDefinition.Name ordering = cfDef.get(parameters.orderings.keySet().iterator().next()); - Collections.sort(cqlRows.rows, new SingleColumnComparator(orderingIndexes.get(ordering), ordering.type)); - return; + List<ColumnDefinition> cc = cfm.clusteringColumns(); + idToSort.add(orderingIndexes.get(cc.get(cc.size() - 1).name)); + Restriction last = columnRestrictions[columnRestrictions.length - 1]; - sorters.add(makeComparatorFor(last.values(variables))); ++ sorters.add(makeComparatorFor(last.values(variables), isReversed)); } - // builds a 'composite' type for multi-column comparison from the comparators of the ordering components - // and passes collected position information and built composite comparator to CompositeComparator to do - // an actual comparison of the CQL rows. - List<AbstractType<?>> types = new ArrayList<AbstractType<?>>(parameters.orderings.size()); - int[] positions = new int[parameters.orderings.size()]; - - int idx = 0; + // Then add the order by for (ColumnIdentifier identifier : parameters.orderings.keySet()) { - CFDefinition.Name orderingColumn = cfDef.get(identifier); - types.add(orderingColumn.type); - positions[idx++] = orderingIndexes.get(orderingColumn); + ColumnDefinition orderingColumn = cfm.getColumnDefinition(identifier); + idToSort.add(orderingIndexes.get(orderingColumn.name)); + sorters.add(orderingColumn.type); } - Collections.sort(cqlRows.rows, new CompositeComparator(types, positions)); + Comparator<List<ByteBuffer>> comparator = idToSort.size() == 1 + ? new SingleColumnComparator(idToSort.get(0), sorters.get(0)) + : new CompositeComparator(sorters, idToSort); + Collections.sort(cqlRows.rows, comparator); } - private void handleGroup(Selection selection, Selection.ResultSetBuilder result, ByteBuffer[] keyComponents, ColumnGroupMap columns) throws InvalidRequestException + // Comparator used when the last clustering key is an IN, to sort result + // rows in the order of the values provided for the IN. - private Comparator<ByteBuffer> makeComparatorFor(final List<ByteBuffer> values) ++ private Comparator<ByteBuffer> makeComparatorFor(final List<ByteBuffer> vals, final boolean isReversed) { - // Respect requested order - result.newRow(); - for (CFDefinition.Name name : selection.getColumnsList()) + // This may not always be the most efficient, but it probably is if + // values is small, which is likely to be the most common case. + return new Comparator<ByteBuffer>() { - switch (name.kind) ++ private final List<ByteBuffer> values = isReversed ? com.google.common.collect.Lists.reverse(vals) : vals; ++ + public int compare(ByteBuffer b1, ByteBuffer b2) { - case KEY_ALIAS: - result.add(keyComponents[name.position]); - break; - case COLUMN_ALIAS: - result.add(columns.getKeyComponent(name.position)); - break; - case VALUE_ALIAS: - // This should not happen for SPARSE - throw new AssertionError(); - case COLUMN_METADATA: - if (name.type.isCollection()) - { - List<Pair<ByteBuffer, Column>> collection = columns.getCollection(name.name.key); - ByteBuffer value = collection == null - ? null - : ((CollectionType)name.type).serialize(collection); - result.add(value); - } - else - { - result.add(columns.getSimple(name.name.key)); - } - break; + int idx1 = -1; + int idx2 = -1; + for (int i = 0; i < values.size(); i++) + { + ByteBuffer bb = values.get(i); + if (bb.equals(b1)) + idx1 = i; + if (bb.equals(b2)) + idx2 = i; + + if (idx1 >= 0 && idx2 >= 0) + break; + } + assert idx1 >= 0 && idx2 >= 0 : "Got CQL3 row that was not queried in resultset"; + return idx1 - idx2; } - } + }; } - private static boolean isReversedType(CFDefinition.Name name) + private static boolean isReversedType(ColumnDefinition def) { - return name.type instanceof ReversedType; + return def.type instanceof ReversedType; } private boolean columnFilterIsIdentity()