Allow DynamicCompositeType to compare components of different types patch by slebresne; reviewed by edanuff for CASSANDRA-3625
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/6a1ed620 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/6a1ed620 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/6a1ed620 Branch: refs/heads/trunk Commit: 6a1ed6205cad8d019eb6eda326d7796a8a0dd67b Parents: f2cb272 Author: Sylvain Lebresne <sylv...@datastax.com> Authored: Fri Jan 13 08:49:21 2012 +0100 Committer: Sylvain Lebresne <sylv...@datastax.com> Committed: Fri Jan 13 08:49:21 2012 +0100 ---------------------------------------------------------------------- CHANGES.txt | 2 + .../cassandra/db/marshal/DynamicCompositeType.java | 54 ++++++++++++++- .../db/marshal/DynamicCompositeTypeTest.java | 28 ++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/6a1ed620/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 39211a4..30c002d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -26,6 +26,8 @@ * Improve stream protocol mismatch errors (CASSANDRA-3652) * Avoid multiple thread doing HH to the same target (CASSANDRA-3681) * Add JMX property for rp_timeout_in_ms (CASSANDRA-2940) + * Allow DynamicCompositeType to compare component of different types + (CASSANDRA-3625) Merged from 0.8: * avoid logging (harmless) exception when GC takes < 1ms (CASSANDRA-3656) * prevent new nodes from thinking down nodes are up forever (CASSANDRA-3626) http://git-wip-us.apache.org/repos/asf/cassandra/blob/6a1ed620/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java b/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java index 592f392..53e10d3 100644 --- a/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java +++ b/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java @@ -117,11 +117,25 @@ public class DynamicCompositeType extends AbstractCompositeType AbstractType comp1 = getComparator(bb1); AbstractType comp2 = getComparator(bb2); - // This rely on comparator always being singleton instances + // Fast test if the comparator uses singleton instances if (comp1 != comp2) { - logger.error("Mismatch between {} and {}", comp1, comp2); - throw new RuntimeException("Comparator mismatch while comparing two DynamicCompositeType colum name"); + /* + * We compare component of different types by comparing the + * comparator class names. We start with the simple classname + * first because that will be faster in almost all cases, but + * allback on the full name if necessary + */ + int cmp = comp1.getClass().getSimpleName().compareTo(comp2.getClass().getSimpleName()); + if (cmp != 0) + return cmp < 0 ? FixedValueComparator.instance : ReversedType.getInstance(FixedValueComparator.instance); + + cmp = comp1.getClass().getName().compareTo(comp2.getClass().getName()); + if (cmp != 0) + return cmp < 0 ? FixedValueComparator.instance : ReversedType.getInstance(FixedValueComparator.instance); + + // if cmp == 0, we're actually having the same type, but one that + // did not have a singleton instance. It's ok (though inefficient). } return comp1; } @@ -263,4 +277,38 @@ public class DynamicCompositeType extends AbstractCompositeType { return getClass().getName() + TypeParser.stringifyAliasesParameters(aliases); } + + /* + * A comparator that always sorts it's first argument before the second + * one. + */ + private static class FixedValueComparator extends AbstractType<Void> + { + public static final FixedValueComparator instance = new FixedValueComparator(); + + public int compare(ByteBuffer v1, ByteBuffer v2) + { + return -1; + } + + public Void compose(ByteBuffer bytes) + { + throw new UnsupportedOperationException(); + } + + public ByteBuffer decompose(Void value) + { + throw new UnsupportedOperationException(); + } + + public String getString(ByteBuffer bytes) + { + throw new UnsupportedOperationException(); + } + + public void validate(ByteBuffer bytes) + { + throw new UnsupportedOperationException(); + } + } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/6a1ed620/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java b/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java index 100c50e..e453705 100644 --- a/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java +++ b/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java @@ -192,6 +192,34 @@ public class DynamicCompositeTypeTest extends CleanupHelper assert iter.next().name().equals(cname5); } + @Test + public void testUncomparableColumns() + { + ByteBuffer bytes = ByteBuffer.allocate(2 + 2 + 4 + 1); + bytes.putShort((short)(0x8000 | 'b')); + bytes.putShort((short) 4); + bytes.put(new byte[4]); + bytes.put((byte) 0); + bytes.rewind(); + + ByteBuffer uuid = ByteBuffer.allocate(2 + 2 + 16 + 1); + uuid.putShort((short)(0x8000 | 't')); + uuid.putShort((short) 16); + uuid.put(UUIDGen.decompose(uuids[0])); + uuid.put((byte) 0); + uuid.rewind(); + + try + { + int c = comparator.compare(bytes, uuid); + assert c == -1 : "Expecting bytes to sort before uuid, but got " + c; + } + catch (Exception e) + { + fail("Shouldn't throw exception"); + } + } + private void addColumn(RowMutation rm, ByteBuffer cname) { rm.add(new QueryPath(cfName, null , cname), ByteBufferUtil.EMPTY_BYTE_BUFFER, 0);