You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sl...@apache.org on 2013/12/17 17:03:48 UTC

[12/13] Push composites support in the storage engine

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql/QueryProcessor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/QueryProcessor.java b/src/java/org/apache/cassandra/cql/QueryProcessor.java
index 87f603e..12a0c22 100644
--- a/src/java/org/apache/cassandra/cql/QueryProcessor.java
+++ b/src/java/org/apache/cassandra/cql/QueryProcessor.java
@@ -35,6 +35,9 @@ import org.apache.cassandra.cql.hooks.PreExecutionHook;
 import org.apache.cassandra.cql.hooks.PreparationContext;
 import org.apache.cassandra.db.CounterColumn;
 import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.composites.CellName;
+import org.apache.cassandra.db.composites.CellNameType;
+import org.apache.cassandra.db.composites.Composite;
 import org.apache.cassandra.db.context.CounterContext;
 import org.apache.cassandra.db.filter.*;
 import org.apache.cassandra.db.index.SecondaryIndexManager;
@@ -103,7 +106,7 @@ public class QueryProcessor
         // ...of a list of column names
         if (!select.isColumnRange())
         {
-            SortedSet<ByteBuffer> columnNames = getColumnNames(select, metadata, variables);
+            SortedSet<CellName> columnNames = getColumnNames(select, metadata, variables);
             validateColumnNames(columnNames);
 
             for (Term rawKey: select.getKeys())
@@ -117,9 +120,9 @@ public class QueryProcessor
         // ...a range (slice) of column names
         else
         {
-            AbstractType<?> comparator = metadata.comparator;
-            ByteBuffer start = select.getColumnStart().getByteBuffer(comparator,variables);
-            ByteBuffer finish = select.getColumnFinish().getByteBuffer(comparator,variables);
+            AbstractType<?> at = metadata.comparator.asAbstractType();
+            Composite start = metadata.comparator.fromByteBuffer(select.getColumnStart().getByteBuffer(at,variables));
+            Composite finish = metadata.comparator.fromByteBuffer(select.getColumnFinish().getByteBuffer(at,variables));
 
             for (Term rawKey : select.getKeys())
             {
@@ -138,17 +141,17 @@ public class QueryProcessor
         return StorageProxy.read(commands, select.getConsistencyLevel());
     }
 
-    private static SortedSet<ByteBuffer> getColumnNames(SelectStatement select, CFMetaData metadata, List<ByteBuffer> variables)
+    private static SortedSet<CellName> getColumnNames(SelectStatement select, CFMetaData metadata, List<ByteBuffer> variables)
     throws InvalidRequestException
     {
         String keyString = metadata.getCQL2KeyName();
         List<Term> selectColumnNames = select.getColumnNames();
-        SortedSet<ByteBuffer> columnNames = new TreeSet<ByteBuffer>(metadata.comparator);
+        SortedSet<CellName> columnNames = new TreeSet<>(metadata.comparator);
         for (Term column : selectColumnNames)
         {
             // skip the key for the slice op; we'll add it to the resultset in extractThriftColumns
             if (!column.getText().equalsIgnoreCase(keyString))
-                columnNames.add(column.getByteBuffer(metadata.comparator,variables));
+                columnNames.add(metadata.comparator.cellFromByteBuffer(column.getByteBuffer(metadata.comparator.asAbstractType(),variables)));
         }
         return columnNames;
     }
@@ -186,8 +189,8 @@ public class QueryProcessor
         for (Relation columnRelation : columnRelations)
         {
             // Left and right side of relational expression encoded according to comparator/validator.
-            ByteBuffer entity = columnRelation.getEntity().getByteBuffer(metadata.comparator, variables);
-            ByteBuffer value = columnRelation.getValue().getByteBuffer(metadata.getValueValidatorFromCellName(entity), variables);
+            ByteBuffer entity = columnRelation.getEntity().getByteBuffer(metadata.comparator.asAbstractType(), variables);
+            ByteBuffer value = columnRelation.getValue().getByteBuffer(metadata.getValueValidatorForFullCellName(entity), variables);
 
             expressions.add(new IndexExpression(entity,
                                                 IndexExpression.Operator.valueOf(columnRelation.operator().toString()),
@@ -230,8 +233,9 @@ public class QueryProcessor
     {
         if (select.isColumnRange() || select.getColumnNames().size() == 0)
         {
-            return new SliceQueryFilter(select.getColumnStart().getByteBuffer(metadata.comparator, variables),
-                                        select.getColumnFinish().getByteBuffer(metadata.comparator, variables),
+            AbstractType<?> comparator = metadata.comparator.asAbstractType();
+            return new SliceQueryFilter(metadata.comparator.fromByteBuffer(select.getColumnStart().getByteBuffer(comparator, variables)),
+                                        metadata.comparator.fromByteBuffer(select.getColumnFinish().getByteBuffer(comparator, variables)),
                                         select.isColumnsReversed(),
                                         select.getColumnsLimit());
         }
@@ -265,12 +269,13 @@ public class QueryProcessor
         if (select.getColumnRelations().size() > 0)
         {
             ColumnFamilyStore cfstore = Keyspace.open(keyspace).getColumnFamilyStore(select.getColumnFamily());
-            AbstractType<?> comparator = cfstore.metadata.comparator;
+            CellNameType comparator = cfstore.metadata.comparator;
+            AbstractType<?> at = comparator.asAbstractType();
             SecondaryIndexManager idxManager = cfstore.indexManager;
             for (Relation relation : select.getColumnRelations())
             {
-                ByteBuffer name = relation.getEntity().getByteBuffer(comparator, variables);
-                if ((relation.operator() == RelationType.EQ) && idxManager.indexes(name))
+                ByteBuffer name = relation.getEntity().getByteBuffer(at, variables);
+                if ((relation.operator() == RelationType.EQ) && idxManager.indexes(comparator.cellFromByteBuffer(name)))
                     return;
             }
             throw new InvalidRequestException("No indexed columns present in by-columns clause with \"equals\" operator");
@@ -300,31 +305,31 @@ public class QueryProcessor
             throw new InvalidRequestException(String.format("Expected key '%s' to be present in WHERE clause for '%s'", realKeyAlias, cfm.cfName));
     }
 
-    private static void validateColumnNames(Iterable<ByteBuffer> columns)
+    private static void validateColumnNames(Iterable<CellName> columns)
     throws InvalidRequestException
     {
-        for (ByteBuffer name : columns)
+        for (CellName name : columns)
         {
-            if (name.remaining() > org.apache.cassandra.db.Column.MAX_NAME_LENGTH)
+            if (name.dataSize() > org.apache.cassandra.db.Column.MAX_NAME_LENGTH)
                 throw new InvalidRequestException(String.format("column name is too long (%s > %s)",
-                                                                name.remaining(),
+                                                                name.dataSize(),
                                                                 org.apache.cassandra.db.Column.MAX_NAME_LENGTH));
-            if (name.remaining() == 0)
+            if (name.isEmpty())
                 throw new InvalidRequestException("zero-length column name");
         }
     }
 
-    public static void validateColumnName(ByteBuffer column)
+    public static void validateColumnName(CellName column)
     throws InvalidRequestException
     {
         validateColumnNames(Arrays.asList(column));
     }
 
-    public static void validateColumn(CFMetaData metadata, ByteBuffer name, ByteBuffer value)
+    public static void validateColumn(CFMetaData metadata, CellName name, ByteBuffer value)
     throws InvalidRequestException
     {
         validateColumnName(name);
-        AbstractType<?> validator = metadata.getValueValidatorFromCellName(name);
+        AbstractType<?> validator = metadata.getValueValidator(name);
 
         try
         {
@@ -334,7 +339,7 @@ public class QueryProcessor
         catch (MarshalException me)
         {
             throw new InvalidRequestException(String.format("Invalid column value for column (name=%s); %s",
-                                                            ByteBufferUtil.bytesToHex(name),
+                                                            ByteBufferUtil.bytesToHex(name.toByteBuffer()),
                                                             me.getMessage()));
         }
     }
@@ -354,12 +359,12 @@ public class QueryProcessor
         validateSliceFilter(metadata, range.start(), range.finish(), range.reversed);
     }
 
-    private static void validateSliceFilter(CFMetaData metadata, ByteBuffer start, ByteBuffer finish, boolean reversed)
+    private static void validateSliceFilter(CFMetaData metadata, Composite start, Composite finish, boolean reversed)
     throws InvalidRequestException
     {
-        AbstractType<?> comparator = metadata.comparator;
-        Comparator<ByteBuffer> orderedComparator = reversed ? comparator.reverseComparator: comparator;
-        if (start.remaining() > 0 && finish.remaining() > 0 && orderedComparator.compare(start, finish) > 0)
+        CellNameType comparator = metadata.comparator;
+        Comparator<Composite> orderedComparator = reversed ? comparator.reverseComparator(): comparator;
+        if (!start.isEmpty() && !finish.isEmpty() && orderedComparator.compare(start, finish) > 0)
             throw new InvalidRequestException("range finish must come after start in traversal order");
     }
 
@@ -442,7 +447,7 @@ public class QueryProcessor
                 // otherwise create resultset from query results
                 result.schema = new CqlMetadata(new HashMap<ByteBuffer, String>(),
                                                 new HashMap<ByteBuffer, String>(),
-                                                TypeParser.getShortName(metadata.comparator),
+                                                TypeParser.getShortName(metadata.comparator.asAbstractType()),
                                                 TypeParser.getShortName(metadata.getDefaultValidator()));
                 List<CqlRow> cqlRows = new ArrayList<CqlRow>(rows.size());
                 for (org.apache.cassandra.db.Row row : rows)
@@ -467,9 +472,9 @@ public class QueryProcessor
                                 if (c.isMarkedForDelete(now))
                                     continue;
 
-                                ColumnDefinition cd = metadata.getColumnDefinitionFromCellName(c.name());
+                                ColumnDefinition cd = metadata.getColumnDefinition(c.name());
                                 if (cd != null)
-                                    result.schema.value_types.put(c.name(), TypeParser.getShortName(cd.type));
+                                    result.schema.value_types.put(c.name().toByteBuffer(), TypeParser.getShortName(cd.type));
 
                                 thriftColumns.add(thriftify(c));
                             }
@@ -495,22 +500,23 @@ public class QueryProcessor
                             if (row.cf == null)
                                 continue;
 
-                            ByteBuffer name;
+                            ByteBuffer nameBytes;
                             try
                             {
-                                name = term.getByteBuffer(metadata.comparator, variables);
+                                nameBytes = term.getByteBuffer(metadata.comparator.asAbstractType(), variables);
                             }
                             catch (InvalidRequestException e)
                             {
                                 throw new AssertionError(e);
                             }
 
-                            ColumnDefinition cd = metadata.getColumnDefinitionFromCellName(name);
+                            CellName name = metadata.comparator.cellFromByteBuffer(nameBytes);
+                            ColumnDefinition cd = metadata.getColumnDefinition(name);
                             if (cd != null)
-                                result.schema.value_types.put(name, TypeParser.getShortName(cd.type));
+                                result.schema.value_types.put(nameBytes, TypeParser.getShortName(cd.type));
                             org.apache.cassandra.db.Column c = row.cf.getColumn(name);
-                            if (c == null || c.isMarkedForDelete(now))
-                                thriftColumns.add(new Column().setName(name));
+                            if (c == null || c.isMarkedForDelete(System.currentTimeMillis()))
+                                thriftColumns.add(new Column().setName(nameBytes));
                             else
                                 thriftColumns.add(thriftify(c));
                         }
@@ -683,7 +689,7 @@ public class QueryProcessor
                         if (cd.getIndexType() != null)
                             throw new InvalidRequestException("Index already exists");
                         if (logger.isDebugEnabled())
-                            logger.debug("Updating column {} definition for index {}", cfm.comparator.getString(columnName), createIdx.getIndexName());
+                            logger.debug("Updating column {} definition for index {}", cfm.comparator.getString(cfm.comparator.fromByteBuffer(columnName)), createIdx.getIndexName());
                         cd.setIndexType(IndexType.KEYS, Collections.<String, String>emptyMap());
                         cd.setIndexName(createIdx.getIndexName());
                         columnExists = true;
@@ -691,7 +697,7 @@ public class QueryProcessor
                     }
                 }
                 if (!columnExists)
-                    throw new InvalidRequestException("No column definition found for column " + oldCfm.comparator.getString(columnName));
+                    throw new InvalidRequestException("No column definition found for column " + oldCfm.comparator.getString(cfm.comparator.fromByteBuffer(columnName)));
 
                 try
                 {
@@ -853,7 +859,7 @@ public class QueryProcessor
         ByteBuffer value = (c instanceof CounterColumn)
                            ? ByteBufferUtil.bytes(CounterContext.instance().total(c.value()))
                            : c.value();
-        return new Column(c.name()).setValue(value).setTimestamp(c.timestamp());
+        return new Column(c.name().toByteBuffer()).setValue(value).setTimestamp(c.timestamp());
     }
 
     private static CQLStatement getStatement(String queryStr) throws SyntaxException

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql/SelectStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/SelectStatement.java b/src/java/org/apache/cassandra/cql/SelectStatement.java
index b77e9ec..b4ccd56 100644
--- a/src/java/org/apache/cassandra/cql/SelectStatement.java
+++ b/src/java/org/apache/cassandra/cql/SelectStatement.java
@@ -17,13 +17,10 @@
  */
 package org.apache.cassandra.cql;
 
-import java.nio.ByteBuffer;
 import java.util.List;
 import java.util.Set;
 
 import org.apache.cassandra.config.CFMetaData;
-import org.apache.cassandra.config.Schema;
-import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.db.ConsistencyLevel;
 
 /**

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql/UpdateStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/UpdateStatement.java b/src/java/org/apache/cassandra/cql/UpdateStatement.java
index 59d797f..446c5a2 100644
--- a/src/java/org/apache/cassandra/cql/UpdateStatement.java
+++ b/src/java/org/apache/cassandra/cql/UpdateStatement.java
@@ -23,6 +23,8 @@ import java.util.*;
 import org.apache.cassandra.auth.Permission;
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.config.Schema;
+import org.apache.cassandra.db.composites.CellName;
+import org.apache.cassandra.db.composites.CellNameType;
 import org.apache.cassandra.db.CounterMutation;
 import org.apache.cassandra.db.ConsistencyLevel;
 import org.apache.cassandra.db.IMutation;
@@ -177,7 +179,8 @@ public class UpdateStatement extends AbstractModification
     throws InvalidRequestException
     {
         validateKey(key);
-        AbstractType<?> comparator = metadata.comparator;
+        CellNameType comparator = metadata.comparator;
+        AbstractType<?> at = comparator.asAbstractType();
 
         // if true we need to wrap RowMutation into CounterMutation
         boolean hasCounterColumn = false;
@@ -185,7 +188,7 @@ public class UpdateStatement extends AbstractModification
 
         for (Map.Entry<Term, Operation> column : getColumns().entrySet())
         {
-            ByteBuffer colName = column.getKey().getByteBuffer(comparator, variables);
+            CellName colName = comparator.cellFromByteBuffer(column.getKey().getByteBuffer(at, variables));
             Operation op = column.getValue();
 
             if (op.isUnary())
@@ -193,7 +196,7 @@ public class UpdateStatement extends AbstractModification
                 if (hasCounterColumn)
                     throw new InvalidRequestException("Mix of commutative and non-commutative operations is not allowed.");
 
-                ByteBuffer colValue = op.a.getByteBuffer(metadata.getValueValidatorFromCellName(colName),variables);
+                ByteBuffer colValue = op.a.getByteBuffer(metadata.getValueValidator(colName),variables);
 
                 validateColumn(metadata, colName, colValue);
                 rm.add(columnFamily,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/CQL3Row.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/CQL3Row.java b/src/java/org/apache/cassandra/cql3/CQL3Row.java
new file mode 100644
index 0000000..bc6bb2c
--- /dev/null
+++ b/src/java/org/apache/cassandra/cql3/CQL3Row.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.cql3;
+
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.cassandra.db.Column;
+
+public interface CQL3Row
+{
+    public ByteBuffer getClusteringColumn(int i);
+    public Column getColumn(ColumnIdentifier name);
+    public List<Column> getCollection(ColumnIdentifier name);
+
+    public interface Builder
+    {
+        Iterator<CQL3Row> group(Iterator<Column> cells);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/ColumnIdentifier.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/ColumnIdentifier.java b/src/java/org/apache/cassandra/cql3/ColumnIdentifier.java
index a11094e..db203e6 100644
--- a/src/java/org/apache/cassandra/cql3/ColumnIdentifier.java
+++ b/src/java/org/apache/cassandra/cql3/ColumnIdentifier.java
@@ -20,14 +20,17 @@ package org.apache.cassandra.cql3;
 import java.util.Locale;
 import java.nio.ByteBuffer;
 
+import org.apache.cassandra.cache.IMeasurableMemory;
 import org.apache.cassandra.cql3.statements.Selectable;
+import org.apache.cassandra.db.TypeSizes;
 import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.ObjectSizes;
 
 /**
  * Represents an identifer for a CQL column definition.
  */
-public class ColumnIdentifier implements Selectable, Comparable<ColumnIdentifier>
+public class ColumnIdentifier implements Selectable, Comparable<ColumnIdentifier>, IMeasurableMemory
 {
     public final ByteBuffer bytes;
     private final String text;
@@ -53,6 +56,11 @@ public class ColumnIdentifier implements Selectable, Comparable<ColumnIdentifier
     @Override
     public final boolean equals(Object o)
     {
+        // Note: it's worth checking for reference equality since we intern those
+        // in SparseCellNameType
+        if (this == o)
+            return true;
+
         if(!(o instanceof ColumnIdentifier))
             return false;
         ColumnIdentifier that = (ColumnIdentifier)o;
@@ -65,8 +73,18 @@ public class ColumnIdentifier implements Selectable, Comparable<ColumnIdentifier
         return text;
     }
 
+    public long memorySize()
+    {
+        return ObjectSizes.getFieldSize(2 * ObjectSizes.getReferenceSize())
+             + ObjectSizes.getSize(bytes)
+             + TypeSizes.NATIVE.sizeof(text);
+    }
+
     public int compareTo(ColumnIdentifier other)
     {
+        if (this == other)
+            return 0;
+
         return bytes.compareTo(other.bytes);
     }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/ColumnNameBuilder.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/ColumnNameBuilder.java b/src/java/org/apache/cassandra/cql3/ColumnNameBuilder.java
deleted file mode 100644
index 384916d..0000000
--- a/src/java/org/apache/cassandra/cql3/ColumnNameBuilder.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.cql3;
-
-import java.nio.ByteBuffer;
-
-/**
- * Build a potentially composite column name.
- */
-public interface ColumnNameBuilder
-{
-    /**
-     * Add a new ByteBuffer as the next component for this name.
-     * @param bb the ByteBuffer to add
-     * @throws IllegalStateException if the builder if full, i.e. if enough component has been added.
-     * @return this builder
-     */
-    public ColumnNameBuilder add(ByteBuffer bb);
-
-    public ColumnNameBuilder add(ColumnIdentifier name);
-
-    /**
-     * Add a new ByteBuffer as the next component for this name.
-     * @param t the ByteBuffer to add
-     * @param op the relationship this component should respect.
-     * @throws IllegalStateException if the builder if full, i.e. if enough component has been added.
-     * @return this builder
-     */
-    public ColumnNameBuilder add(ByteBuffer t, Relation.Type op);
-
-    /**
-     * Returns the number of component already added to this builder.
-     * @return the number of component in this Builder
-     */
-    public int componentCount();
-
-    /**
-     * @return the maximum number of component that can still be added to this Builder
-     */
-    public int remainingCount();
-
-    /**
-     * @return the ith component in this builder.
-     */
-    public ByteBuffer get(int idx);
-
-    /**
-     * Build the column name.
-     * @return the built column name
-     */
-    public ByteBuffer build();
-
-    /**
-     * Build the column name so that the result sorts at the end of the range
-     * represented by this (uncomplete) column name.
-     * @throws IllegalStateException if the builder is empty or full.
-     */
-    public ByteBuffer buildAsEndOfRange();
-
-    /**
-     * Clone this builder.
-     * @return the cloned builder.
-     */
-    public ColumnNameBuilder copy();
-
-    /**
-     * Returns the ith component added to this builder.
-     *
-     * @param i the component to return
-     * @return the ith component added to this builder.
-     * @throws IllegalArgumentException if i >= componentCount().
-     */
-    public ByteBuffer getComponent(int i);
-
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/Constants.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Constants.java b/src/java/org/apache/cassandra/cql3/Constants.java
index 34b3f8d..1784752 100644
--- a/src/java/org/apache/cassandra/cql3/Constants.java
+++ b/src/java/org/apache/cassandra/cql3/Constants.java
@@ -20,18 +20,20 @@ package org.apache.cassandra.cql3;
 import java.nio.ByteBuffer;
 import java.util.List;
 
-import org.apache.cassandra.serializers.MarshalException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.cassandra.db.ColumnFamily;
+import org.apache.cassandra.config.ColumnDefinition;
+import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.composites.CellName;
+import org.apache.cassandra.db.composites.Composite;
 import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.db.marshal.BytesType;
-import org.apache.cassandra.db.marshal.CollectionType;
 import org.apache.cassandra.db.marshal.CounterColumnType;
 import org.apache.cassandra.db.marshal.LongType;
 import org.apache.cassandra.db.marshal.ReversedType;
 import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.serializers.MarshalException;
 import org.apache.cassandra.utils.ByteBufferUtil;
 
 /**
@@ -261,7 +263,7 @@ public abstract class Constants
         protected Marker(int bindIndex, ColumnSpecification receiver)
         {
             super(bindIndex, receiver);
-            assert !(receiver.type instanceof CollectionType);
+            assert !receiver.type.isCollection();
         }
 
         @Override
@@ -289,14 +291,14 @@ public abstract class Constants
 
     public static class Setter extends Operation
     {
-        public Setter(ColumnIdentifier column, Term t)
+        public Setter(ColumnDefinition column, Term t)
         {
             super(column, t);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
-            ByteBuffer cname = columnName == null ? prefix.build() : prefix.add(columnName).build();
+            CellName cname = cf.getComparator().create(prefix, column.name);
             ByteBuffer value = t.bindAndGet(params.variables);
             cf.addColumn(value == null ? params.makeTombstone(cname) : params.makeColumn(cname, value));
         }
@@ -304,30 +306,30 @@ public abstract class Constants
 
     public static class Adder extends Operation
     {
-        public Adder(ColumnIdentifier column, Term t)
+        public Adder(ColumnDefinition column, Term t)
         {
             super(column, t);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
             ByteBuffer bytes = t.bindAndGet(params.variables);
             if (bytes == null)
                 throw new InvalidRequestException("Invalid null value for counter increment");
             long increment = ByteBufferUtil.toLong(bytes);
-            ByteBuffer cname = columnName == null ? prefix.build() : prefix.add(columnName).build();
+            CellName cname = cf.getComparator().create(prefix, column.name);
             cf.addCounter(cname, increment);
         }
     }
 
     public static class Substracter extends Operation
     {
-        public Substracter(ColumnIdentifier column, Term t)
+        public Substracter(ColumnDefinition column, Term t)
         {
             super(column, t);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
             ByteBuffer bytes = t.bindAndGet(params.variables);
             if (bytes == null)
@@ -337,7 +339,7 @@ public abstract class Constants
             if (increment == Long.MIN_VALUE)
                 throw new InvalidRequestException("The negation of " + increment + " overflows supported counter precision (signed 8 bytes integer)");
 
-            ByteBuffer cname = columnName == null ? prefix.build() : prefix.add(columnName).build();
+            CellName cname = cf.getComparator().create(prefix, column.name);
             cf.addCounter(cname, -increment);
         }
     }
@@ -346,22 +348,18 @@ public abstract class Constants
     // duplicating this further
     public static class Deleter extends Operation
     {
-        private final boolean isCollection;
-
-        public Deleter(ColumnIdentifier column, boolean isCollection)
+        public Deleter(ColumnDefinition column)
         {
             super(column, null);
-            this.isCollection = isCollection;
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
-            ColumnNameBuilder column = prefix.add(columnName);
-
-            if (isCollection)
-                cf.addAtom(params.makeRangeTombstone(column.build(), column.buildAsEndOfRange()));
+            CellName cname = cf.getComparator().create(prefix, column.name);
+            if (column.type.isCollection())
+                cf.addAtom(params.makeRangeTombstone(cname.slice()));
             else
-                cf.addColumn(params.makeTombstone(column.build()));
+                cf.addColumn(params.makeTombstone(cname));
         }
     };
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/Lists.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Lists.java b/src/java/org/apache/cassandra/cql3/Lists.java
index 35da98e..6bcdfcd 100644
--- a/src/java/org/apache/cassandra/cql3/Lists.java
+++ b/src/java/org/apache/cassandra/cql3/Lists.java
@@ -23,8 +23,11 @@ import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.apache.cassandra.config.ColumnDefinition;
 import org.apache.cassandra.db.ColumnFamily;
 import org.apache.cassandra.db.Column;
+import org.apache.cassandra.db.composites.CellName;
+import org.apache.cassandra.db.composites.Composite;
 import org.apache.cassandra.db.marshal.CollectionType;
 import org.apache.cassandra.db.marshal.Int32Type;
 import org.apache.cassandra.db.marshal.ListType;
@@ -32,7 +35,6 @@ import org.apache.cassandra.exceptions.InvalidRequestException;
 import org.apache.cassandra.serializers.MarshalException;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.FBUtilities;
-import org.apache.cassandra.utils.Pair;
 import org.apache.cassandra.utils.UUIDGen;
 
 /**
@@ -258,17 +260,17 @@ public abstract class Lists
 
     public static class Setter extends Operation
     {
-        public Setter(ColumnIdentifier column, Term t)
+        public Setter(ColumnDefinition column, Term t)
         {
             super(column, t);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
             // delete + append
-            ColumnNameBuilder column = prefix.add(columnName);
-            cf.addAtom(params.makeTombstoneForOverwrite(column.build(), column.buildAsEndOfRange()));
-            Appender.doAppend(t, cf, column, params);
+            CellName name = cf.getComparator().create(prefix, column.name);
+            cf.addAtom(params.makeTombstoneForOverwrite(name.slice()));
+            Appender.doAppend(t, cf, prefix, column.name, params);
         }
     }
 
@@ -276,7 +278,7 @@ public abstract class Lists
     {
         private final Term idx;
 
-        public SetterByIndex(ColumnIdentifier column, Term idx, Term t)
+        public SetterByIndex(ColumnDefinition column, Term idx, Term t)
         {
             super(column, t);
             this.idx = idx;
@@ -295,7 +297,7 @@ public abstract class Lists
             idx.collectMarkerSpecification(boundNames);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
             ByteBuffer index = idx.bindAndGet(params.variables);
             ByteBuffer value = t.bindAndGet(params.variables);
@@ -303,13 +305,12 @@ public abstract class Lists
             if (index == null)
                 throw new InvalidRequestException("Invalid null value for list index");
 
-            List<Pair<ByteBuffer, Column>> existingList = params.getPrefetchedList(rowKey, columnName);
+            List<Column> existingList = params.getPrefetchedList(rowKey, column.name);
             int idx = ByteBufferUtil.toInt(index);
             if (idx < 0 || idx >= existingList.size())
                 throw new InvalidRequestException(String.format("List index %d out of bound, list has size %d", idx, existingList.size()));
 
-            ByteBuffer elementName = existingList.get(idx).right.name();
-
+            CellName elementName = existingList.get(idx).name();
             if (value == null)
             {
                 cf.addColumn(params.makeTombstone(elementName));
@@ -329,17 +330,17 @@ public abstract class Lists
 
     public static class Appender extends Operation
     {
-        public Appender(ColumnIdentifier column, Term t)
+        public Appender(ColumnDefinition column, Term t)
         {
             super(column, t);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
-            doAppend(t, cf, prefix.add(columnName), params);
+            doAppend(t, cf, prefix, column.name, params);
         }
 
-        static void doAppend(Term t, ColumnFamily cf, ColumnNameBuilder columnName, UpdateParameters params) throws InvalidRequestException
+        static void doAppend(Term t, ColumnFamily cf, Composite prefix, ColumnIdentifier columnName, UpdateParameters params) throws InvalidRequestException
         {
             Term.Terminal value = t.bind(params.variables);
             // If we append null, do nothing. Note that for Setter, we've
@@ -351,22 +352,20 @@ public abstract class Lists
             List<ByteBuffer> toAdd = ((Lists.Value)value).elements;
             for (int i = 0; i < toAdd.size(); i++)
             {
-                ColumnNameBuilder b = i == toAdd.size() - 1 ? columnName : columnName.copy();
                 ByteBuffer uuid = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes());
-                ByteBuffer cellName = b.add(uuid).build();
-                cf.addColumn(params.makeColumn(cellName, toAdd.get(i)));
+                cf.addColumn(params.makeColumn(cf.getComparator().create(prefix, columnName, uuid), toAdd.get(i)));
             }
         }
     }
 
     public static class Prepender extends Operation
     {
-        public Prepender(ColumnIdentifier column, Term t)
+        public Prepender(ColumnDefinition column, Term t)
         {
             super(column, t);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
             Term.Terminal value = t.bind(params.variables);
             if (value == null)
@@ -376,21 +375,18 @@ public abstract class Lists
             long time = PrecisionTime.REFERENCE_TIME - (System.currentTimeMillis() - PrecisionTime.REFERENCE_TIME);
 
             List<ByteBuffer> toAdd = ((Lists.Value)value).elements;
-            ColumnNameBuilder column = prefix.add(columnName);
             for (int i = 0; i < toAdd.size(); i++)
             {
-                ColumnNameBuilder b = i == toAdd.size() - 1 ? column : column.copy();
                 PrecisionTime pt = PrecisionTime.getNext(time);
                 ByteBuffer uuid = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(pt.millis, pt.nanos));
-                ByteBuffer cellName = b.add(uuid).build();
-                cf.addColumn(params.makeColumn(cellName, toAdd.get(i)));
+                cf.addColumn(params.makeColumn(cf.getComparator().create(prefix, column.name, uuid), toAdd.get(i)));
             }
         }
     }
 
     public static class Discarder extends Operation
     {
-        public Discarder(ColumnIdentifier column, Term t)
+        public Discarder(ColumnDefinition column, Term t)
         {
             super(column, t);
         }
@@ -401,9 +397,9 @@ public abstract class Lists
             return true;
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
-            List<Pair<ByteBuffer, Column>> existingList = params.getPrefetchedList(rowKey, columnName);
+            List<Column> existingList = params.getPrefetchedList(rowKey, column.name);
             if (existingList.isEmpty())
                 return;
 
@@ -418,18 +414,17 @@ public abstract class Lists
             // the read-before-write this operation requires limits its usefulness on big lists, so in practice
             // toDiscard will be small and keeping a list will be more efficient.
             List<ByteBuffer> toDiscard = ((Lists.Value)value).elements;
-            for (Pair<ByteBuffer, Column> p : existingList)
+            for (Column cell : existingList)
             {
-                Column element = p.right;
-                if (toDiscard.contains(element.value()))
-                    cf.addColumn(params.makeTombstone(element.name()));
+                if (toDiscard.contains(cell.value()))
+                    cf.addColumn(params.makeTombstone(cell.name()));
             }
         }
     }
 
     public static class DiscarderByIndex extends Operation
     {
-        public DiscarderByIndex(ColumnIdentifier column, Term idx)
+        public DiscarderByIndex(ColumnDefinition column, Term idx)
         {
             super(column, idx);
         }
@@ -440,7 +435,7 @@ public abstract class Lists
             return true;
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
             Term.Terminal index = t.bind(params.variables);
             if (index == null)
@@ -448,12 +443,12 @@ public abstract class Lists
 
             assert index instanceof Constants.Value;
 
-            List<Pair<ByteBuffer, Column>> existingList = params.getPrefetchedList(rowKey, columnName);
+            List<Column> existingList = params.getPrefetchedList(rowKey, column.name);
             int idx = ByteBufferUtil.toInt(((Constants.Value)index).bytes);
             if (idx < 0 || idx >= existingList.size())
                 throw new InvalidRequestException(String.format("List index %d out of bound, list has size %d", idx, existingList.size()));
 
-            ByteBuffer elementName = existingList.get(idx).right.name();
+            CellName elementName = existingList.get(idx).name();
             cf.addColumn(params.makeTombstone(elementName));
         }
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/Maps.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Maps.java b/src/java/org/apache/cassandra/cql3/Maps.java
index 4107b95..d156845 100644
--- a/src/java/org/apache/cassandra/cql3/Maps.java
+++ b/src/java/org/apache/cassandra/cql3/Maps.java
@@ -27,7 +27,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
 
+import org.apache.cassandra.config.ColumnDefinition;
 import org.apache.cassandra.db.ColumnFamily;
+import org.apache.cassandra.db.composites.CellName;
+import org.apache.cassandra.db.composites.Composite;
 import org.apache.cassandra.db.marshal.CollectionType;
 import org.apache.cassandra.db.marshal.MapType;
 import org.apache.cassandra.exceptions.InvalidRequestException;
@@ -236,17 +239,17 @@ public abstract class Maps
 
     public static class Setter extends Operation
     {
-        public Setter(ColumnIdentifier column, Term t)
+        public Setter(ColumnDefinition column, Term t)
         {
             super(column, t);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
             // delete + put
-            ColumnNameBuilder column = prefix.add(columnName);
-            cf.addAtom(params.makeTombstoneForOverwrite(column.build(), column.buildAsEndOfRange()));
-            Putter.doPut(t, cf, column, params);
+            CellName name = cf.getComparator().create(prefix, column.name);
+            cf.addAtom(params.makeTombstoneForOverwrite(name.slice()));
+            Putter.doPut(t, cf, prefix, column.name, params);
         }
     }
 
@@ -254,7 +257,7 @@ public abstract class Maps
     {
         private final Term k;
 
-        public SetterByKey(ColumnIdentifier column, Term k, Term t)
+        public SetterByKey(ColumnDefinition column, Term k, Term t)
         {
             super(column, t);
             this.k = k;
@@ -267,14 +270,14 @@ public abstract class Maps
             k.collectMarkerSpecification(boundNames);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
             ByteBuffer key = k.bindAndGet(params.variables);
             ByteBuffer value = t.bindAndGet(params.variables);
             if (key == null)
                 throw new InvalidRequestException("Invalid null map key");
 
-            ByteBuffer cellName = prefix.add(columnName).add(key).build();
+            CellName cellName = cf.getComparator().create(prefix, column.name, key);
 
             if (value == null)
             {
@@ -295,17 +298,17 @@ public abstract class Maps
 
     public static class Putter extends Operation
     {
-        public Putter(ColumnIdentifier column, Term t)
+        public Putter(ColumnDefinition column, Term t)
         {
             super(column, t);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
-            doPut(t, cf, prefix.add(columnName), params);
+            doPut(t, cf, prefix, column.name, params);
         }
 
-        static void doPut(Term t, ColumnFamily cf, ColumnNameBuilder columnName, UpdateParameters params) throws InvalidRequestException
+        static void doPut(Term t, ColumnFamily cf, Composite prefix, ColumnIdentifier columnName, UpdateParameters params) throws InvalidRequestException
         {
             Term.Terminal value = t.bind(params.variables);
             if (value == null)
@@ -315,7 +318,7 @@ public abstract class Maps
             Map<ByteBuffer, ByteBuffer> toAdd = ((Maps.Value)value).map;
             for (Map.Entry<ByteBuffer, ByteBuffer> entry : toAdd.entrySet())
             {
-                ByteBuffer cellName = columnName.copy().add(entry.getKey()).build();
+                CellName cellName = cf.getComparator().create(prefix, columnName, entry.getKey());
                 cf.addColumn(params.makeColumn(cellName, entry.getValue()));
             }
         }
@@ -323,19 +326,19 @@ public abstract class Maps
 
     public static class DiscarderByKey extends Operation
     {
-        public DiscarderByKey(ColumnIdentifier column, Term k)
+        public DiscarderByKey(ColumnDefinition column, Term k)
         {
             super(column, k);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
             Term.Terminal key = t.bind(params.variables);
             if (key == null)
                 throw new InvalidRequestException("Invalid null map key");
             assert key instanceof Constants.Value;
 
-            ByteBuffer cellName = prefix.add(columnName).add(((Constants.Value)key).bytes).build();
+            CellName cellName = cf.getComparator().create(prefix, column.name, ((Constants.Value)key).bytes);
             cf.addColumn(params.makeTombstone(cellName));
         }
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/Operation.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Operation.java b/src/java/org/apache/cassandra/cql3/Operation.java
index 65f08cb..689cee0 100644
--- a/src/java/org/apache/cassandra/cql3/Operation.java
+++ b/src/java/org/apache/cassandra/cql3/Operation.java
@@ -21,6 +21,7 @@ import java.nio.ByteBuffer;
 
 import org.apache.cassandra.config.ColumnDefinition;
 import org.apache.cassandra.db.ColumnFamily;
+import org.apache.cassandra.db.composites.Composite;
 import org.apache.cassandra.db.marshal.CollectionType;
 import org.apache.cassandra.db.marshal.CounterColumnType;
 import org.apache.cassandra.db.marshal.ListType;
@@ -42,16 +43,17 @@ import org.apache.cassandra.exceptions.InvalidRequestException;
  */
 public abstract class Operation
 {
-    // Name of the column the operation applies to
-    public final ColumnIdentifier columnName;
+    // the column the operation applies to
+    public final ColumnDefinition column;
 
     // Term involved in the operation. In theory this should not be here since some operation
     // may require none of more than one term, but most need 1 so it simplify things a bit.
     protected final Term t;
 
-    protected Operation(ColumnIdentifier columnName, Term t)
+    protected Operation(ColumnDefinition column, Term t)
     {
-        this.columnName = columnName;
+        assert column != null;
+        this.column = column;
         this.t = t;
     }
 
@@ -81,11 +83,10 @@ public abstract class Operation
      *
      * @param rowKey row key for the update.
      * @param cf the column family to which to add the updates generated by this operation.
-     * @param namePrefix the prefix that identify the CQL3 row this operation applies to (callers should not reuse
-     * the ColumnNameBuilder they pass here).
+     * @param prefix the prefix that identify the CQL3 row this operation applies to.
      * @param params parameters of the update.
      */
-    public abstract void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder namePrefix, UpdateParameters params) throws InvalidRequestException;
+    public abstract void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException;
 
     /**
      * A parsed raw UPDATE operation.
@@ -144,7 +145,7 @@ public abstract class Operation
          * @param receiver the "column" this operation applies to.
          * @return the prepared delete operation.
          */
-        public Operation prepare(ColumnSpecification receiver) throws InvalidRequestException;
+        public Operation prepare(ColumnDefinition receiver) throws InvalidRequestException;
     }
 
     public static class SetValue implements RawUpdate
@@ -164,16 +165,16 @@ public abstract class Operation
                 throw new InvalidRequestException(String.format("Cannot set the value of counter column %s (counters can only be incremented/decremented, not set)", receiver));
 
             if (!(receiver.type instanceof CollectionType))
-                return new Constants.Setter(receiver.kind == ColumnDefinition.Kind.COMPACT_VALUE ? null : receiver.name, v);
+                return new Constants.Setter(receiver, v);
 
             switch (((CollectionType)receiver.type).kind)
             {
                 case LIST:
-                    return new Lists.Setter(receiver.name, v);
+                    return new Lists.Setter(receiver, v);
                 case SET:
-                    return new Sets.Setter(receiver.name, v);
+                    return new Sets.Setter(receiver, v);
                 case MAP:
-                    return new Maps.Setter(receiver.name, v);
+                    return new Maps.Setter(receiver, v);
             }
             throw new AssertionError();
         }
@@ -212,13 +213,13 @@ public abstract class Operation
                 case LIST:
                     Term idx = selector.prepare(Lists.indexSpecOf(receiver));
                     Term lval = value.prepare(Lists.valueSpecOf(receiver));
-                    return new Lists.SetterByIndex(receiver.name, idx, lval);
+                    return new Lists.SetterByIndex(receiver, idx, lval);
                 case SET:
                     throw new InvalidRequestException(String.format("Invalid operation (%s) for set column %s", toString(receiver), receiver));
                 case MAP:
                     Term key = selector.prepare(Maps.keySpecOf(receiver));
                     Term mval = value.prepare(Maps.valueSpecOf(receiver));
-                    return new Maps.SetterByKey(receiver.name, key, mval);
+                    return new Maps.SetterByKey(receiver, key, mval);
             }
             throw new AssertionError();
         }
@@ -253,17 +254,17 @@ public abstract class Operation
             {
                 if (!(receiver.type instanceof CounterColumnType))
                     throw new InvalidRequestException(String.format("Invalid operation (%s) for non counter column %s", toString(receiver), receiver));
-                return new Constants.Adder(receiver.kind == ColumnDefinition.Kind.COMPACT_VALUE ? null : receiver.name, v);
+                return new Constants.Adder(receiver, v);
             }
 
             switch (((CollectionType)receiver.type).kind)
             {
                 case LIST:
-                    return new Lists.Appender(receiver.name, v);
+                    return new Lists.Appender(receiver, v);
                 case SET:
-                    return new Sets.Adder(receiver.name, v);
+                    return new Sets.Adder(receiver, v);
                 case MAP:
-                    return new Maps.Putter(receiver.name, v);
+                    return new Maps.Putter(receiver, v);
             }
             throw new AssertionError();
         }
