You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by be...@apache.org on 2015/09/01 12:57:08 UTC

[2/4] cassandra git commit: Require AbstractType.isByteOrderComparable declaration on construction

Require AbstractType.isByteOrderComparable declaration on construction

Force users with custom implementations of AbstractType to
update their code on upgrade, to warn them of the impending
possibility of future deprecation of non-byte-order comparability

patch by benedict; reviewed by sylvain and ariel for CASSANDRA-9901


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/07594ee0
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/07594ee0
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/07594ee0

Branch: refs/heads/trunk
Commit: 07594ee05e038bdd582b97985f4116227bb416d5
Parents: 704bf1e
Author: Benedict Elliott Smith <be...@apache.org>
Authored: Wed Aug 5 10:56:19 2015 +0100
Committer: Benedict Elliott Smith <be...@apache.org>
Committed: Tue Sep 1 11:56:04 2015 +0100

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../org/apache/cassandra/config/CFMetaData.java |   3 +
 .../cassandra/db/ClusteringComparator.java      |  23 ++---
 .../db/marshal/AbstractCompositeType.java       |   7 +-
 .../cassandra/db/marshal/AbstractType.java      | 102 ++++++++++++++-----
 .../apache/cassandra/db/marshal/AsciiType.java  |  12 +--
 .../cassandra/db/marshal/BooleanType.java       |   4 +-
 .../apache/cassandra/db/marshal/ByteType.java   |   3 +-
 .../apache/cassandra/db/marshal/BytesType.java  |  12 +--
 .../cassandra/db/marshal/CollectionType.java    |   3 +-
 .../db/marshal/ColumnToCollectionType.java      |   3 +-
 .../cassandra/db/marshal/CounterColumnType.java |  12 +--
 .../apache/cassandra/db/marshal/DateType.java   |  15 +--
 .../cassandra/db/marshal/DecimalType.java       |   4 +-
 .../apache/cassandra/db/marshal/DoubleType.java |   4 +-
 .../db/marshal/DynamicCompositeType.java        |   8 +-
 .../apache/cassandra/db/marshal/EmptyType.java  |   4 +-
 .../apache/cassandra/db/marshal/FloatType.java  |   4 +-
 .../apache/cassandra/db/marshal/FrozenType.java |  10 +-
 .../cassandra/db/marshal/InetAddressType.java   |  12 +--
 .../apache/cassandra/db/marshal/Int32Type.java  |   3 +-
 .../cassandra/db/marshal/IntegerType.java       |   4 +-
 .../cassandra/db/marshal/LexicalUUIDType.java   |   3 +-
 .../apache/cassandra/db/marshal/ListType.java   |   4 +-
 .../apache/cassandra/db/marshal/LongType.java   |   4 +-
 .../apache/cassandra/db/marshal/MapType.java    |   9 +-
 .../db/marshal/PartitionerDefinedOrder.java     |   3 +-
 .../cassandra/db/marshal/ReversedType.java      |   3 +-
 .../apache/cassandra/db/marshal/SetType.java    |   9 +-
 .../apache/cassandra/db/marshal/ShortType.java  |   3 +-
 .../cassandra/db/marshal/SimpleDateType.java    |  14 +--
 .../apache/cassandra/db/marshal/TimeType.java   |  13 +--
 .../cassandra/db/marshal/TimeUUIDType.java      |   3 +-
 .../cassandra/db/marshal/TimestampType.java     |   4 +-
 .../apache/cassandra/db/marshal/TupleType.java  |   3 +-
 .../apache/cassandra/db/marshal/UTF8Type.java   |  12 +--
 .../apache/cassandra/db/marshal/UUIDType.java   |   3 +-
 .../org/apache/cassandra/cql3/UDHelperTest.java |   6 +-
 38 files changed, 158 insertions(+), 191 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 390255c..6a0b0b6 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.0-beta2
+ * Require AbstractType.isByteOrderComparable declaration in constructor (CASSANDRA-9901)
  * Avoid digest mismatch on upgrade to 3.0 (CASSANDRA-9554)
  * Fix Materialized View builder when adding multiple MVs (CASSANDRA-10156)
  * Choose better poolingOptions for protocol v4 in cassandra-stress (CASSANDRA-10182)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/config/CFMetaData.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java b/src/java/org/apache/cassandra/config/CFMetaData.java
index be3093d..bcc65b5 100644
--- a/src/java/org/apache/cassandra/config/CFMetaData.java
+++ b/src/java/org/apache/cassandra/config/CFMetaData.java
@@ -293,7 +293,10 @@ public final class CFMetaData
         for (ColumnDefinition def : partitionKeyColumns)
             this.columnMetadata.put(def.name.bytes, def);
         for (ColumnDefinition def : clusteringColumns)
+        {
             this.columnMetadata.put(def.name.bytes, def);
+            def.type.checkComparable();
+        }
         for (ColumnDefinition def : partitionColumns)
             this.columnMetadata.put(def.name.bytes, def);
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/ClusteringComparator.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ClusteringComparator.java b/src/java/org/apache/cassandra/db/ClusteringComparator.java
index a5401f0..f3411cf 100644
--- a/src/java/org/apache/cassandra/db/ClusteringComparator.java
+++ b/src/java/org/apache/cassandra/db/ClusteringComparator.java
@@ -24,11 +24,13 @@ import java.util.List;
 import java.util.Objects;
 
 import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
 
 import org.apache.cassandra.db.rows.Row;
 import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.serializers.MarshalException;
 import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.FastByteOperations;
 
 import static org.apache.cassandra.io.sstable.IndexHelper.IndexInfo;
 