@@ -296,15 +297,15 @@ public abstract class Operation
             {
                 if (!(receiver.type instanceof CounterColumnType))
                     throw new InvalidRequestException(String.format("Invalid operation (%s) for non counter column %s", toString(receiver), receiver));
-                return new Constants.Substracter(receiver.kind == ColumnDefinition.Kind.COMPACT_VALUE ? null : receiver.name, v);
+                return new Constants.Substracter(receiver, v);
             }
 
             switch (((CollectionType)receiver.type).kind)
             {
                 case LIST:
-                    return new Lists.Discarder(receiver.name, v);
+                    return new Lists.Discarder(receiver, v);
                 case SET:
-                    return new Sets.Discarder(receiver.name, v);
+                    return new Sets.Discarder(receiver, v);
                 case MAP:
                     throw new InvalidRequestException(String.format("Invalid operation (%s) for map column %s", toString(receiver), receiver));
             }
@@ -338,7 +339,7 @@ public abstract class Operation
             if (!(receiver.type instanceof ListType))
                 throw new InvalidRequestException(String.format("Invalid operation (%s) for non list column %s", toString(receiver), receiver));
 
-            return new Lists.Prepender(receiver.name, v);
+            return new Lists.Prepender(receiver, v);
         }
 
         protected String toString(ColumnSpecification column)
@@ -366,10 +367,10 @@ public abstract class Operation
             return id;
         }
 
-        public Operation prepare(ColumnSpecification receiver) throws InvalidRequestException
+        public Operation prepare(ColumnDefinition receiver) throws InvalidRequestException
         {
             // No validation, deleting a column is always "well typed"
-            return new Constants.Deleter(id, receiver.type instanceof CollectionType);
+            return new Constants.Deleter(receiver);
         }
     }
 
@@ -389,7 +390,7 @@ public abstract class Operation
             return id;
         }
 
-        public Operation prepare(ColumnSpecification receiver) throws InvalidRequestException
+        public Operation prepare(ColumnDefinition receiver) throws InvalidRequestException
         {
             if (!(receiver.type instanceof CollectionType))
                 throw new InvalidRequestException(String.format("Invalid deletion operation for non collection column %s", receiver));
@@ -398,13 +399,13 @@ public abstract class Operation
             {
                 case LIST:
                     Term idx = element.prepare(Lists.indexSpecOf(receiver));
-                    return new Lists.DiscarderByIndex(id, idx);
+                    return new Lists.DiscarderByIndex(receiver, idx);
                 case SET:
                     Term elt = element.prepare(Sets.valueSpecOf(receiver));
-                    return new Sets.Discarder(id, elt);
+                    return new Sets.Discarder(receiver, elt);
                 case MAP:
                     Term key = element.prepare(Maps.keySpecOf(receiver));
-                    return new Maps.DiscarderByKey(id, key);
+                    return new Maps.DiscarderByKey(receiver, key);
             }
             throw new AssertionError();
         }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/QueryProcessor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/QueryProcessor.java b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