@@ -42,7 +44,6 @@ import static org.apache.cassandra.io.sstable.IndexHelper.IndexInfo;
 public class ClusteringComparator implements Comparator<Clusterable>
 {
     private final List<AbstractType<?>> clusteringTypes;
-    private final boolean isByteOrderComparable;
 
     private final Comparator<IndexInfo> indexComparator;
     private final Comparator<IndexInfo> indexReverseComparator;
@@ -52,25 +53,19 @@ public class ClusteringComparator implements Comparator<Clusterable>
 
     public ClusteringComparator(AbstractType<?>... clusteringTypes)
     {
-        this(Arrays.asList(clusteringTypes));
+        this(ImmutableList.copyOf(clusteringTypes));
     }
 
     public ClusteringComparator(List<AbstractType<?>> clusteringTypes)
     {
-        this.clusteringTypes = clusteringTypes;
-        this.isByteOrderComparable = isByteOrderComparable(clusteringTypes);
+        // copy the list to ensure despatch is monomorphic
+        this.clusteringTypes = ImmutableList.copyOf(clusteringTypes);
 
         this.indexComparator = (o1, o2) -> ClusteringComparator.this.compare(o1.lastName, o2.lastName);
         this.indexReverseComparator = (o1, o2) -> ClusteringComparator.this.compare(o1.firstName, o2.firstName);
         this.reverseComparator = (c1, c2) -> ClusteringComparator.this.compare(c2, c1);
-    }
-
-    private static boolean isByteOrderComparable(Iterable<AbstractType<?>> types)
-    {
-        boolean isByteOrderComparable = true;
-        for (AbstractType<?> type : types)
-            isByteOrderComparable &= type.isByteOrderComparable();
-        return isByteOrderComparable;
+        for (AbstractType<?> type : clusteringTypes)
+            type.checkComparable(); // this should already be enforced by CFMetaData.rebuild, but we check again for other constructors
     }
 
     /**
@@ -168,9 +163,7 @@ public class ClusteringComparator implements Comparator<Clusterable>
         if (v2 == null)
             return 1;
 
-        return isByteOrderComparable
-             ? ByteBufferUtil.compareUnsigned(v1, v2)
-             : clusteringTypes.get(i).compare(v1, v2);
+        return clusteringTypes.get(i).compare(v1, v2);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
index bb2fbf1..ad4050d 100644
--- a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
+++ b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
@@ -36,7 +36,12 @@ import org.apache.cassandra.utils.ByteBufferUtil;
  */
 public abstract class AbstractCompositeType extends AbstractType<ByteBuffer>
 {
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    protected AbstractCompositeType()
+    {
+        super(ComparisonType.CUSTOM);
+    }
+
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         if (!o1.hasRemaining() || !o2.hasRemaining())
             return o1.hasRemaining() ? 1 : o2.hasRemaining() ? -1 : 0;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/AbstractType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/AbstractType.java b/src/java/org/apache/cassandra/db/marshal/AbstractType.java
index 258a8a5..30d9ae9 100644
--- a/src/java/org/apache/cassandra/db/marshal/AbstractType.java
+++ b/src/java/org/apache/cassandra/db/marshal/AbstractType.java
@@ -18,6 +18,7 @@
 package org.apache.cassandra.db.marshal;
 
 import java.io.IOException;
+import java.lang.reflect.Method;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -26,6 +27,9 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import org.apache.cassandra.cql3.CQL3Type;
 import org.apache.cassandra.cql3.Term;
 import org.apache.cassandra.db.TypeSizes;
@@ -33,12 +37,16 @@ import org.apache.cassandra.exceptions.SyntaxException;
 import org.apache.cassandra.serializers.TypeSerializer;
 import org.apache.cassandra.serializers.MarshalException;
 
+import org.apache.cassandra.utils.FastByteOperations;
 import org.github.jamm.Unmetered;
 import org.apache.cassandra.io.util.DataOutputPlus;
 import org.apache.cassandra.io.util.DataInputPlus;
 import org.apache.cassandra.io.util.FileUtils;
 import org.apache.cassandra.utils.ByteBufferUtil;
 
+import static org.apache.cassandra.db.marshal.AbstractType.ComparisonType.CUSTOM;
+import static org.apache.cassandra.db.marshal.AbstractType.ComparisonType.NOT_COMPARABLE;
+
 /**
  * Specifies a Comparator for a specific type of ByteBuffer.
  *
@@ -50,26 +58,47 @@ import org.apache.cassandra.utils.ByteBufferUtil;
 @Unmetered
 public abstract class AbstractType<T> implements Comparator<ByteBuffer>
 {
+    private static final Logger logger = LoggerFactory.getLogger(AbstractType.class);
+
     public final Comparator<ByteBuffer> reverseComparator;
 
-    protected AbstractType()
-    {
-        reverseComparator = new Comparator<ByteBuffer>()
+    public static enum ComparisonType
+    {
+        /**
+         * This type should never be compared
+         */
+        NOT_COMPARABLE,
+        /**
+         * This type is always compared by its sequence of unsigned bytes
+         */
+        BYTE_ORDER,
+        /**
+         * This type can only be compared by calling the type's compareCustom() method, which may be expensive.
+         * Support for this may be removed in a major release of Cassandra, however upgrade facilities will be
+         * provided if and when this happens.
+         */
+        CUSTOM
+    }
+
+    public final ComparisonType comparisonType;
+    public final boolean isByteOrderComparable;
+    protected AbstractType(ComparisonType comparisonType)
+    {
+        this.comparisonType = comparisonType;
+        this.isByteOrderComparable = comparisonType == ComparisonType.BYTE_ORDER;
+        reverseComparator = (o1, o2) -> AbstractType.this.compare(o2, o1);
+        try
         {
-            public int compare(ByteBuffer o1, ByteBuffer o2)
-            {
-                if (o1.remaining() == 0)
-                {
-                    return o2.remaining() == 0 ? 0 : -1;
-                }
-                if (o2.remaining() == 0)
-                {
-                    return 1;
-                }
-
-                return AbstractType.this.compare(o2, o1);
-            }
-        };
+            Method custom = getClass().getMethod("compareCustom", ByteBuffer.class, ByteBuffer.class);
+            if ((custom.getDeclaringClass() == AbstractType.class) == (comparisonType == CUSTOM))
+                throw new IllegalStateException((comparisonType == CUSTOM ? "compareCustom must be overridden if ComparisonType is CUSTOM"
+                                                                         : "compareCustom should not be overridden if ComparisonType is not CUSTOM")
+                                                + " (" + getClass().getSimpleName() + ")");
+        }
+        catch (NoSuchMethodException e)
+        {
+            throw new IllegalStateException();
+        }
     }
 
     public static List<String> asCQLTypeStringList(List<AbstractType<?>> abstractTypes)