index 351fc86..772c103 100644
--- a/src/java/org/apache/cassandra/cql3/QueryProcessor.java
+++ b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
@@ -34,6 +34,8 @@ import org.apache.cassandra.cql3.hooks.*;
 import org.apache.cassandra.cql3.statements.*;
 import org.apache.cassandra.transport.messages.ResultMessage;
 import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.composites.CellName;
+import org.apache.cassandra.db.composites.Composite;
 import org.apache.cassandra.exceptions.*;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.service.QueryState;
@@ -157,21 +159,25 @@ public class QueryProcessor
         }
     }
 
-    public static void validateCellNames(Iterable<ByteBuffer> cellNames) throws InvalidRequestException
+    public static void validateCellNames(Iterable<CellName> cellNames) throws InvalidRequestException
     {
-        for (ByteBuffer name : cellNames)
+        for (CellName name : cellNames)
             validateCellName(name);
     }
 
-    public static void validateCellName(ByteBuffer name) throws InvalidRequestException
+    public static void validateCellName(CellName name) throws InvalidRequestException
     {
-        if (name.remaining() > Column.MAX_NAME_LENGTH)
+        validateComposite(name);
+        if (name.isEmpty())
+            throw new InvalidRequestException("Invalid empty value for clustering column of COMPACT TABLE");
+    }
+
+    public static void validateComposite(Composite name) throws InvalidRequestException
+    {
+        if (name.dataSize() > Column.MAX_NAME_LENGTH)
             throw new InvalidRequestException(String.format("The sum of all clustering columns is too long (%s > %s)",
-                                                            name.remaining(),
+                                                            name.dataSize(),
                                                             Column.MAX_NAME_LENGTH));
-
-        if (name.remaining() == 0)
-            throw new InvalidRequestException("Invalid empty value for clustering column of COMPACT TABLE");
     }
 
     private static ResultMessage processStatement(CQLStatement statement,
@@ -233,7 +239,7 @@ public class QueryProcessor
         {
             ResultMessage result = process(query, QueryState.forInternalCalls(), new QueryOptions(cl, Collections.<ByteBuffer>emptyList()));
             if (result instanceof ResultMessage.Rows)
-                return new UntypedResultSet(((ResultMessage.Rows)result).result);
+                return UntypedResultSet.create(((ResultMessage.Rows)result).result);
             else
                 return null;
         }
@@ -254,7 +260,7 @@ public class QueryProcessor
             statement.validate(state);
             ResultMessage result = statement.executeInternal(qState);
             if (result instanceof ResultMessage.Rows)
-                return new UntypedResultSet(((ResultMessage.Rows)result).result);
+                return UntypedResultSet.create(((ResultMessage.Rows)result).result);
             else
                 return null;
         }