@@ -122,6 +151,27 @@ public abstract class AbstractType<T> implements Comparator<ByteBuffer>
         getSerializer().validate(bytes);
     }
 
+    public final int compare(ByteBuffer left, ByteBuffer right)
+    {
+        return isByteOrderComparable
+               ? FastByteOperations.compareUnsigned(left, right)
+               : compareCustom(left, right);
+    }
+
+    /**
+     * Implement IFF ComparisonType is CUSTOM
+     *
+     * Compares the ByteBuffer representation of two instances of this class,
+     * for types where this cannot be done by simple in-order comparison of the
+     * unsigned bytes
+     *
+     * Standard Java compare semantics
+     */
+    public int compareCustom(ByteBuffer left, ByteBuffer right)
+    {
+        throw new UnsupportedOperationException();
+    }
+
     /**
      * Validate cell value. Unlike {@linkplain #validate(java.nio.ByteBuffer)},
      * cell value is passed to validate its content.
@@ -230,15 +280,6 @@ public abstract class AbstractType<T> implements Comparator<ByteBuffer>
     }
 
     /**
-     * @return true IFF the byte representation of this type can be compared unsigned
-     * and always return the same result as calling this object's compare or compareCollectionMembers methods
-     */
-    public boolean isByteOrderComparable()
-    {
-        return false;
-    }
-
-    /**
      * An alternative comparison function used by CollectionsType in conjunction with CompositeType.
      *
      * This comparator is only called to compare components of a CompositeType. It gets the value of the
@@ -366,4 +407,13 @@ public abstract class AbstractType<T> implements Comparator<ByteBuffer>
     {
         return getClass().getName();
     }
+
+    public void checkComparable()
+    {
+        switch (comparisonType)
+        {
+            case NOT_COMPARABLE:
+                throw new IllegalArgumentException(this + " cannot be used in comparisons, so cannot be used as a clustering column");
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/AsciiType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/AsciiType.java b/src/java/org/apache/cassandra/db/marshal/AsciiType.java
index 953fc09..d03fc30 100644
--- a/src/java/org/apache/cassandra/db/marshal/AsciiType.java
+++ b/src/java/org/apache/cassandra/db/marshal/AsciiType.java
@@ -37,7 +37,7 @@ public class AsciiType extends AbstractType<String>
 {
     public static final AsciiType instance = new AsciiType();
 
-    AsciiType() {} // singleton
+    AsciiType() {super(ComparisonType.BYTE_ORDER);} // singleton
 
     private final ThreadLocal<CharsetEncoder> encoder = new ThreadLocal<CharsetEncoder>()
     {
@@ -48,11 +48,6 @@ public class AsciiType extends AbstractType<String>
         }
     };
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
-    {
-        return ByteBufferUtil.compareUnsigned(o1, o2);
-    }
-
     public ByteBuffer fromString(String source)
     {
         // the encoder must be reset each time it's used, hence the thread-local storage
@@ -105,9 +100,4 @@ public class AsciiType extends AbstractType<String>
     {
         return AsciiSerializer.instance;
     }
-
-    public boolean isByteOrderComparable()
-    {
-        return true;
-    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/BooleanType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/BooleanType.java b/src/java/org/apache/cassandra/db/marshal/BooleanType.java
index f87eb12..24d0632 100644
--- a/src/java/org/apache/cassandra/db/marshal/BooleanType.java
+++ b/src/java/org/apache/cassandra/db/marshal/BooleanType.java
@@ -35,14 +35,14 @@ public class BooleanType extends AbstractType<Boolean>
 
     public static final BooleanType instance = new BooleanType();
 
-    BooleanType() {} // singleton
+    BooleanType() {super(ComparisonType.CUSTOM);} // singleton
 
     public boolean isEmptyValueMeaningless()
     {
         return true;
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         if (!o1.hasRemaining() || !o2.hasRemaining())
             return o1.hasRemaining() ? 1 : o2.hasRemaining() ? -1 : 0;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/ByteType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/ByteType.java b/src/java/org/apache/cassandra/db/marshal/ByteType.java
index b63b92e..14699cd 100644
--- a/src/java/org/apache/cassandra/db/marshal/ByteType.java
+++ b/src/java/org/apache/cassandra/db/marshal/ByteType.java
@@ -33,9 +33,10 @@ public class ByteType extends AbstractType<Byte>
 
     ByteType()
     {
+        super(ComparisonType.CUSTOM);
     } // singleton
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         return o1.get(o1.position()) - o2.get(o2.position());
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/BytesType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/BytesType.java b/src/java/org/apache/cassandra/db/marshal/BytesType.java
index eed3872..cec20f4 100644
--- a/src/java/org/apache/cassandra/db/marshal/BytesType.java
+++ b/src/java/org/apache/cassandra/db/marshal/BytesType.java
@@ -32,12 +32,7 @@ public class BytesType extends AbstractType<ByteBuffer>
 {
     public static final BytesType instance = new BytesType();
 
-    BytesType() {} // singleton
-
-    public int compare(ByteBuffer o1, ByteBuffer o2)
-    {
-        return ByteBufferUtil.compareUnsigned(o1, o2);
-    }
+    BytesType() {super(ComparisonType.BYTE_ORDER);} // singleton
 
     public ByteBuffer fromString(String source)
     {
@@ -89,11 +84,6 @@ public class BytesType extends AbstractType<ByteBuffer>
         return true;
     }
 
-    public boolean isByteOrderComparable()
-    {
-        return true;
-    }
-
     public CQL3Type asCQL3Type()
     {
         return CQL3Type.Native.BLOB;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/CollectionType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/CollectionType.java b/src/java/org/apache/cassandra/db/marshal/CollectionType.java
index cc424b9..8992aed 100644
--- a/src/java/org/apache/cassandra/db/marshal/CollectionType.java
+++ b/src/java/org/apache/cassandra/db/marshal/CollectionType.java
@@ -83,8 +83,9 @@ public abstract class CollectionType<T> extends AbstractType<T>
 
     public final Kind kind;
 
-    protected CollectionType(Kind kind)
+    protected CollectionType(ComparisonType comparisonType, Kind kind)
     {
+        super(comparisonType);
         this.kind = kind;
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/ColumnToCollectionType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/ColumnToCollectionType.java b/src/java/org/apache/cassandra/db/marshal/ColumnToCollectionType.java
index a81d3f8..96efa24 100644
--- a/src/java/org/apache/cassandra/db/marshal/ColumnToCollectionType.java
+++ b/src/java/org/apache/cassandra/db/marshal/ColumnToCollectionType.java
@@ -61,10 +61,11 @@ public class ColumnToCollectionType extends AbstractType<ByteBuffer>
 
     private ColumnToCollectionType(Map<ByteBuffer, CollectionType> defined)
     {
+        super(ComparisonType.CUSTOM);
         this.defined = ImmutableMap.copyOf(defined);
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         throw new UnsupportedOperationException("ColumnToCollectionType should only be used in composite types, never alone");
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java b/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java
index 687e525..18ff256 100644
--- a/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java
+++ b/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java
@@ -31,7 +31,7 @@ public class CounterColumnType extends AbstractType<Long>
 {
     public static final CounterColumnType instance = new CounterColumnType();
 
-    CounterColumnType() {} // singleton
+    CounterColumnType() {super(ComparisonType.NOT_COMPARABLE);} // singleton
 
     public boolean isEmptyValueMeaningless()
     {
@@ -43,11 +43,6 @@ public class CounterColumnType extends AbstractType<Long>
         return true;
     }
 
-    public boolean isByteOrderComparable()
-    {
-        throw new AssertionError();
-    }
-
     @Override
     public Long compose(ByteBuffer bytes)
     {
@@ -66,11 +61,6 @@ public class CounterColumnType extends AbstractType<Long>
         CounterContext.instance().validateContext(cellValue);
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
-    {
-        return ByteBufferUtil.compareUnsigned(o1, o2);
-    }
-
     public String getString(ByteBuffer bytes)
     {
         return ByteBufferUtil.bytesToHex(bytes);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/DateType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/DateType.java b/src/java/org/apache/cassandra/db/marshal/DateType.java
index 66da443..6643da4 100644
--- a/src/java/org/apache/cassandra/db/marshal/DateType.java
+++ b/src/java/org/apache/cassandra/db/marshal/DateType.java
@@ -37,21 +37,13 @@ public class DateType extends AbstractType<Date>
 
     public static final DateType instance = new DateType();
 
-    DateType() {} // singleton
+    DateType() {super(ComparisonType.BYTE_ORDER);} // singleton
 
     public boolean isEmptyValueMeaningless()
     {
         return true;
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
-    {
-        if (!o1.hasRemaining() || !o2.hasRemaining())
-            return o1.hasRemaining() ? 1 : o2.hasRemaining() ? -1 : 0;
-
-        return ByteBufferUtil.compareUnsigned(o1, o2);
-    }
-
     public ByteBuffer fromString(String source) throws MarshalException
     {
       // Return an empty ByteBuffer for an empty string.
@@ -103,11 +95,6 @@ public class DateType extends AbstractType<Date>
         return false;
     }
 
-    public boolean isByteOrderComparable()
-    {
-        return true;
-    }
-
     @Override
     public boolean isValueCompatibleWithInternal(AbstractType<?> otherType)
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/DecimalType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/DecimalType.java b/src/java/org/apache/cassandra/db/marshal/DecimalType.java
index 4052d70..17d91d3 100644
--- a/src/java/org/apache/cassandra/db/marshal/DecimalType.java
+++ b/src/java/org/apache/cassandra/db/marshal/DecimalType.java
@@ -32,14 +32,14 @@ public class DecimalType extends AbstractType<BigDecimal>
 {
     public static final DecimalType instance = new DecimalType();
 
-    DecimalType() {} // singleton
+    DecimalType() {super(ComparisonType.CUSTOM);} // singleton
 
     public boolean isEmptyValueMeaningless()
     {
         return true;
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         if (!o1.hasRemaining() || !o2.hasRemaining())
             return o1.hasRemaining() ? 1 : o2.hasRemaining() ? -1 : 0;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/DoubleType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/DoubleType.java b/src/java/org/apache/cassandra/db/marshal/DoubleType.java
index bc160d5..a84bdec 100644
--- a/src/java/org/apache/cassandra/db/marshal/DoubleType.java
+++ b/src/java/org/apache/cassandra/db/marshal/DoubleType.java
@@ -31,14 +31,14 @@ public class DoubleType extends AbstractType<Double>
 {
     public static final DoubleType instance = new DoubleType();
 
-    DoubleType() {} // singleton
+    DoubleType() {super(ComparisonType.CUSTOM);} // singleton
 
     public boolean isEmptyValueMeaningless()
     {
         return true;
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         if (!o1.hasRemaining() || !o2.hasRemaining())
             return o1.hasRemaining() ? 1 : o2.hasRemaining() ? -1 : 0;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/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 97d145d..657f126 100644
--- a/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java
+++ b/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java
@@ -343,10 +343,11 @@ public class DynamicCompositeType extends AbstractCompositeType
 
         public FixedValueComparator(int cmp)
         {
+            super(ComparisonType.CUSTOM);
             this.cmp = cmp;
         }
 
-        public int compare(ByteBuffer v1, ByteBuffer v2)
+        public int compareCustom(ByteBuffer v1, ByteBuffer v2)
         {
             return cmp;
         }
@@ -395,10 +396,5 @@ public class DynamicCompositeType extends AbstractCompositeType
         {
             throw new UnsupportedOperationException();
         }
-
-        public boolean isByteOrderComparable()
-        {
-            return false;
-        }
     }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/EmptyType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/EmptyType.java b/src/java/org/apache/cassandra/db/marshal/EmptyType.java
index 448376f..9cd7226 100644
--- a/src/java/org/apache/cassandra/db/marshal/EmptyType.java
+++ b/src/java/org/apache/cassandra/db/marshal/EmptyType.java
@@ -34,9 +34,9 @@ public class EmptyType extends AbstractType<Void>
 {
     public static final EmptyType instance = new EmptyType();
 
-    private EmptyType() {} // singleton
+    private EmptyType() {super(ComparisonType.CUSTOM);} // singleton
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         return 0;
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/FloatType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/FloatType.java b/src/java/org/apache/cassandra/db/marshal/FloatType.java
index ceedce4..86164b0 100644
--- a/src/java/org/apache/cassandra/db/marshal/FloatType.java
+++ b/src/java/org/apache/cassandra/db/marshal/FloatType.java
@@ -32,14 +32,14 @@ public class FloatType extends AbstractType<Float>
 {
     public static final FloatType instance = new FloatType();
 
-    FloatType() {} // singleton
+    FloatType() {super(ComparisonType.CUSTOM);} // singleton
 
     public boolean isEmptyValueMeaningless()
     {
         return true;
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         if (!o1.hasRemaining() || !o2.hasRemaining())
             return o1.hasRemaining() ? 1 : o2.hasRemaining() ? -1 : 0;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/FrozenType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/FrozenType.java b/src/java/org/apache/cassandra/db/marshal/FrozenType.java
index 7713028..261e789 100644
--- a/src/java/org/apache/cassandra/db/marshal/FrozenType.java
+++ b/src/java/org/apache/cassandra/db/marshal/FrozenType.java
@@ -31,6 +31,11 @@ import org.apache.cassandra.serializers.MarshalException;
  */
 public class FrozenType extends AbstractType<Void>
 {
+    protected FrozenType()
+    {
+        super(ComparisonType.NOT_COMPARABLE);
+    }
+
     public static AbstractType<?> getInstance(TypeParser parser) throws ConfigurationException, SyntaxException
     {
         List<AbstractType<?>> innerTypes = parser.getTypeParameters();
@@ -41,11 +46,6 @@ public class FrozenType extends AbstractType<Void>
         return innerType.freeze();
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
-    {
-        throw new UnsupportedOperationException();
-    }
-
     public String getString(ByteBuffer bytes)
     {
         throw new UnsupportedOperationException();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/InetAddressType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/InetAddressType.java b/src/java/org/apache/cassandra/db/marshal/InetAddressType.java
index 4901c74..7ffb9c7 100644
--- a/src/java/org/apache/cassandra/db/marshal/InetAddressType.java
+++ b/src/java/org/apache/cassandra/db/marshal/InetAddressType.java
@@ -32,18 +32,13 @@ public class InetAddressType extends AbstractType<InetAddress>
 {
     public static final InetAddressType instance = new InetAddressType();
 
-    InetAddressType() {} // singleton
+    InetAddressType() {super(ComparisonType.BYTE_ORDER);} // singleton
 
     public boolean isEmptyValueMeaningless()
     {
         return true;
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
-    {
-        return ByteBufferUtil.compareUnsigned(o1, o2);
-    }
-
     public ByteBuffer fromString(String source) throws MarshalException
     {
         // Return an empty ByteBuffer for an empty string.
@@ -93,9 +88,4 @@ public class InetAddressType extends AbstractType<InetAddress>
     {
         return InetAddressSerializer.instance;
     }
-
-    public boolean isByteOrderComparable()
-    {
-        return true;
-    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/Int32Type.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/Int32Type.java b/src/java/org/apache/cassandra/db/marshal/Int32Type.java
index cb0c584..770a76d 100644
--- a/src/java/org/apache/cassandra/db/marshal/Int32Type.java
+++ b/src/java/org/apache/cassandra/db/marshal/Int32Type.java
@@ -33,6 +33,7 @@ public class Int32Type extends AbstractType<Integer>
 
     Int32Type()
     {
+        super(ComparisonType.CUSTOM);
     } // singleton
 
     public boolean isEmptyValueMeaningless()
@@ -40,7 +41,7 @@ public class Int32Type extends AbstractType<Integer>
         return true;
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         if (!o1.hasRemaining() || !o2.hasRemaining())
             return o1.hasRemaining() ? 1 : o2.hasRemaining() ? -1 : 0;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/IntegerType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/IntegerType.java b/src/java/org/apache/cassandra/db/marshal/IntegerType.java
index a3741d4..8f4ba44 100644
--- a/src/java/org/apache/cassandra/db/marshal/IntegerType.java
+++ b/src/java/org/apache/cassandra/db/marshal/IntegerType.java
@@ -58,14 +58,14 @@ public final class IntegerType extends AbstractType<BigInteger>
         return i;
     }
 
-    IntegerType() {/* singleton */}
+    IntegerType() {super(ComparisonType.CUSTOM);}/* singleton */
 
     public boolean isEmptyValueMeaningless()
     {
         return true;
     }
 
-    public int compare(ByteBuffer lhs, ByteBuffer rhs)
+    public int compareCustom(ByteBuffer lhs, ByteBuffer rhs)
     {
         return IntegerType.compareIntegers(lhs, rhs);
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java b/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java
index 174ce3a..70767d4 100644
--- a/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java
+++ b/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java
@@ -34,6 +34,7 @@ public class LexicalUUIDType extends AbstractType<UUID>
 
     LexicalUUIDType()
     {
+        super(ComparisonType.CUSTOM);
     } // singleton
 
     public boolean isEmptyValueMeaningless()
@@ -41,7 +42,7 @@ public class LexicalUUIDType extends AbstractType<UUID>
         return true;
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         if (!o1.hasRemaining() || !o2.hasRemaining())
             return o1.hasRemaining() ? 1 : o2.hasRemaining() ? -1 : 0;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/ListType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/ListType.java b/src/java/org/apache/cassandra/db/marshal/ListType.java
index 73af808..4b1158e 100644
--- a/src/java/org/apache/cassandra/db/marshal/ListType.java
+++ b/src/java/org/apache/cassandra/db/marshal/ListType.java
@@ -68,7 +68,7 @@ public class ListType<T> extends CollectionType<List<T>>
 
     private ListType(AbstractType<T> elements, boolean isMultiCell)
     {
-        super(Kind.LIST);
+        super(ComparisonType.CUSTOM, Kind.LIST);
         this.elements = elements;
         this.serializer = ListSerializer.getInstance(elements.getSerializer());
         this.isMultiCell = isMultiCell;
@@ -124,7 +124,7 @@ public class ListType<T> extends CollectionType<List<T>>
     }
 
     @Override
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         return compareListOrSet(elements, o1, o2);
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/LongType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/LongType.java b/src/java/org/apache/cassandra/db/marshal/LongType.java
index 9d41f4f..8a1528a 100644
--- a/src/java/org/apache/cassandra/db/marshal/LongType.java
+++ b/src/java/org/apache/cassandra/db/marshal/LongType.java
@@ -31,14 +31,14 @@ public class LongType extends AbstractType<Long>
 {
     public static final LongType instance = new LongType();
 
-    LongType() {} // singleton
+    LongType() {super(ComparisonType.CUSTOM);} // singleton
 
     public boolean isEmptyValueMeaningless()
     {
         return true;
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         return compareLongs(o1, o2);
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/MapType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/MapType.java b/src/java/org/apache/cassandra/db/marshal/MapType.java
index b1440a5..3d6bf22 100644
--- a/src/java/org/apache/cassandra/db/marshal/MapType.java
+++ b/src/java/org/apache/cassandra/db/marshal/MapType.java
@@ -67,7 +67,7 @@ public class MapType<K, V> extends CollectionType<Map<K, V>>
 
     private MapType(AbstractType<K> keys, AbstractType<V> values, boolean isMultiCell)
     {
-        super(Kind.MAP);
+        super(ComparisonType.CUSTOM, Kind.MAP);
         this.keys = keys;
         this.values = values;
         this.serializer = MapSerializer.getInstance(keys.getSerializer(), values.getSerializer(), keys);
@@ -126,7 +126,7 @@ public class MapType<K, V> extends CollectionType<Map<K, V>>
     }
 
     @Override
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         return compareMaps(keys, values, o1, o2);
     }
@@ -167,11 +167,6 @@ public class MapType<K, V> extends CollectionType<Map<K, V>>
         return serializer;
     }
 
-    public boolean isByteOrderComparable()
-    {
-        return keys.isByteOrderComparable();
-    }
-
     @Override
     protected int collectionSize(List<ByteBuffer> values)
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/PartitionerDefinedOrder.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/PartitionerDefinedOrder.java b/src/java/org/apache/cassandra/db/marshal/PartitionerDefinedOrder.java
index 88f9906..02f01ae 100644
--- a/src/java/org/apache/cassandra/db/marshal/PartitionerDefinedOrder.java
+++ b/src/java/org/apache/cassandra/db/marshal/PartitionerDefinedOrder.java
@@ -37,6 +37,7 @@ public class PartitionerDefinedOrder extends AbstractType<ByteBuffer>
 
     public PartitionerDefinedOrder(IPartitioner partitioner)
     {
+        super(ComparisonType.CUSTOM);
         this.partitioner = partitioner;
     }
 
@@ -86,7 +87,7 @@ public class PartitionerDefinedOrder extends AbstractType<ByteBuffer>
         throw new UnsupportedOperationException();
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         // o1 and o2 can be empty so we need to use PartitionPosition, not DecoratedKey
         return PartitionPosition.ForKey.get(o1, partitioner).compareTo(PartitionPosition.ForKey.get(o2, partitioner));

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/ReversedType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/ReversedType.java b/src/java/org/apache/cassandra/db/marshal/ReversedType.java
index cf357a8..2e01d9b 100644
--- a/src/java/org/apache/cassandra/db/marshal/ReversedType.java
+++ b/src/java/org/apache/cassandra/db/marshal/ReversedType.java
@@ -57,6 +57,7 @@ public class ReversedType<T> extends AbstractType<T>
 
     private ReversedType(AbstractType<T> baseType)
     {
+        super(ComparisonType.CUSTOM);
         this.baseType = baseType;
     }
 
@@ -65,7 +66,7 @@ public class ReversedType<T> extends AbstractType<T>
         return baseType.isEmptyValueMeaningless();
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         // An empty byte buffer is always smaller
         if (o1.remaining() == 0)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/SetType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/SetType.java b/src/java/org/apache/cassandra/db/marshal/SetType.java
index 7e94fcb..2fd4960 100644
--- a/src/java/org/apache/cassandra/db/marshal/SetType.java
+++ b/src/java/org/apache/cassandra/db/marshal/SetType.java
@@ -62,7 +62,7 @@ public class SetType<T> extends CollectionType<Set<T>>
 
     public SetType(AbstractType<T> elements, boolean isMultiCell)
     {
-        super(Kind.SET);
+        super(ComparisonType.CUSTOM, Kind.SET);
         this.elements = elements;
         this.serializer = SetSerializer.getInstance(elements.getSerializer(), elements);
         this.isMultiCell = isMultiCell;
@@ -113,7 +113,7 @@ public class SetType<T> extends CollectionType<Set<T>>
     }
 
     @Override
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         return ListType.compareListOrSet(elements, o1, o2);
     }
@@ -123,11 +123,6 @@ public class SetType<T> extends CollectionType<Set<T>>
         return serializer;
     }
 
-    public boolean isByteOrderComparable()
-    {
-        return elements.isByteOrderComparable();
-    }
-
     @Override
     public String toString(boolean ignoreFreezing)
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/ShortType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/ShortType.java b/src/java/org/apache/cassandra/db/marshal/ShortType.java
index 43e8f5e..15618b8 100644
--- a/src/java/org/apache/cassandra/db/marshal/ShortType.java
+++ b/src/java/org/apache/cassandra/db/marshal/ShortType.java
@@ -33,9 +33,10 @@ public class ShortType extends AbstractType<Short>
 
     ShortType()
     {
+        super(ComparisonType.CUSTOM);
     } // singleton
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         int diff = o1.get(o1.position()) - o2.get(o2.position());
         if (diff != 0)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/SimpleDateType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/SimpleDateType.java b/src/java/org/apache/cassandra/db/marshal/SimpleDateType.java
index 747709e..dbfac9e 100644
--- a/src/java/org/apache/cassandra/db/marshal/SimpleDateType.java
+++ b/src/java/org/apache/cassandra/db/marshal/SimpleDateType.java
@@ -31,19 +31,7 @@ public class SimpleDateType extends AbstractType<Integer>
 {
     public static final SimpleDateType instance = new SimpleDateType();
 
-    SimpleDateType() {} // singleton
-
-    public int compare(ByteBuffer o1, ByteBuffer o2)
-    {
-        // We add Integer.MIN_VALUE to overflow to allow unsigned comparison
-        return ByteBufferUtil.compareUnsigned(o1, o2);
-    }
-
-    @Override
-    public boolean isByteOrderComparable()
-    {
-        return true;
-    }
+    SimpleDateType() {super(ComparisonType.BYTE_ORDER);} // singleton
 
     public ByteBuffer fromString(String source) throws MarshalException
     {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/TimeType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/TimeType.java b/src/java/org/apache/cassandra/db/marshal/TimeType.java
index c241a38..780b020 100644
--- a/src/java/org/apache/cassandra/db/marshal/TimeType.java
+++ b/src/java/org/apache/cassandra/db/marshal/TimeType.java
@@ -33,12 +33,7 @@ import org.apache.cassandra.utils.ByteBufferUtil;
 public class TimeType extends AbstractType<Long>
 {
     public static final TimeType instance = new TimeType();
-    private TimeType() {} // singleton
-
-    public int compare(ByteBuffer o1, ByteBuffer o2)
-    {
-        return ByteBufferUtil.compareUnsigned(o1, o2);
-    }
+    private TimeType() {super(ComparisonType.BYTE_ORDER);} // singleton
 
     public ByteBuffer fromString(String source) throws MarshalException
     {
@@ -46,12 +41,6 @@ public class TimeType extends AbstractType<Long>
     }
 
     @Override
-    public boolean isByteOrderComparable()
-    {
-        return true;
-    }
-
-    @Override
     public boolean isCompatibleWith(AbstractType<?> previous)
     {
         return super.isCompatibleWith(previous);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java b/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java
index 64fa750..36305a3 100644
--- a/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java
+++ b/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java
@@ -33,6 +33,7 @@ public class TimeUUIDType extends AbstractType<UUID>
 
     TimeUUIDType()
     {
+        super(ComparisonType.CUSTOM);
     } // singleton
 
     public boolean isEmptyValueMeaningless()
@@ -40,7 +41,7 @@ public class TimeUUIDType extends AbstractType<UUID>
         return true;
     }
 
-    public int compare(ByteBuffer b1, ByteBuffer b2)
+    public int compareCustom(ByteBuffer b1, ByteBuffer b2)
     {
         // Compare for length
         int s1 = b1.position(), s2 = b2.position();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/TimestampType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/TimestampType.java b/src/java/org/apache/cassandra/db/marshal/TimestampType.java
index 288f8fd..ebaff42 100644
--- a/src/java/org/apache/cassandra/db/marshal/TimestampType.java
+++ b/src/java/org/apache/cassandra/db/marshal/TimestampType.java
@@ -43,14 +43,14 @@ public class TimestampType extends AbstractType<Date>
 
     public static final TimestampType instance = new TimestampType();
 
-    private TimestampType() {} // singleton
+    private TimestampType() {super(ComparisonType.CUSTOM);} // singleton
 
     public boolean isEmptyValueMeaningless()
     {
         return true;
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         return LongType.compareLongs(o1, o2);
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/TupleType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/TupleType.java b/src/java/org/apache/cassandra/db/marshal/TupleType.java
index 688e173..7a98074 100644
--- a/src/java/org/apache/cassandra/db/marshal/TupleType.java
+++ b/src/java/org/apache/cassandra/db/marshal/TupleType.java
@@ -41,6 +41,7 @@ public class TupleType extends AbstractType<ByteBuffer>
 
     public TupleType(List<AbstractType<?>> types)
     {
+        super(ComparisonType.CUSTOM);
         for (int i = 0; i < types.size(); i++)
             types.set(i, types.get(i).freeze());
         this.types = types;
@@ -69,7 +70,7 @@ public class TupleType extends AbstractType<ByteBuffer>
         return types;
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
+    public int compareCustom(ByteBuffer o1, ByteBuffer o2)
     {
         if (!o1.hasRemaining() || !o2.hasRemaining())
             return o1.hasRemaining() ? 1 : o2.hasRemaining() ? -1 : 0;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/UTF8Type.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/UTF8Type.java b/src/java/org/apache/cassandra/db/marshal/UTF8Type.java
index 3fd175c..0778b04 100644
--- a/src/java/org/apache/cassandra/db/marshal/UTF8Type.java
+++ b/src/java/org/apache/cassandra/db/marshal/UTF8Type.java
@@ -35,12 +35,7 @@ public class UTF8Type extends AbstractType<String>
 {
     public static final UTF8Type instance = new UTF8Type();
 
-    UTF8Type() {} // singleton
-
-    public int compare(ByteBuffer o1, ByteBuffer o2)
-    {
-        return ByteBufferUtil.compareUnsigned(o1, o2);
-    }
+    UTF8Type() {super(ComparisonType.BYTE_ORDER);} // singleton
 
     public ByteBuffer fromString(String source)
     {
@@ -83,11 +78,6 @@ public class UTF8Type extends AbstractType<String>
         return this == previous || previous == AsciiType.instance;
     }
 
-    public boolean isByteOrderComparable()
-    {
-        return true;
-    }
-
     public CQL3Type asCQL3Type()
     {
         return CQL3Type.Native.TEXT;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/src/java/org/apache/cassandra/db/marshal/UUIDType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/UUIDType.java b/src/java/org/apache/cassandra/db/marshal/UUIDType.java
index 14c9f48..acaf27c 100644
--- a/src/java/org/apache/cassandra/db/marshal/UUIDType.java
+++ b/src/java/org/apache/cassandra/db/marshal/UUIDType.java
@@ -48,6 +48,7 @@ public class UUIDType extends AbstractType<UUID>
 
     UUIDType()
     {
+        super(ComparisonType.CUSTOM);
     }
 
     public boolean isEmptyValueMeaningless()
@@ -55,7 +56,7 @@ public class UUIDType extends AbstractType<UUID>
         return true;
     }
 
-    public int compare(ByteBuffer b1, ByteBuffer b2)
+    public int compareCustom(ByteBuffer b1, ByteBuffer b2)
     {
         // Compare for length
         int s1 = b1.position(), s2 = b2.position();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/07594ee0/test/unit/org/apache/cassandra/cql3/UDHelperTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/UDHelperTest.java b/test/unit/org/apache/cassandra/cql3/UDHelperTest.java
index 4a5e78e..288cd86 100644
--- a/test/unit/org/apache/cassandra/cql3/UDHelperTest.java
+++ b/test/unit/org/apache/cassandra/cql3/UDHelperTest.java
@@ -54,6 +54,10 @@ public class UDHelperTest
 {
     static class UFTestCustomType extends AbstractType<String>
     {
+        protected UFTestCustomType()
+        {
+            super(ComparisonType.CUSTOM);
+        }
 
         public ByteBuffer fromString(String source) throws MarshalException
         {
@@ -70,7 +74,7 @@ public class UDHelperTest
             return UTF8Type.instance.getSerializer();
         }
 
-        public int compare(ByteBuffer o1, ByteBuffer o2)
+        public int compareCustom(ByteBuffer o1, ByteBuffer o2)
         {
             return o1.compareTo(o2);
         }