@@ -279,7 +285,7 @@ public class QueryProcessor
         {
             SelectStatement ss = (SelectStatement) getStatement(query, null).statement;
             ResultSet cqlRows = ss.process(rows);
-            return new UntypedResultSet(cqlRows);
+            return UntypedResultSet.create(cqlRows);
         }
         catch (RequestValidationException e)
         {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/Sets.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Sets.java b/src/java/org/apache/cassandra/cql3/Sets.java
index 01ac1e7..2531b2a 100644
--- a/src/java/org/apache/cassandra/cql3/Sets.java
+++ b/src/java/org/apache/cassandra/cql3/Sets.java
@@ -29,7 +29,10 @@ import java.util.TreeSet;
 
 import com.google.common.base.Joiner;
 
+import org.apache.cassandra.config.ColumnDefinition;
 import org.apache.cassandra.db.ColumnFamily;
+import org.apache.cassandra.db.composites.CellName;
+import org.apache.cassandra.db.composites.Composite;
 import org.apache.cassandra.db.marshal.CollectionType;
 import org.apache.cassandra.db.marshal.MapType;
 import org.apache.cassandra.db.marshal.SetType;
@@ -222,33 +225,33 @@ public abstract class Sets
 
     public static class Setter extends Operation
     {
-        public Setter(ColumnIdentifier column, Term t)
+        public Setter(ColumnDefinition column, Term t)
         {
             super(column, t);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
             // delete + add
-            ColumnNameBuilder column = prefix.add(columnName);
-            cf.addAtom(params.makeTombstoneForOverwrite(column.build(), column.buildAsEndOfRange()));
-            Adder.doAdd(t, cf, column, params);
+            CellName name = cf.getComparator().create(prefix, column.name);
+            cf.addAtom(params.makeTombstoneForOverwrite(name.slice()));
+            Adder.doAdd(t, cf, prefix, column.name, params);
         }
     }
 
     public static class Adder extends Operation
     {
-        public Adder(ColumnIdentifier column, Term t)
+        public Adder(ColumnDefinition column, Term t)
         {
             super(column, t);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
-            doAdd(t, cf, prefix.add(columnName), params);
+            doAdd(t, cf, prefix, column.name, params);
         }
 
-        static void doAdd(Term t, ColumnFamily cf, ColumnNameBuilder columnName, UpdateParameters params) throws InvalidRequestException
+        static void doAdd(Term t, ColumnFamily cf, Composite prefix, ColumnIdentifier columnName, UpdateParameters params) throws InvalidRequestException
         {
             Term.Terminal value = t.bind(params.variables);
             if (value == null)
@@ -259,7 +262,7 @@ public abstract class Sets
             Set<ByteBuffer> toAdd = ((Sets.Value)value).elements;
             for (ByteBuffer bb : toAdd)
             {
-                ByteBuffer cellName = columnName.copy().add(bb).build();
+                CellName cellName = cf.getComparator().create(prefix, columnName, bb);
                 cf.addColumn(params.makeColumn(cellName, ByteBufferUtil.EMPTY_BYTE_BUFFER));
             }
         }
@@ -267,12 +270,12 @@ public abstract class Sets
 
     public static class Discarder extends Operation
     {
-        public Discarder(ColumnIdentifier column, Term t)
+        public Discarder(ColumnDefinition column, Term t)
         {
             super(column, t);
         }
 
-        public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
         {
             Term.Terminal value = t.bind(params.variables);
             if (value == null)
@@ -283,11 +286,9 @@ public abstract class Sets
                                       ? Collections.singleton(((Constants.Value)value).bytes)
                                       : ((Sets.Value)value).elements;
 
-            ColumnNameBuilder column = prefix.add(columnName);
             for (ByteBuffer bb : toDiscard)
             {
-                ByteBuffer cellName = column.copy().add(bb).build();
-                cf.addColumn(params.makeTombstone(cellName));
+                cf.addColumn(params.makeTombstone(cf.getComparator().create(prefix, column.name, bb)));
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/UntypedResultSet.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/UntypedResultSet.java b/src/java/org/apache/cassandra/cql3/UntypedResultSet.java
index 8f1aaf5..5519f2e 100644
--- a/src/java/org/apache/cassandra/cql3/UntypedResultSet.java
+++ b/src/java/org/apache/cassandra/cql3/UntypedResultSet.java
@@ -28,45 +28,98 @@ import org.apache.cassandra.db.marshal.*;
 import org.apache.cassandra.cql3.ResultSet;
 
 /** a utility for doing internal cql-based queries */
-public class UntypedResultSet implements Iterable<UntypedResultSet.Row>
+public abstract class UntypedResultSet implements Iterable<UntypedResultSet.Row>
 {
-    private final ResultSet cqlRows;
-
-    public UntypedResultSet(ResultSet cqlRows)
+    public static UntypedResultSet create(ResultSet rs)
     {
-        this.cqlRows = cqlRows;
+        return new FromResultSet(rs);
     }
 
-    public boolean isEmpty()
+    public static UntypedResultSet create(List<Map<String, ByteBuffer>> results)
     {
-        return cqlRows.size() == 0;
+        return new FromResultList(results);
     }
 
-    public int size()
+    public boolean isEmpty()
     {
-        return cqlRows.size();
+        return size() == 0;
     }
 
-    public Row one()
+    public abstract int size();
+    public abstract Row one();
+
+    private static class FromResultSet extends UntypedResultSet
     {
-        if (cqlRows.rows.size() != 1)
-            throw new IllegalStateException("One row required, " + cqlRows.rows.size() + " found");
-        return new Row(cqlRows.metadata.names, cqlRows.rows.get(0));
+        private final ResultSet cqlRows;
+
+        private FromResultSet(ResultSet cqlRows)
+        {
+            this.cqlRows = cqlRows;
+        }
+
+        public int size()
+        {
+            return cqlRows.size();
+        }
+
+        public Row one()
+        {
+            if (cqlRows.rows.size() != 1)
+                throw new IllegalStateException("One row required, " + cqlRows.rows.size() + " found");
+            return new Row(cqlRows.metadata.names, cqlRows.rows.get(0));
+        }
+
+        public Iterator<Row> iterator()
+        {
+            return new AbstractIterator<Row>()
+            {
+                Iterator<List<ByteBuffer>> iter = cqlRows.rows.iterator();
+
+                protected Row computeNext()
+                {
+                    if (!iter.hasNext())
+                        return endOfData();
+                    return new Row(cqlRows.metadata.names, iter.next());
+                }
+            };
+        }
     }
 
-    public Iterator<Row> iterator()
+    private static class FromResultList extends UntypedResultSet
     {
-        return new AbstractIterator<Row>()
+        private final List<Map<String, ByteBuffer>> cqlRows;
+
+        private FromResultList(List<Map<String, ByteBuffer>> cqlRows)
+        {
+            this.cqlRows = cqlRows;
+        }
+
+        public int size()
         {
-            Iterator<List<ByteBuffer>> iter = cqlRows.rows.iterator();
+            return cqlRows.size();
+        }
+
+        public Row one()
+        {
+            if (cqlRows.size() != 1)
+                throw new IllegalStateException("One row required, " + cqlRows.size() + " found");
+            return new Row(cqlRows.get(0));
+        }
 
-            protected Row computeNext()
+        public Iterator<Row> iterator()
+        {
+            return new AbstractIterator<Row>()
             {
-                if (!iter.hasNext())
-                    return endOfData();
-                return new Row(cqlRows.metadata.names, iter.next());
-            }
-        };
+                Iterator<Map<String, ByteBuffer>> iter = cqlRows.iterator();
+
+                protected Row computeNext()
+                {
+                    if (!iter.hasNext())
+                        return endOfData();
+                    return new Row(iter.next());
+                }
+            };
+        }
     }
 
     public static class Row

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/UpdateParameters.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/UpdateParameters.java b/src/java/org/apache/cassandra/cql3/UpdateParameters.java
index 1288576..cc3fe4d 100644
--- a/src/java/org/apache/cassandra/cql3/UpdateParameters.java
+++ b/src/java/org/apache/cassandra/cql3/UpdateParameters.java
@@ -23,10 +23,10 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.cassandra.config.CFMetaData;
-import org.apache.cassandra.cql3.statements.ColumnGroupMap;
 import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.composites.CellName;
+import org.apache.cassandra.db.filter.ColumnSlice;
 import org.apache.cassandra.exceptions.InvalidRequestException;
-import org.apache.cassandra.utils.Pair;
 
 /**
  * A simple container that simplify passing parameters for collections methods.
@@ -40,9 +40,9 @@ public class UpdateParameters
     public final int localDeletionTime;
 
     // For lists operation that require a read-before-write. Will be null otherwise.
-    private final Map<ByteBuffer, ColumnGroupMap> prefetchedLists;
+    private final Map<ByteBuffer, CQL3Row> prefetchedLists;
 
-    public UpdateParameters(CFMetaData metadata, List<ByteBuffer> variables, long timestamp, int ttl, Map<ByteBuffer, ColumnGroupMap> prefetchedLists)
+    public UpdateParameters(CFMetaData metadata, List<ByteBuffer> variables, long timestamp, int ttl, Map<ByteBuffer, CQL3Row> prefetchedLists)
     {
         this.metadata = metadata;
         this.variables = variables;
@@ -52,38 +52,38 @@ public class UpdateParameters
         this.prefetchedLists = prefetchedLists;
     }
 
-    public Column makeColumn(ByteBuffer name, ByteBuffer value) throws InvalidRequestException
+    public Column makeColumn(CellName name, ByteBuffer value) throws InvalidRequestException
     {
         QueryProcessor.validateCellName(name);
         return Column.create(name, value, timestamp, ttl, metadata);
     }
 
-    public Column makeTombstone(ByteBuffer name) throws InvalidRequestException
+    public Column makeTombstone(CellName name) throws InvalidRequestException
     {
         QueryProcessor.validateCellName(name);
         return new DeletedColumn(name, localDeletionTime, timestamp);
     }
 
-    public RangeTombstone makeRangeTombstone(ByteBuffer start, ByteBuffer end) throws InvalidRequestException
+    public RangeTombstone makeRangeTombstone(ColumnSlice slice) throws InvalidRequestException
     {
-        QueryProcessor.validateCellName(start);
-        QueryProcessor.validateCellName(end);
-        return new RangeTombstone(start, end, timestamp, localDeletionTime);
+        QueryProcessor.validateComposite(slice.start);
+        QueryProcessor.validateComposite(slice.finish);
+        return new RangeTombstone(slice.start, slice.finish, timestamp, localDeletionTime);
     }
 
-    public RangeTombstone makeTombstoneForOverwrite(ByteBuffer start, ByteBuffer end) throws InvalidRequestException
+    public RangeTombstone makeTombstoneForOverwrite(ColumnSlice slice) throws InvalidRequestException
     {
-        QueryProcessor.validateCellName(start);
-        QueryProcessor.validateCellName(end);
-        return new RangeTombstone(start, end, timestamp - 1, localDeletionTime);
+        QueryProcessor.validateComposite(slice.start);
+        QueryProcessor.validateComposite(slice.finish);
+        return new RangeTombstone(slice.start, slice.finish, timestamp - 1, localDeletionTime);
     }
 
-    public List<Pair<ByteBuffer, Column>> getPrefetchedList(ByteBuffer rowKey, ColumnIdentifier cql3ColumnName)
+    public List<Column> getPrefetchedList(ByteBuffer rowKey, ColumnIdentifier cql3ColumnName)
     {
         if (prefetchedLists == null)
             return Collections.emptyList();
 
-        ColumnGroupMap m = prefetchedLists.get(rowKey);
-        return m == null ? Collections.<Pair<ByteBuffer, Column>>emptyList() : m.getCollection(cql3ColumnName.bytes);
+        CQL3Row row = prefetchedLists.get(rowKey);
+        return row == null ? Collections.<Column>emptyList() : row.getCollection(cql3ColumnName);
     }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/functions/TimeuuidFcts.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/TimeuuidFcts.java b/src/java/org/apache/cassandra/cql3/functions/TimeuuidFcts.java
index 9c69c19..be20102 100644
--- a/src/java/org/apache/cassandra/cql3/functions/TimeuuidFcts.java
+++ b/src/java/org/apache/cassandra/cql3/functions/TimeuuidFcts.java
@@ -91,3 +91,4 @@ public abstract class TimeuuidFcts
         }
     };
 }
+

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/functions/TokenFct.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/TokenFct.java b/src/java/org/apache/cassandra/cql3/functions/TokenFct.java
index cb6e6c4..5093a72 100644
--- a/src/java/org/apache/cassandra/cql3/functions/TokenFct.java
+++ b/src/java/org/apache/cassandra/cql3/functions/TokenFct.java
@@ -23,7 +23,7 @@ import java.util.List;
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.config.ColumnDefinition;
 import org.apache.cassandra.config.Schema;
-import org.apache.cassandra.cql3.ColumnNameBuilder;
+import org.apache.cassandra.db.composites.CBuilder;
 import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.dht.IPartitioner;
 import org.apache.cassandra.exceptions.InvalidRequestException;
@@ -61,7 +61,7 @@ public class TokenFct extends AbstractFunction
 
     public ByteBuffer execute(List<ByteBuffer> parameters) throws InvalidRequestException
     {
-        ColumnNameBuilder builder = cfm.getKeyNameBuilder();
+        CBuilder builder = cfm.getKeyValidatorAsCType().builder();
         for (int i = 0; i < parameters.size(); i++)
         {
             ByteBuffer bb = parameters.get(i);
@@ -69,6 +69,6 @@ public class TokenFct extends AbstractFunction
                 return null;
             builder.add(bb);
         }
-        return partitioner.getTokenFactory().toByteArray(partitioner.getToken(builder.build()));
+        return partitioner.getTokenFactory().toByteArray(partitioner.getToken(builder.build().toByteBuffer()));
     }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
index 049f90d..d1452d2 100644
--- a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
@@ -17,9 +17,7 @@
  */
 package org.apache.cassandra.cql3.statements;
 
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -77,7 +75,7 @@ public class AlterTableStatement extends SchemaAlteringStatement
         switch (oType)
         {
             case ADD:
-                if (cfm.isDense())
+                if (cfm.comparator.isDense())
                     throw new InvalidRequestException("Cannot add new column to a compact CF");
                 if (def != null)
                 {
@@ -94,28 +92,15 @@ public class AlterTableStatement extends SchemaAlteringStatement
                 AbstractType<?> type = validator.getType();
                 if (type instanceof CollectionType)
                 {
-                    if (!cfm.hasCompositeComparator())
+                    if (!cfm.comparator.supportCollections())
                         throw new InvalidRequestException("Cannot use collection types with non-composite PRIMARY KEY");
                     if (cfm.isSuper())
                         throw new InvalidRequestException("Cannot use collection types with Super column family");
 
-                    Map<ByteBuffer, CollectionType> collections = cfm.hasCollections()
-                                                                ? new HashMap<ByteBuffer, CollectionType>(cfm.getCollectionType().defined)
-                                                                : new HashMap<ByteBuffer, CollectionType>();
-
-                    collections.put(columnName.bytes, (CollectionType)type);
-                    ColumnToCollectionType newColType = ColumnToCollectionType.getInstance(collections);
-                    List<AbstractType<?>> ctypes = new ArrayList<AbstractType<?>>(((CompositeType)cfm.comparator).types);
-                    if (cfm.hasCollections())
-                        ctypes.set(ctypes.size() - 1, newColType);
-                    else
-                        ctypes.add(newColType);
-                    cfm.comparator = CompositeType.getInstance(ctypes);
+                    cfm.comparator = cfm.comparator.addCollection(columnName, (CollectionType)type);
                 }
 
-                Integer componentIndex = meta.hasCompositeComparator()
-                                       ? ((CompositeType)meta.comparator).types.size() - (meta.hasCollections() ? 2 : 1)
-                                       : null;
+                Integer componentIndex = cfm.comparator.isCompound() ? cfm.comparator.clusteringPrefixSize() : null;
                 cfm.addColumnDefinition(ColumnDefinition.regularDef(cfm, columnName.bytes, type, componentIndex));
                 break;
 
@@ -153,19 +138,17 @@ public class AlterTableStatement extends SchemaAlteringStatement
                         }
                         break;
                     case CLUSTERING_COLUMN:
-                        assert cfm.hasCompositeComparator();
-                        List<AbstractType<?>> oldTypes = ((CompositeType) cfm.comparator).types;
+                        AbstractType<?> oldType = cfm.comparator.subtype(def.position());
                         // Note that CFMetaData.validateCompatibility already validate the change we're about to do. However, the error message it
                         // sends is a bit cryptic for a CQL3 user, so validating here for a sake of returning a better error message
                         // Do note that we need isCompatibleWith here, not just isValueCompatibleWith.
-                        if (!validator.getType().isCompatibleWith(oldTypes.get(def.position())))
+                        if (!validator.getType().isCompatibleWith(oldType))
                             throw new ConfigurationException(String.format("Cannot change %s from type %s to type %s: types are not order-compatible.",
                                                                            columnName,
-                                                                           oldTypes.get(def.position()).asCQL3Type(),
+                                                                           oldType.asCQL3Type(),
                                                                            validator));
-                        List<AbstractType<?>> newTypes = new ArrayList<AbstractType<?>>(oldTypes);
-                        newTypes.set(def.position(), validator.getType());
-                        cfm.comparator = CompositeType.getInstance(newTypes);
+
+                        cfm.comparator = cfm.comparator.setSubtype(def.position(), validator.getType());
                         break;
                     case COMPACT_VALUE:
                         // See below
@@ -195,9 +178,7 @@ public class AlterTableStatement extends SchemaAlteringStatement
                 break;
 
             case DROP:
-                if (cfm.isDense())
-                    throw new InvalidRequestException("Cannot drop columns from a compact CF");
-                if (!cfm.hasCompositeComparator())
+                if (!cfm.isCQL3Table())
                     throw new InvalidRequestException("Cannot drop columns from a non-CQL3 CF");
                 if (def == null)
                     throw new InvalidRequestException(String.format("Column %s was not found in table %s", columnName, columnFamily()));

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java b/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
index fbecefe..ea9f0c7 100644
--- a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
@@ -23,6 +23,7 @@ import java.util.*;
 import org.apache.cassandra.auth.Permission;
 import org.apache.cassandra.config.*;
 import org.apache.cassandra.cql3.*;
+import org.apache.cassandra.db.composites.CellNames;
 import org.apache.cassandra.db.marshal.*;
 import org.apache.cassandra.exceptions.*;
 import org.apache.cassandra.service.ClientState;
@@ -153,7 +154,7 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement
                 cfm.keyValidator(updateWith(cfm.getKeyValidator(), toReplace, updated));
                 break;
             case CLUSTERING_COLUMN:
-                cfm.comparator = updateWith(cfm.comparator, toReplace, updated);
+                cfm.comparator = CellNames.fromAbstractType(updateWith(cfm.comparator.asAbstractType(), toReplace, updated), cfm.comparator.isDense());
                 break;
         }
         return true;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/362cc053/src/java/org/apache/cassandra/cql3/statements/ColumnGroupMap.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/ColumnGroupMap.java b/src/java/org/apache/cassandra/cql3/statements/ColumnGroupMap.java
deleted file mode 100644
index 8974523..0000000
--- a/src/java/org/apache/cassandra/cql3/statements/ColumnGroupMap.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.cql3.statements;
-
-import java.nio.ByteBuffer;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.cassandra.db.Column;
-import org.apache.cassandra.db.marshal.CompositeType;
-import org.apache.cassandra.utils.Pair;
-
-public class ColumnGroupMap
-{
-    private final ByteBuffer[] fullPath;
-    private final Map<ByteBuffer, Value> map = new HashMap<ByteBuffer, Value>();
-
-    private ColumnGroupMap(ByteBuffer[] fullPath)
-    {
-        this.fullPath = fullPath;
-    }
-
-    private void add(ByteBuffer[] fullName, int idx, Column column)
-    {
-        ByteBuffer columnName = fullName[idx];
-        if (fullName.length == idx + 2)
-        {
-            // It's a collection
-            Value v = map.get(columnName);
-            if (v == null)
-            {
-                v = new Collection();
-                map.put(columnName, v);
-            }
-            assert v instanceof Collection;
-
-            ((Collection)v).add(Pair.create(fullName[idx + 1], column));
-        }
-        else
-        {
-            assert !map.containsKey(columnName);
-            map.put(columnName, new Simple(column));
-        }
-    }
-
-    public ByteBuffer getKeyComponent(int pos)
-    {
-        return fullPath[pos];
-    }
-
-    public Column getSimple(ByteBuffer key)
-    {
-        Value v = map.get(key);
-        if (v == null)
-            return null;
-
-        assert v instanceof Simple;
-        return ((Simple)v).column;
-    }
-
-    public List<Pair<ByteBuffer, Column>> getCollection(ByteBuffer key)
-    {
-        Value v = map.get(key);
-        if (v == null)
-            return null;
-
-        assert v instanceof Collection;
-        return (List<Pair<ByteBuffer, Column>>)v;
-    }
-
-    private interface Value {};
-
-    private static class Simple implements Value
-    {
-        public final Column column;
-
-        Simple(Column column)
-        {
-            this.column = column;
-        }
-    }
-
-    private static class Collection extends ArrayList<Pair<ByteBuffer, Column>> implements Value {}
-
-    public static class Builder
-    {
-        private final CompositeType composite;
-        private final int idx;
-        private final long now;
-        private ByteBuffer[] previous;
-
-        private final List<ColumnGroupMap> groups = new ArrayList<ColumnGroupMap>();
-        private ColumnGroupMap currentGroup;
-
-        public Builder(CompositeType composite, boolean hasCollections, long now)
-        {
-            this.composite = composite;
-            this.idx = composite.types.size() - (hasCollections ? 2 : 1);
-            this.now = now;
-        }
-
-        public void add(Column c)
-        {
-            if (c.isMarkedForDelete(now))
-                return;
-
-            ByteBuffer[] current = composite.split(c.name());
-
-            if (currentGroup == null)
-            {
-                currentGroup = new ColumnGroupMap(current);
-                currentGroup.add(current, idx, c);
-                previous = current;
-                return;
-            }
-
-            if (!isSameGroup(current))
-            {
-                groups.add(currentGroup);
-                currentGroup = new ColumnGroupMap(current);
-            }
-            currentGroup.add(current, idx, c);
-            previous = current;
-        }
-
-        /**
-         * For sparse composite, returns wheter the column belong to the same
-         * cqlRow than the previously added, based on the full list of component
-         * in the name.
-         * Two columns do belong together if they differ only by the last
-         * component.
-         */
-        private boolean isSameGroup(ByteBuffer[] c)
-        {
-            for (int i = 0; i < idx; i++)
-            {
-                if (!c[i].equals(previous[i]))
-                    return false;
-            }
-            return true;
-        }
-
-        public List<ColumnGroupMap> groups()
-        {
-            if (currentGroup != null)
-            {
-                groups.add(currentGroup);
-                currentGroup = null;
-            }
-            return groups;
-        }
-    }
-}