cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From slebre...@apache.org
Subject [2/3] git commit: Merge branch 'cassandra-2.0' into cassandra-2.1
Date Thu, 06 Mar 2014 09:07:00 GMT
Merge branch 'cassandra-2.0' into cassandra-2.1

Conflicts:
	CHANGES.txt
	src/java/org/apache/cassandra/cql3/statements/ColumnGroupMap.java
	src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
	src/java/org/apache/cassandra/db/SystemKeyspace.java
	src/java/org/apache/cassandra/db/filter/NamesQueryFilter.java
	src/java/org/apache/cassandra/utils/FBUtilities.java
	test/long/org/apache/cassandra/db/LongKeyspaceTest.java
	test/unit/org/apache/cassandra/SchemaLoader.java
	test/unit/org/apache/cassandra/config/DefsTest.java
	test/unit/org/apache/cassandra/db/CollationControllerTest.java
	test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
	test/unit/org/apache/cassandra/db/KeyspaceTest.java
	test/unit/org/apache/cassandra/db/ReadMessageTest.java
	test/unit/org/apache/cassandra/db/RecoveryManagerTruncateTest.java
	test/unit/org/apache/cassandra/db/RemoveCellTest.java
	test/unit/org/apache/cassandra/io/sstable/LegacySSTableTest.java
	test/unit/org/apache/cassandra/tools/SSTableExportTest.java


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

Branch: refs/heads/trunk
Commit: 5d67e852e2de161bec0722f80243a3cefbbc6535
Parents: 4cf8a8a 773fade
Author: Sylvain Lebresne <sylvain@datastax.com>
Authored: Thu Mar 6 10:05:29 2014 +0100
Committer: Sylvain Lebresne <sylvain@datastax.com>
Committed: Thu Mar 6 10:05:29 2014 +0100

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../db/composites/AbstractCellNameType.java     | 10 +++--
 .../cassandra/db/composites/CellName.java       |  2 +-
 .../db/composites/CompoundDenseCellName.java    |  4 +-
 .../db/composites/CompoundSparseCellName.java   |  4 +-
 .../composites/CompoundSparseCellNameType.java  |  2 +-
 .../db/composites/SimpleDenseCellName.java      |  4 +-
 .../db/composites/SimpleSparseCellName.java     |  2 +-
 .../db/composites/SimpleSparseCellNameType.java |  2 +-
 .../apache/cassandra/db/filter/ColumnSlice.java |  2 +-
 .../cassandra/db/ColumnFamilyStoreTest.java     | 44 ++++++++++++++++++++
 11 files changed, 62 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d67e852/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index f420fb1,d697e3f..098ecbc
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -44,44 -33,24 +44,45 @@@ Merged from 2.0
   * Fix UPDATE updating PRIMARY KEY columns implicitly (CASSANDRA-6782)
   * Fix IllegalArgumentException when updating from 1.2 with SuperColumns
     (CASSANDRA-6733)
+  * FBUtilities.singleton() should use the CF comparator (CASSANDRA-6778)
 -Merged from 1.2:
 - * Add CMSClassUnloadingEnabled JVM option (CASSANDRA-6541)
 - * Catch memtable flush exceptions during shutdown (CASSANDRA-6735)
 - * Fix broken streams when replacing with same IP (CASSANDRA-6622)
 - * Fix upgradesstables NPE for non-CF-based indexes (CASSANDRA-6645)
 - * Fix partition and range deletes not triggering flush (CASSANDRA-6655)
 - * Fix mean cells and mean row size per sstable calculations (CASSANDRA-6667)
 - * Compact hints after partial replay to clean out tombstones (CASSANDRA-6666)
 - * Log USING TTL/TIMESTAMP in a counter update warning (CASSANDRA-6649)
 - * Don't exchange schema between nodes with different versions (CASSANDRA-6695)
 - * Use real node messaging versions for schema exchange decisions (CASSANDRA-6700)
 - * IN on the last clustering columns + ORDER BY DESC yield no results (CASSANDRA-6701)
 - * Fix SecondaryIndexManager#deleteFromIndexes() (CASSANDRA-6711)
 - * Fix snapshot repair not snapshotting coordinator itself (CASSANDRA-6713)
 - * Support negative timestamps for CQL3 dates in query string (CASSANDRA-6718)
 - * Avoid NPEs when receiving table changes for an unknown keyspace (CASSANDRA-5631)
 - * Fix bootstrapping when there is no schema (CASSANDRA-6685)
 +
 +
 +2.1.0-beta1
 + * Add flush directory distinct from compaction directories (CASSANDRA-6357)
 + * Require JNA by default (CASSANDRA-6575)
 + * add listsnapshots command to nodetool (CASSANDRA-5742)
 + * Introduce AtomicBTreeColumns (CASSANDRA-6271, 6692)
 + * Multithreaded commitlog (CASSANDRA-3578)
 + * allocate fixed index summary memory pool and resample cold index summaries 
 +   to use less memory (CASSANDRA-5519)
 + * Removed multithreaded compaction (CASSANDRA-6142)
 + * Parallelize fetching rows for low-cardinality indexes (CASSANDRA-1337)
 + * change logging from log4j to logback (CASSANDRA-5883)
 + * switch to LZ4 compression for internode communication (CASSANDRA-5887)
 + * Stop using Thrift-generated Index* classes internally (CASSANDRA-5971)
 + * Remove 1.2 network compatibility code (CASSANDRA-5960)
 + * Remove leveled json manifest migration code (CASSANDRA-5996)
 + * Remove CFDefinition (CASSANDRA-6253)
 + * Use AtomicIntegerFieldUpdater in RefCountedMemory (CASSANDRA-6278)
 + * User-defined types for CQL3 (CASSANDRA-5590)
 + * Use of o.a.c.metrics in nodetool (CASSANDRA-5871, 6406)
 + * Batch read from OTC's queue and cleanup (CASSANDRA-1632)
 + * Secondary index support for collections (CASSANDRA-4511, 6383)
 + * SSTable metadata(Stats.db) format change (CASSANDRA-6356)
 + * Push composites support in the storage engine
 +   (CASSANDRA-5417, CASSANDRA-6520)
 + * Add snapshot space used to cfstats (CASSANDRA-6231)
 + * Add cardinality estimator for key count estimation (CASSANDRA-5906)
 + * CF id is changed to be non-deterministic. Data dir/key cache are created
 +   uniquely for CF id (CASSANDRA-5202)
 + * New counters implementation (CASSANDRA-6504)
 + * Replace UnsortedColumns, EmptyColumns, TreeMapBackedSortedColumns with new
 +   ArrayBackedSortedColumns (CASSANDRA-6630, CASSANDRA-6662, CASSANDRA-6690)
 + * Add option to use row cache with a given amount of rows (CASSANDRA-5357)
 + * Avoid repairing already repaired data (CASSANDRA-5351)
 + * Reject counter updates with USING TTL/TIMESTAMP (CASSANDRA-6649)
 + * Replace index_interval with min/max_index_interval (CASSANDRA-6379)
 + * Lift limitation that order by columns must be selected for IN queries (CASSANDRA-4911)
  
  
  2.0.5

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d67e852/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java
index 22aba09,0000000..6bba44a
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/AbstractCellNameType.java
@@@ -1,428 -1,0 +1,430 @@@
 +/*
 + * 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.db.composites;
 +
 +import java.io.DataInput;
 +import java.io.DataOutput;
 +import java.io.IOException;
 +import java.nio.ByteBuffer;
 +import java.util.*;
 +
 +import com.google.common.collect.AbstractIterator;
 +import org.apache.cassandra.config.ColumnDefinition;
 +import org.apache.cassandra.cql3.CQL3Row;
 +import org.apache.cassandra.cql3.ColumnIdentifier;
 +import org.apache.cassandra.db.*;
 +import org.apache.cassandra.db.filter.IDiskAtomFilter;
 +import org.apache.cassandra.db.filter.NamesQueryFilter;
 +import org.apache.cassandra.db.marshal.AbstractType;
 +import org.apache.cassandra.db.marshal.CollectionType;
 +import org.apache.cassandra.db.marshal.ColumnToCollectionType;
 +import org.apache.cassandra.io.ISerializer;
 +import org.apache.cassandra.io.IVersionedSerializer;
 +import org.apache.cassandra.utils.ByteBufferUtil;
 +
 +public abstract class AbstractCellNameType extends AbstractCType implements CellNameType
 +{
 +    private final Comparator<Cell> columnComparator;
 +    private final Comparator<Cell> columnReverseComparator;
 +    private final Comparator<OnDiskAtom> onDiskAtomComparator;
 +
 +    private final ISerializer<CellName> cellSerializer;
 +    private final ColumnSerializer columnSerializer;
 +    private final OnDiskAtom.Serializer onDiskAtomSerializer;
 +    private final IVersionedSerializer<NamesQueryFilter> namesQueryFilterSerializer;
 +    private final IVersionedSerializer<IDiskAtomFilter> diskAtomFilterSerializer;
 +
 +    protected AbstractCellNameType()
 +    {
 +        columnComparator = new Comparator<Cell>()
 +        {
 +            public int compare(Cell c1, Cell c2)
 +            {
 +                return AbstractCellNameType.this.compare(c1.name(), c2.name());
 +            }
 +        };
 +        columnReverseComparator = new Comparator<Cell>()
 +        {
 +            public int compare(Cell c1, Cell c2)
 +            {
 +                return AbstractCellNameType.this.compare(c2.name(), c1.name());
 +            }
 +        };
 +        onDiskAtomComparator = new Comparator<OnDiskAtom>()
 +        {
 +            public int compare(OnDiskAtom c1, OnDiskAtom c2)
 +            {
 +                int comp = AbstractCellNameType.this.compare(c1.name(), c2.name());
 +                if (comp != 0)
 +                    return comp;
 +
 +                if (c1 instanceof RangeTombstone)
 +                {
 +                    if (c2 instanceof RangeTombstone)
 +                    {
 +                        RangeTombstone t1 = (RangeTombstone)c1;
 +                        RangeTombstone t2 = (RangeTombstone)c2;
 +                        int comp2 = AbstractCellNameType.this.compare(t1.max, t2.max);
 +                        return comp2 == 0 ? t1.data.compareTo(t2.data) : comp2;
 +                    }
 +                    else
 +                    {
 +                        return -1;
 +                    }
 +                }
 +                else
 +                {
 +                    return c2 instanceof RangeTombstone ? 1 : 0;
 +                }
 +            }
 +        };
 +
 +        // A trivial wrapped over the composite serializer
 +        cellSerializer = new ISerializer<CellName>()
 +        {
 +            public void serialize(CellName c, DataOutput out) throws IOException
 +            {
 +                serializer().serialize(c, out);
 +            }
 +
 +            public CellName deserialize(DataInput in) throws IOException
 +            {
 +                Composite ct = serializer().deserialize(in);
 +                if (ct.isEmpty())
 +                    throw ColumnSerializer.CorruptColumnException.create(in, ByteBufferUtil.EMPTY_BYTE_BUFFER);
 +
 +                assert ct instanceof CellName : ct;
 +                return (CellName)ct;
 +            }
 +
 +            public long serializedSize(CellName c, TypeSizes type)
 +            {
 +                return serializer().serializedSize(c, type);
 +            }
 +        };
 +        columnSerializer = new ColumnSerializer(this);
 +        onDiskAtomSerializer = new OnDiskAtom.Serializer(this);
 +        namesQueryFilterSerializer = new NamesQueryFilter.Serializer(this);
 +        diskAtomFilterSerializer = new IDiskAtomFilter.Serializer(this);
 +    }
 +
 +    public Comparator<Cell> columnComparator()
 +    {
 +        return columnComparator;
 +    }
 +
 +    public Comparator<Cell> columnReverseComparator()
 +    {
 +        return columnReverseComparator;
 +    }
 +
 +    public Comparator<OnDiskAtom> onDiskAtomComparator()
 +    {
 +        return onDiskAtomComparator;
 +    }
 +
 +    public ISerializer<CellName> cellSerializer()
 +    {
 +        return cellSerializer;
 +    }
 +
 +    public ColumnSerializer columnSerializer()
 +    {
 +        return columnSerializer;
 +    }
 +
 +    public OnDiskAtom.Serializer onDiskAtomSerializer()
 +    {
 +        return onDiskAtomSerializer;
 +    }
 +
 +    public IVersionedSerializer<NamesQueryFilter> namesQueryFilterSerializer()
 +    {
 +        return namesQueryFilterSerializer;
 +    }
 +
 +    public IVersionedSerializer<IDiskAtomFilter> diskAtomFilterSerializer()
 +    {
 +        return diskAtomFilterSerializer;
 +    }
 +
 +    public CellName cellFromByteBuffer(ByteBuffer bytes)
 +    {
 +        return (CellName)fromByteBuffer(bytes);
 +    }
 +
 +    public CellName create(Composite prefix, ColumnDefinition column, ByteBuffer collectionElement)
 +    {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    public CellName rowMarker(Composite prefix)
 +    {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    public Composite staticPrefix()
 +    {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    public boolean hasCollections()
 +    {
 +        return false;
 +    }
 +
 +    public boolean supportCollections()
 +    {
 +        return false;
 +    }
 +
 +    public ColumnToCollectionType collectionType()
 +    {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    public CellNameType addOrUpdateCollection(ColumnIdentifier columnName, CollectionType newCollection)
 +    {
 +        throw new UnsupportedOperationException();
 +    }
 +
 +    @Override
 +    public Composite make(Object... components)
 +    {
 +        return components.length == size() ? makeCellName(components) : super.make(components);
 +    }
 +
 +    public CellName makeCellName(Object... components)
 +    {
 +        ByteBuffer[] rawComponents = new ByteBuffer[components.length];
 +        for (int i = 0; i < components.length; i++)
 +        {
 +            Object c = components[i];
 +            if (c instanceof ByteBuffer)
 +            {
 +                rawComponents[i] = (ByteBuffer)c;
 +            }
 +            else
 +            {
 +                AbstractType<?> type = subtype(i);
 +                // If it's a collection type, we need to find the right collection and use the key comparator (since we're building a cell name)
 +                if (type instanceof ColumnToCollectionType)
 +                {
 +                    assert i > 0;
 +                    type = ((ColumnToCollectionType)type).defined.get(rawComponents[i-1]).nameComparator();
 +                }
 +                rawComponents[i] = ((AbstractType)type).decompose(c);
 +            }
 +        }
 +        return makeCellName(rawComponents);
 +    }
 +
 +    protected abstract CellName makeCellName(ByteBuffer[] components);
 +
 +    protected static CQL3Row.Builder makeDenseCQL3RowBuilder(final long now)
 +    {
 +        return new CQL3Row.Builder()
 +        {
 +            public CQL3Row.RowIterator group(Iterator<Cell> cells)
 +            {
 +                return new DenseRowIterator(cells, now);
 +            }
 +        };
 +    }
 +
 +    private static class DenseRowIterator extends AbstractIterator<CQL3Row> implements CQL3Row.RowIterator
 +    {
 +        private final Iterator<Cell> cells;
 +        private final long now;
 +
 +        public DenseRowIterator(Iterator<Cell> cells, long now)
 +        {
 +            this.cells = cells;
 +            this.now = now;
 +        }
 +
 +        public CQL3Row getStaticRow()
 +        {
 +            // There can't be static columns in dense tables
 +            return null;
 +        }
 +
 +        protected CQL3Row computeNext()
 +        {
 +            while (cells.hasNext())
 +            {
 +                final Cell cell = cells.next();
 +                if (cell.isMarkedForDelete(now))
 +                    continue;
 +
 +                return new CQL3Row()
 +                {
 +                    public ByteBuffer getClusteringColumn(int i)
 +                    {
 +                        return cell.name().get(i);
 +                    }
 +
 +                    public Cell getColumn(ColumnIdentifier name)
 +                    {
 +                        return cell;
 +                    }
 +
 +                    public List<Cell> getCollection(ColumnIdentifier name)
 +                    {
 +                        return null;
 +                    }
 +                };
 +            }
 +            return endOfData();
 +        }
 +    }
 +
-     protected static CQL3Row.Builder makeSparseCQL3RowBuilder(final long now)
++    protected static CQL3Row.Builder makeSparseCQL3RowBuilder(final CellNameType type, final long now)
 +    {
 +        return new CQL3Row.Builder()
 +        {
 +            public CQL3Row.RowIterator group(Iterator<Cell> cells)
 +            {
-                 return new SparseRowIterator(cells, now);
++                return new SparseRowIterator(type, cells, now);
 +            }
 +        };
 +    }
 +
 +    private static class SparseRowIterator extends AbstractIterator<CQL3Row> implements CQL3Row.RowIterator
 +    {
++        private final CellNameType type;
 +        private final Iterator<Cell> cells;
 +        private final long now;
 +        private final CQL3Row staticRow;
 +
 +        private Cell nextCell;
 +        private CellName previous;
 +        private CQL3RowOfSparse currentRow;
 +
-         public SparseRowIterator(Iterator<Cell> cells, long now)
++        public SparseRowIterator(CellNameType type, Iterator<Cell> cells, long now)
 +        {
++            this.type = type;
 +            this.cells = cells;
 +            this.now = now;
 +            this.staticRow = hasNextCell() && nextCell.name().isStatic()
 +                           ? computeNext()
 +                           : null;
 +        }
 +
 +        public CQL3Row getStaticRow()
 +        {
 +            return staticRow;
 +        }
 +
 +        private boolean hasNextCell()
 +        {
 +            if (nextCell != null)
 +                return true;
 +
 +            while (cells.hasNext())
 +            {
 +                Cell cell = cells.next();
 +                if (cell.isMarkedForDelete(now))
 +                    continue;
 +
 +                nextCell = cell;
 +                return true;
 +            }
 +            return false;
 +        }
 +
 +        protected CQL3Row computeNext()
 +        {
 +            while (hasNextCell())
 +            {
 +                CQL3Row toReturn = null;
 +                CellName current = nextCell.name();
-                 if (currentRow == null || !current.isSameCQL3RowAs(previous))
++                if (currentRow == null || !current.isSameCQL3RowAs(type, previous))
 +                {
 +                    toReturn = currentRow;
 +                    currentRow = new CQL3RowOfSparse(current);
 +                }
 +                currentRow.add(nextCell);
 +                nextCell = null;
 +                previous = current;
 +
 +                if (toReturn != null)
 +                    return toReturn;
 +            }
 +            if (currentRow != null)
 +            {
 +                CQL3Row toReturn = currentRow;
 +                currentRow = null;
 +                return toReturn;
 +            }
 +            return endOfData();
 +        }
 +    }
 +
 +    private static class CQL3RowOfSparse implements CQL3Row
 +    {
 +        private final CellName cell;
 +        private Map<ColumnIdentifier, Cell> columns;
 +        private Map<ColumnIdentifier, List<Cell>> collections;
 +
 +        CQL3RowOfSparse(CellName cell)
 +        {
 +            this.cell = cell;
 +        }
 +
 +        public ByteBuffer getClusteringColumn(int i)
 +        {
 +            return cell.get(i);
 +        }
 +
 +        void add(Cell cell)
 +        {
 +            CellName cellName = cell.name();
 +            ColumnIdentifier columnName =  cellName.cql3ColumnName();
 +            if (cellName.isCollectionCell())
 +            {
 +                if (collections == null)
 +                    collections = new HashMap<>();
 +
 +                List<Cell> values = collections.get(columnName);
 +                if (values == null)
 +                {
 +                    values = new ArrayList<Cell>();
 +                    collections.put(columnName, values);
 +                }
 +                values.add(cell);
 +            }
 +            else
 +            {
 +                if (columns == null)
 +                    columns = new HashMap<>();
 +                columns.put(columnName, cell);
 +            }
 +        }
 +
 +        public Cell getColumn(ColumnIdentifier name)
 +        {
 +            return columns == null ? null : columns.get(name);
 +        }
 +
 +        public List<Cell> getCollection(ColumnIdentifier name)
 +        {
 +            return collections == null ? null : collections.get(name);
 +        }
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d67e852/src/java/org/apache/cassandra/db/composites/CellName.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/composites/CellName.java
index d55243e,0000000..202d73a
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/composites/CellName.java
+++ b/src/java/org/apache/cassandra/db/composites/CellName.java
@@@ -1,76 -1,0 +1,76 @@@
 +/*
 + * 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.db.composites;
 +
 +import java.nio.ByteBuffer;
 +
 +import org.apache.cassandra.cql3.ColumnIdentifier;
 +import org.apache.cassandra.utils.memory.AbstractAllocator;
 +
 +/**
 + * A CellName is a Composite, but for which, for the sake of CQL3, we
 + * distinguish different parts: a CellName has first a number of clustering
 + * components, followed by the CQL3 column name, and then possibly followed by
 + * a collection element part.
 + *
 + * The clustering prefix can itself be composed of multiple component. It can
 + * also be empty if the table has no clustering keys. In general, the CQL3
 + * column name follows. However, some type of COMPACT STORAGE layout do not
 + * store the CQL3 column name in the cell name and so this part can be null (we
 + * call "dense" the cells whose name don't store the CQL3 column name).
 + *
 + * Lastly, if the cell is part of a CQL3 collection, we'll have a last
 + * component (a UUID for lists, an element for sets and a key for maps).
 + */
 +public interface CellName extends Composite
 +{
 +    /**
 +     * The number of clustering components.
 +     *
 +     * It can be 0 if the table has no clustering columns, and it can be
 +     * equal to size() if the table is dense() (in which case cql3ColumnName()
 +     * will be null).
 +     */
 +    public int clusteringSize();
 +
 +    /**
 +     * The name of the CQL3 column this cell represents.
 +     *
 +     * Will be null for cells of "dense" tables.
 +     */
 +    public ColumnIdentifier cql3ColumnName();
 +
 +    /**
 +     * The value of the collection element, or null if the cell is not part
 +     * of a collection (i.e. if !isCollectionCell()).
 +     */
 +    public ByteBuffer collectionElement();
 +    public boolean isCollectionCell();
 +
 +    /**
 +     * Whether this cell is part of the same CQL3 row as the other cell.
 +     */
-     public boolean isSameCQL3RowAs(CellName other);
++    public boolean isSameCQL3RowAs(CellNameType type, CellName other);
 +
 +    // If cellnames were sharing some prefix components, this will break it, so
 +    // we might want to try to do better.
 +    @Override
 +    public CellName copy(AbstractAllocator allocator);
 +
 +    public long excessHeapSizeExcludingData();
 +}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d67e852/src/java/org/apache/cassandra/db/composites/CompoundDenseCellName.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/composites/CompoundDenseCellName.java
index 0f5b2f5,0000000..db80043
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/composites/CompoundDenseCellName.java
+++ b/src/java/org/apache/cassandra/db/composites/CompoundDenseCellName.java
@@@ -1,85 -1,0 +1,85 @@@
 +/*
 + * 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.db.composites;
 +
 +import java.nio.ByteBuffer;
 +
 +import org.apache.cassandra.cql3.ColumnIdentifier;
 +import org.apache.cassandra.utils.memory.AbstractAllocator;
 +import org.apache.cassandra.utils.ObjectSizes;
 +
 +public class CompoundDenseCellName extends CompoundComposite implements CellName
 +{
 +
 +    private static final long HEAP_SIZE = ObjectSizes.measure(new CompoundDenseCellName(new ByteBuffer[0]));
 +
 +    // Not meant to be used directly, you should use the CellNameType method instead
 +    CompoundDenseCellName(ByteBuffer[] elements)
 +    {
 +        super(elements, elements.length, false);
 +    }
 +
 +    CompoundDenseCellName(ByteBuffer[] elements, int size)
 +    {
 +        super(elements, size, false);
 +    }
 +
 +    public int clusteringSize()
 +    {
 +        return size;
 +    }
 +
 +    public ColumnIdentifier cql3ColumnName()
 +    {
 +        return null;
 +    }
 +
 +    public ByteBuffer collectionElement()
 +    {
 +        return null;
 +    }
 +
 +    public boolean isCollectionCell()
 +    {
 +        return false;
 +    }
 +
-     public boolean isSameCQL3RowAs(CellName other)
++    public boolean isSameCQL3RowAs(CellNameType type, CellName other)
 +    {
 +        // Dense cell imply one cell by CQL row so no other cell will be the same row.
-         return equals(other);
++        return type.compare(this, other) == 0;
 +    }
 +
 +    @Override
 +    public long unsharedHeapSize()
 +    {
 +        return HEAP_SIZE + ObjectSizes.sizeOnHeapOf(elements);
 +    }
 +
 +    @Override
 +    public long excessHeapSizeExcludingData()
 +    {
 +        return HEAP_SIZE + ObjectSizes.sizeOnHeapExcludingData(elements);
 +    }
 +
 +    public CellName copy(AbstractAllocator allocator)
 +    {
 +        return new CompoundDenseCellName(elementsCopy(allocator));
 +    }
 +
 +}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d67e852/src/java/org/apache/cassandra/db/composites/CompoundSparseCellName.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/composites/CompoundSparseCellName.java
index 0106309,0000000..0be9433
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/composites/CompoundSparseCellName.java
+++ b/src/java/org/apache/cassandra/db/composites/CompoundSparseCellName.java
@@@ -1,175 -1,0 +1,175 @@@
 +/*
 + * 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.db.composites;
 +
 +import java.nio.ByteBuffer;
 +
 +import org.apache.cassandra.cql3.ColumnIdentifier;
 +import org.apache.cassandra.utils.ByteBufferUtil;
 +import org.apache.cassandra.utils.memory.AbstractAllocator;
 +import org.apache.cassandra.utils.ObjectSizes;
 +import org.apache.cassandra.utils.memory.PoolAllocator;
 +
 +public class CompoundSparseCellName extends CompoundComposite implements CellName
 +{
 +    private static final ByteBuffer[] EMPTY_PREFIX = new ByteBuffer[0];
 +
 +    private static final long HEAP_SIZE = ObjectSizes.measure(new CompoundSparseCellName(null, false));
 +
 +    protected final ColumnIdentifier columnName;
 +
 +    // Not meant to be used directly, you should use the CellNameType method instead
 +    CompoundSparseCellName(ColumnIdentifier columnName, boolean isStatic)
 +    {
 +        this(EMPTY_PREFIX, columnName, isStatic);
 +    }
 +
 +    CompoundSparseCellName(ByteBuffer[] elements, ColumnIdentifier columnName, boolean isStatic)
 +    {
 +        this(elements, elements.length, columnName, isStatic);
 +    }
 +
 +    CompoundSparseCellName(ByteBuffer[] elements, int size, ColumnIdentifier columnName, boolean isStatic)
 +    {
 +        super(elements, size, isStatic);
 +        this.columnName = columnName;
 +    }
 +
 +    public int size()
 +    {
 +        return size + 1;
 +    }
 +
 +    public ByteBuffer get(int i)
 +    {
 +        return i == size ? columnName.bytes : elements[i];
 +    }
 +
 +    public int clusteringSize()
 +    {
 +        return size;
 +    }
 +
 +    public ColumnIdentifier cql3ColumnName()
 +    {
 +        return columnName;
 +    }
 +
 +    public ByteBuffer collectionElement()
 +    {
 +        return null;
 +    }
 +
 +    public boolean isCollectionCell()
 +    {
 +        return false;
 +    }
 +
-     public boolean isSameCQL3RowAs(CellName other)
++    public boolean isSameCQL3RowAs(CellNameType type, CellName other)
 +    {
 +        if (clusteringSize() != other.clusteringSize() || other.isStatic() != isStatic())
 +            return false;
 +
 +        for (int i = 0; i < clusteringSize(); i++)
 +        {
-             if (!elements[i].equals(other.get(i)))
++            if (type.subtype(i).compare(elements[i], other.get(i)) != 0)
 +                return false;
 +        }
 +        return true;
 +    }
 +
 +    public CellName copy(AbstractAllocator allocator)
 +    {
 +        if (elements.length == 0)
 +            return this;
 +
 +        // We don't copy columnName because it's interned in SparseCellNameType
 +        return new CompoundSparseCellName(elementsCopy(allocator), columnName, isStatic());
 +    }
 +
 +    public static class WithCollection extends CompoundSparseCellName
 +    {
 +        private static final long HEAP_SIZE = ObjectSizes.measure(new WithCollection(null, ByteBufferUtil.EMPTY_BYTE_BUFFER, false));
 +
 +        private final ByteBuffer collectionElement;
 +
 +        WithCollection(ColumnIdentifier columnName, ByteBuffer collectionElement, boolean isStatic)
 +        {
 +            this(EMPTY_PREFIX, columnName, collectionElement, isStatic);
 +        }
 +
 +        WithCollection(ByteBuffer[] elements, ColumnIdentifier columnName, ByteBuffer collectionElement, boolean isStatic)
 +        {
 +            this(elements, elements.length, columnName, collectionElement, isStatic);
 +        }
 +
 +        WithCollection(ByteBuffer[] elements, int size, ColumnIdentifier columnName, ByteBuffer collectionElement, boolean isStatic)
 +        {
 +            super(elements, size, columnName, isStatic);
 +            this.collectionElement = collectionElement;
 +        }
 +
 +        public int size()
 +        {
 +            return size + 2;
 +        }
 +
 +        public ByteBuffer get(int i)
 +        {
 +            return i == size + 1 ? collectionElement : super.get(i);
 +        }
 +
 +        @Override
 +        public ByteBuffer collectionElement()
 +        {
 +            return collectionElement;
 +        }
 +
 +        @Override
 +        public boolean isCollectionCell()
 +        {
 +            return true;
 +        }
 +
 +        @Override
 +        public CellName copy(AbstractAllocator allocator)
 +        {
 +            // We don't copy columnName because it's interned in SparseCellNameType
 +            return new CompoundSparseCellName.WithCollection(elements.length == 0 ? elements : elementsCopy(allocator), size, columnName, allocator.clone(collectionElement), isStatic());
 +        }
 +
 +        @Override
 +        public long unsharedHeapSize()
 +        {
 +            return super.unsharedHeapSize() + ObjectSizes.sizeOnHeapOf(collectionElement);
 +        }
 +
 +        @Override
 +        public long excessHeapSizeExcludingData()
 +        {
 +            return super.excessHeapSizeExcludingData() + ObjectSizes.sizeOnHeapExcludingData(collectionElement);
 +        }
 +
 +        @Override
 +        public void free(PoolAllocator<?> allocator)
 +        {
 +            super.free(allocator);
 +            allocator.free(collectionElement);
 +        }
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d67e852/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
index 44acf21,0000000..4f58e48
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
@@@ -1,301 -1,0 +1,301 @@@
 +/*
 + * 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.db.composites;
 +
 +import java.nio.ByteBuffer;
 +import java.util.*;
 +
 +import org.apache.cassandra.config.ColumnDefinition;
 +import org.apache.cassandra.cql3.CQL3Row;
 +import org.apache.cassandra.cql3.ColumnIdentifier;
 +import org.apache.cassandra.db.marshal.AbstractType;
 +import org.apache.cassandra.db.marshal.CollectionType;
 +import org.apache.cassandra.db.marshal.ColumnToCollectionType;
 +import org.apache.cassandra.db.marshal.UTF8Type;
 +import org.apache.cassandra.utils.ByteBufferUtil;
 +import org.apache.cassandra.utils.memory.AbstractAllocator;
 +import org.apache.cassandra.utils.memory.PoolAllocator;
 +
 +public class CompoundSparseCellNameType extends AbstractCompoundCellNameType
 +{
 +    private static final ColumnIdentifier rowMarkerId = new ColumnIdentifier(ByteBufferUtil.EMPTY_BYTE_BUFFER, UTF8Type.instance);
 +    private static final CellName rowMarkerNoPrefix = new CompoundSparseCellName(rowMarkerId, false);
 +
 +    // For CQL3 columns, this is always UTF8Type. However, for compatibility with super columns, we need to allow it to be non-UTF8.
 +    private final AbstractType<?> columnNameType;
 +    protected final Map<ByteBuffer, ColumnIdentifier> internedIds;
 +
 +    private final Composite staticPrefix;
 +
 +    public CompoundSparseCellNameType(List<AbstractType<?>> types)
 +    {
 +        this(types, UTF8Type.instance);
 +    }
 +
 +    public CompoundSparseCellNameType(List<AbstractType<?>> types, AbstractType<?> columnNameType)
 +    {
 +        this(new CompoundCType(types), columnNameType);
 +    }
 +
 +    private CompoundSparseCellNameType(CompoundCType clusteringType, AbstractType<?> columnNameType)
 +    {
 +        this(clusteringType, columnNameType, makeCType(clusteringType, columnNameType, null), new HashMap<ByteBuffer, ColumnIdentifier>());
 +    }
 +
 +    private CompoundSparseCellNameType(CompoundCType clusteringType, AbstractType<?> columnNameType, CompoundCType fullType, Map<ByteBuffer, ColumnIdentifier> internedIds)
 +    {
 +        super(clusteringType, fullType);
 +        this.columnNameType = columnNameType;
 +        this.internedIds = internedIds;
 +        this.staticPrefix = makeStaticPrefix(clusteringType.size());
 +    }
 +
 +    private static Composite makeStaticPrefix(int size)
 +    {
 +        ByteBuffer[] elements = new ByteBuffer[size];
 +        for (int i = 0; i < size; i++)
 +            elements[i] = ByteBufferUtil.EMPTY_BYTE_BUFFER;
 +
 +        return new CompoundComposite(elements, size, true)
 +        {
 +            @Override
 +            public boolean isStatic()
 +            {
 +                return true;
 +            }
 +
 +            @Override
 +            public long unsharedHeapSize()
 +            {
 +                // We'll share this for a given type.
 +                return 0;
 +            }
 +
 +            @Override
 +            public Composite copy(AbstractAllocator allocator)
 +            {
 +                return this;
 +            }
 +
 +            @Override
 +            public void free(PoolAllocator<?> allocator)
 +            {
 +            }
 +        };
 +    }
 +
 +    protected static CompoundCType makeCType(CompoundCType clusteringType, AbstractType<?> columnNameType, ColumnToCollectionType collectionType)
 +    {
 +        List<AbstractType<?>> allSubtypes = new ArrayList<AbstractType<?>>(clusteringType.size() + (collectionType == null ? 1 : 2));
 +        for (int i = 0; i < clusteringType.size(); i++)
 +            allSubtypes.add(clusteringType.subtype(i));
 +        allSubtypes.add(columnNameType);
 +        if (collectionType != null)
 +            allSubtypes.add(collectionType);
 +        return new CompoundCType(allSubtypes);
 +    }
 +
 +    public CellNameType setSubtype(int position, AbstractType<?> newType)
 +    {
 +        if (position < clusteringSize)
 +            return new CompoundSparseCellNameType(clusteringType.setSubtype(position, newType), columnNameType, fullType.setSubtype(position, newType), internedIds);
 +
 +        if (position == clusteringSize)
 +            throw new IllegalArgumentException();
 +
 +        throw new IndexOutOfBoundsException();
 +    }
 +
 +    @Override
 +    public CellNameType addOrUpdateCollection(ColumnIdentifier columnName, CollectionType newCollection)
 +    {
 +        return new WithCollection(clusteringType, ColumnToCollectionType.getInstance(Collections.singletonMap(columnName.bytes, newCollection)), internedIds);
 +    }
 +
 +    public boolean isDense()
 +    {
 +        return false;
 +    }
 +
 +    public boolean supportCollections()
 +    {
 +        return true;
 +    }
 +
 +    public Composite staticPrefix()
 +    {
 +        return staticPrefix;
 +    }
 +
 +    public CellName create(Composite prefix, ColumnDefinition column)
 +    {
 +        return create(prefix, column.name, column.isStatic());
 +    }
 +
 +    private CellName create(Composite prefix, ColumnIdentifier columnName, boolean isStatic)
 +    {
 +        if (isStatic)
 +            prefix = staticPrefix();
 +
 +        assert prefix.size() == clusteringSize;
 +
 +        if (prefix.isEmpty())
 +            return new CompoundSparseCellName(columnName, isStatic);
 +
 +        assert prefix instanceof CompoundComposite;
 +        CompoundComposite lc = (CompoundComposite)prefix;
 +        return new CompoundSparseCellName(lc.elements, clusteringSize, columnName, isStatic);
 +    }
 +
 +    public CellName rowMarker(Composite prefix)
 +    {
 +        assert !prefix.isStatic(); // static columns don't really create rows, they shouldn't have a row marker
 +        if (prefix.isEmpty())
 +            return rowMarkerNoPrefix;
 +
 +        return create(prefix, rowMarkerId, false);
 +    }
 +
 +    protected ColumnIdentifier idFor(ByteBuffer bb)
 +    {
 +        ColumnIdentifier id = internedIds.get(bb);
 +        return id == null ? new ColumnIdentifier(bb, columnNameType) : id;
 +    }
 +
 +    protected Composite makeWith(ByteBuffer[] components, int size, Composite.EOC eoc, boolean isStatic)
 +    {
 +        if (size < clusteringSize + 1 || eoc != Composite.EOC.NONE)
 +            return new CompoundComposite(components, size, isStatic).withEOC(eoc);
 +
 +        return new CompoundSparseCellName(components, clusteringSize, idFor(components[clusteringSize]), isStatic);
 +    }
 +
 +    protected Composite copyAndMakeWith(ByteBuffer[] components, int size, Composite.EOC eoc, boolean isStatic)
 +    {
 +        if (size < clusteringSize + 1 || eoc != Composite.EOC.NONE)
 +            return new CompoundComposite(Arrays.copyOfRange(components, 0, size), size, isStatic).withEOC(eoc);
 +
 +        ByteBuffer[] clusteringColumns = Arrays.copyOfRange(components, 0, clusteringSize);
 +        return new CompoundSparseCellName(clusteringColumns, idFor(components[clusteringSize]), isStatic);
 +    }
 +
 +    public void addCQL3Column(ColumnIdentifier id)
 +    {
 +        internedIds.put(id.bytes, id);
 +    }
 +
 +    public void removeCQL3Column(ColumnIdentifier id)
 +    {
 +        internedIds.remove(id.bytes);
 +    }
 +
 +    public CQL3Row.Builder CQL3RowBuilder(long now)
 +    {
-         return makeSparseCQL3RowBuilder(now);
++        return makeSparseCQL3RowBuilder(this, now);
 +    }
 +
 +    public static class WithCollection extends CompoundSparseCellNameType
 +    {
 +        private final ColumnToCollectionType collectionType;
 +
 +        public WithCollection(List<AbstractType<?>> types, ColumnToCollectionType collectionType)
 +        {
 +            this(new CompoundCType(types), collectionType);
 +        }
 +
 +        WithCollection(CompoundCType clusteringType, ColumnToCollectionType collectionType)
 +        {
 +            this(clusteringType, collectionType, new HashMap<ByteBuffer, ColumnIdentifier>());
 +        }
 +
 +        private WithCollection(CompoundCType clusteringType, ColumnToCollectionType collectionType, Map<ByteBuffer, ColumnIdentifier> internedIds)
 +        {
 +            this(clusteringType, makeCType(clusteringType, UTF8Type.instance, collectionType), collectionType, internedIds);
 +        }
 +
 +        private WithCollection(CompoundCType clusteringType, CompoundCType fullCType, ColumnToCollectionType collectionType, Map<ByteBuffer, ColumnIdentifier> internedIds)
 +        {
 +            super(clusteringType, UTF8Type.instance, fullCType, internedIds);
 +            this.collectionType = collectionType;
 +        }
 +
 +        @Override
 +        public CellNameType setSubtype(int position, AbstractType<?> newType)
 +        {
 +            if (position < clusteringSize)
 +                return new WithCollection(clusteringType.setSubtype(position, newType), collectionType, internedIds);
 +
 +            throw position >= fullType.size() ? new IndexOutOfBoundsException() : new IllegalArgumentException();
 +        }
 +
 +        @Override
 +        public CellNameType addOrUpdateCollection(ColumnIdentifier columnName, CollectionType newCollection)
 +        {
 +            Map<ByteBuffer, CollectionType> newMap = new HashMap<>(collectionType.defined);
 +            newMap.put(columnName.bytes, newCollection);
 +            return new WithCollection(clusteringType, ColumnToCollectionType.getInstance(newMap), internedIds);
 +        }
 +
 +        @Override
 +        public CellName create(Composite prefix, ColumnDefinition column, ByteBuffer collectionElement)
 +        {
 +            if (column.isStatic())
 +                prefix = staticPrefix();
 +
 +            assert prefix.size() == clusteringSize;
 +
 +            if (prefix.isEmpty())
 +                return new CompoundSparseCellName.WithCollection(column.name, collectionElement, column.isStatic());
 +
 +            assert prefix instanceof CompoundComposite;
 +            CompoundComposite lc = (CompoundComposite)prefix;
 +            return new CompoundSparseCellName.WithCollection(lc.elements, clusteringSize, column.name, collectionElement, column.isStatic());
 +        }
 +
 +        @Override
 +        public boolean hasCollections()
 +        {
 +            return true;
 +        }
 +
 +        @Override
 +        public ColumnToCollectionType collectionType()
 +        {
 +            return collectionType;
 +        }
 +
 +        @Override
 +        protected Composite makeWith(ByteBuffer[] components, int size, Composite.EOC eoc, boolean isStatic)
 +        {
 +            if (size < fullSize)
 +                return super.makeWith(components, size, eoc, isStatic);
 +
 +            return new CompoundSparseCellName.WithCollection(components, clusteringSize, idFor(components[clusteringSize]), components[fullSize - 1], isStatic);
 +        }
 +
 +        protected Composite copyAndMakeWith(ByteBuffer[] components, int size, Composite.EOC eoc, boolean isStatic)
 +        {
 +            if (size < fullSize)
 +                return super.copyAndMakeWith(components, size, eoc, isStatic);
 +
 +            ByteBuffer[] clusteringColumns = Arrays.copyOfRange(components, 0, clusteringSize);
 +            return new CompoundSparseCellName.WithCollection(clusteringColumns, idFor(components[clusteringSize]), components[clusteringSize + 1], isStatic);
 +        }
 +    }
 +}
 +

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d67e852/src/java/org/apache/cassandra/db/composites/SimpleDenseCellName.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/composites/SimpleDenseCellName.java
index a72c458,0000000..a4fb9dc
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/composites/SimpleDenseCellName.java
+++ b/src/java/org/apache/cassandra/db/composites/SimpleDenseCellName.java
@@@ -1,82 -1,0 +1,82 @@@
 +/*
 + * 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.db.composites;
 +
 +import java.nio.ByteBuffer;
 +
 +import org.apache.cassandra.cql3.ColumnIdentifier;
 +import org.apache.cassandra.utils.memory.AbstractAllocator;
 +import org.apache.cassandra.utils.ObjectSizes;
 +
 +public class SimpleDenseCellName extends SimpleComposite implements CellName
 +{
 +    private static final long EMPTY_SIZE = ObjectSizes.measure(new SimpleDenseCellName(ByteBuffer.allocate(1)));
 +
 +    // Not meant to be used directly, you should use the CellNameType method instead
 +    SimpleDenseCellName(ByteBuffer element)
 +    {
 +        super(element);
 +    }
 +
 +    public int clusteringSize()
 +    {
 +        return 1;
 +    }
 +
 +    public ColumnIdentifier cql3ColumnName()
 +    {
 +        return null;
 +    }
 +
 +    public ByteBuffer collectionElement()
 +    {
 +        return null;
 +    }
 +
 +    public boolean isCollectionCell()
 +    {
 +        return false;
 +    }
 +
-     public boolean isSameCQL3RowAs(CellName other)
++    public boolean isSameCQL3RowAs(CellNameType type, CellName other)
 +    {
 +        // Dense cell imply one cell by CQL row so no other cell will be the same row.
-         return equals(other);
++        return type.compare(this, other) == 0;
 +    }
 +
 +    @Override
 +    public long unsharedHeapSize()
 +    {
 +        return EMPTY_SIZE + ObjectSizes.sizeOnHeapOf(element);
 +    }
 +
 +    @Override
 +    public long excessHeapSizeExcludingData()
 +    {
 +        return EMPTY_SIZE + ObjectSizes.sizeOnHeapExcludingData(element);
 +    }
 +
 +    // If cellnames were sharing some prefix components, this will break it, so
 +    // we might want to try to do better.
 +    @Override
 +    public CellName copy(AbstractAllocator allocator)
 +    {
 +        return new SimpleDenseCellName(allocator.clone(element));
 +    }
 +
 +}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d67e852/src/java/org/apache/cassandra/db/composites/SimpleSparseCellName.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/composites/SimpleSparseCellName.java
index 7e6a357,0000000..3f9fd7d
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/composites/SimpleSparseCellName.java
+++ b/src/java/org/apache/cassandra/db/composites/SimpleSparseCellName.java
@@@ -1,109 -1,0 +1,109 @@@
 +/*
 + * 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.db.composites;
 +
 +import java.nio.ByteBuffer;
 +
 +import org.apache.cassandra.cql3.ColumnIdentifier;
 +import org.apache.cassandra.utils.memory.AbstractAllocator;
 +import org.apache.cassandra.utils.ObjectSizes;
 +import org.apache.cassandra.utils.memory.PoolAllocator;
 +
 +public class SimpleSparseCellName extends AbstractComposite implements CellName
 +{
 +    private static final long EMPTY_SIZE = ObjectSizes.measure(new SimpleSparseCellName(null));
 +
 +    private final ColumnIdentifier columnName;
 +
 +    // Not meant to be used directly, you should use the CellNameType method instead
 +    SimpleSparseCellName(ColumnIdentifier columnName)
 +    {
 +        this.columnName = columnName;
 +    }
 +
 +    public int size()
 +    {
 +        return 1;
 +    }
 +
 +    public ByteBuffer get(int i)
 +    {
 +        if (i != 0)
 +            throw new IndexOutOfBoundsException();
 +
 +        return columnName.bytes;
 +    }
 +
 +    @Override
 +    public Composite withEOC(EOC newEoc)
 +    {
 +        // EOC makes no sense for not truly composites.
 +        return this;
 +    }
 +
 +    @Override
 +    public ByteBuffer toByteBuffer()
 +    {
 +        return columnName.bytes;
 +    }
 +
 +    public int clusteringSize()
 +    {
 +        return 0;
 +    }
 +
 +    public ColumnIdentifier cql3ColumnName()
 +    {
 +        return columnName;
 +    }
 +
 +    public ByteBuffer collectionElement()
 +    {
 +        return null;
 +    }
 +
 +    public boolean isCollectionCell()
 +    {
 +        return false;
 +    }
 +
-     public boolean isSameCQL3RowAs(CellName other)
++    public boolean isSameCQL3RowAs(CellNameType type, CellName other)
 +    {
 +        return true;
 +    }
 +
 +    public long excessHeapSizeExcludingData()
 +    {
 +        return EMPTY_SIZE + columnName.excessHeapSizeExcludingData();
 +    }
 +
 +    public long unsharedHeapSize()
 +    {
 +        return EMPTY_SIZE + columnName.unsharedHeapSize();
 +    }
 +
 +    public CellName copy(AbstractAllocator allocator)
 +    {
 +        return new SimpleSparseCellName(columnName.clone(allocator));
 +    }
 +
 +    public void free(PoolAllocator<?> allocator)
 +    {
 +        allocator.free(columnName.bytes);
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d67e852/src/java/org/apache/cassandra/db/composites/SimpleSparseCellNameType.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/composites/SimpleSparseCellNameType.java
index 0f63a6a,0000000..8b446fa
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/composites/SimpleSparseCellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/SimpleSparseCellNameType.java
@@@ -1,99 -1,0 +1,99 @@@
 +/*
 + * 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.db.composites;
 +
 +import java.nio.ByteBuffer;
 +import java.util.HashMap;
 +import java.util.Map;
 +
 +import org.apache.cassandra.config.ColumnDefinition;
 +import org.apache.cassandra.cql3.CQL3Row;
 +import org.apache.cassandra.cql3.ColumnIdentifier;
 +import org.apache.cassandra.db.marshal.AbstractType;
 +
 +public class SimpleSparseCellNameType extends AbstractSimpleCellNameType
 +{
 +    // Simple sparse means static thrift CF or non-clustered CQL3. This means that cell names will mainly
 +    // be those that have been declared and we can intern the whole CellName instances.
 +    private final Map<ByteBuffer, CellName> internedNames;
 +
 +    public SimpleSparseCellNameType(AbstractType<?> type)
 +    {
 +        this(type, new HashMap<ByteBuffer, CellName>());
 +    }
 +
 +    private SimpleSparseCellNameType(AbstractType<?> type, Map<ByteBuffer, CellName> internedNames)
 +    {
 +        super(type);
 +        this.internedNames = internedNames;
 +    }
 +
 +    public int clusteringPrefixSize()
 +    {
 +        return 0;
 +    }
 +
 +    public CellNameType setSubtype(int position, AbstractType<?> newType)
 +    {
 +        if (position != 0)
 +            throw new IllegalArgumentException();
 +        return new SimpleSparseCellNameType(newType, internedNames);
 +    }
 +
 +    public CBuilder prefixBuilder()
 +    {
 +        return Composites.EMPTY_BUILDER;
 +    }
 +
 +    public boolean isDense()
 +    {
 +        return false;
 +    }
 +
 +    public CellName create(Composite prefix, ColumnDefinition column)
 +    {
 +        assert prefix.isEmpty();
 +        CellName cn = internedNames.get(column.name.bytes);
 +        return cn == null ? new SimpleSparseCellName(column.name) : cn;
 +    }
 +
 +    @Override
 +    public Composite fromByteBuffer(ByteBuffer bb)
 +    {
 +        if (!bb.hasRemaining())
 +            return Composites.EMPTY;
 +
 +        CellName cn = internedNames.get(bb);
 +        return cn == null ? new SimpleSparseCellName(new ColumnIdentifier(bb, type)) : cn;
 +    }
 +
 +    public void addCQL3Column(ColumnIdentifier id)
 +    {
 +        internedNames.put(id.bytes, new SimpleSparseInternedCellName(id));
 +    }
 +
 +    public void removeCQL3Column(ColumnIdentifier id)
 +    {
 +        internedNames.remove(id.bytes);
 +    }
 +
 +    public CQL3Row.Builder CQL3RowBuilder(long now)
 +    {
-         return makeSparseCQL3RowBuilder(now);
++        return makeSparseCQL3RowBuilder(this, now);
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d67e852/src/java/org/apache/cassandra/db/filter/ColumnSlice.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/filter/ColumnSlice.java
index 19d26c7,9eff12a..821e19a
--- a/src/java/org/apache/cassandra/db/filter/ColumnSlice.java
+++ b/src/java/org/apache/cassandra/db/filter/ColumnSlice.java
@@@ -186,95 -162,4 +186,95 @@@ public class ColumnSlic
              return computeNext();
          }
      }
 +
 +    private static Cell fakeCell(Composite name)
 +    {
 +        return new Cell(new FakeCellName(name), ByteBufferUtil.EMPTY_BYTE_BUFFER);
 +    }
 +
 +    /*
 +    * We need to take a slice (headMap/tailMap/subMap) of a CellName map
 +    * based on a Composite. While CellName and Composite are comparable
 +    * and so this should work, I haven't found how to generify it properly.
 +    * So instead we create a "fake" CellName object that just encapsulate
 +    * the prefix. I might not be a valid CellName with respect to the CF
 +    * CellNameType, but this doesn't matter here (since we only care about
 +    * comparison). This is arguably a bit of a hack.
 +    */
 +    private static class FakeCellName extends AbstractComposite implements CellName
 +    {
 +        private final Composite prefix;
 +
 +        private FakeCellName(Composite prefix)
 +        {
 +            this.prefix = prefix;
 +        }
 +
 +        public int size()
 +        {
 +            return prefix.size();
 +        }
 +
 +        public boolean isStatic()
 +        {
 +            return prefix.isStatic();
 +        }
 +
 +        public ByteBuffer get(int i)
 +        {
 +            return prefix.get(i);
 +        }
 +
 +        public Composite.EOC eoc()
 +        {
 +            return prefix.eoc();
 +        }
 +
 +        public int clusteringSize()
 +        {
 +            throw new UnsupportedOperationException();
 +        }
 +
 +        public ColumnIdentifier cql3ColumnName()
 +        {
 +            throw new UnsupportedOperationException();
 +        }
 +
 +        public ByteBuffer collectionElement()
 +        {
 +            throw new UnsupportedOperationException();
 +        }
 +
 +        public boolean isCollectionCell()
 +        {
 +            throw new UnsupportedOperationException();
 +        }
 +
-         public boolean isSameCQL3RowAs(CellName other)
++        public boolean isSameCQL3RowAs(CellNameType type, CellName other)
 +        {
 +            throw new UnsupportedOperationException();
 +        }
 +
 +        public CellName copy(AbstractAllocator allocator)
 +        {
 +            throw new UnsupportedOperationException();
 +        }
 +
 +        @Override
 +        public long excessHeapSizeExcludingData()
 +        {
 +            throw new UnsupportedOperationException();
 +        }
 +
 +        @Override
 +        public void free(PoolAllocator<?> allocator)
 +        {
 +            throw new UnsupportedOperationException();
 +        }
 +
 +        public long unsharedHeapSize()
 +        {
 +            throw new UnsupportedOperationException();
 +        }
 +    }
  }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/5d67e852/test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
index ac2f567,2edf6a8..9d25f78
--- a/test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
+++ b/test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
@@@ -678,7 -689,51 +678,51 @@@ public class ColumnFamilyStoreTest exte
      }
  
      @Test
+     public void testCassandra6778() throws CharacterCodingException
+     {
+         String cfname = "StandardInteger1";
+         Keyspace keyspace = Keyspace.open("Keyspace1");
+         ColumnFamilyStore cfs = keyspace.getColumnFamilyStore(cfname);
+ 
+         // insert two columns that represent the same integer but have different binary forms (the
+         // second one is padded with extra zeros)
 -        RowMutation rm = new RowMutation("Keyspace1", ByteBufferUtil.bytes("k1"));
 -        byte[] column1 = {1};
 -        rm.add(cfname, ByteBuffer.wrap(column1), ByteBufferUtil.bytes("data1"), 1);
++        Mutation rm = new Mutation("Keyspace1", ByteBufferUtil.bytes("k1"));
++        CellName column1 = cellname(ByteBuffer.wrap(new byte[]{1}));
++        rm.add(cfname, column1, ByteBufferUtil.bytes("data1"), 1);
+         rm.apply();
+         cfs.forceBlockingFlush();
+ 
 -        rm = new RowMutation("Keyspace1", ByteBufferUtil.bytes("k1"));
 -        byte[] column2 = {0, 0, 1};
 -        rm.add(cfname, ByteBuffer.wrap(column2), ByteBufferUtil.bytes("data2"), 2);
++        rm = new Mutation("Keyspace1", ByteBufferUtil.bytes("k1"));
++        CellName column2 = cellname(ByteBuffer.wrap(new byte[]{0, 0, 1}));
++        rm.add(cfname, column2, ByteBufferUtil.bytes("data2"), 2);
+         rm.apply();
+         cfs.forceBlockingFlush();
+ 
+         // fetch by the first column name; we should get the second version of the column value
+         SliceByNamesReadCommand cmd = new SliceByNamesReadCommand(
+             "Keyspace1", ByteBufferUtil.bytes("k1"), cfname, System.currentTimeMillis(),
 -            new NamesQueryFilter(FBUtilities.singleton(ByteBuffer.wrap(column1), cfs.getComparator())));
++            new NamesQueryFilter(FBUtilities.singleton(column1, cfs.getComparator())));
+ 
+         ColumnFamily cf = cmd.getRow(keyspace).cf;
+         assertEquals(1, cf.getColumnCount());
 -        Column column = cf.getColumn(ByteBuffer.wrap(column1));
 -        assertEquals("data2", ByteBufferUtil.string(column.value()));
 -        assertEquals(ByteBuffer.wrap(column2), column.name());
++        Cell cell = cf.getColumn(column1);
++        assertEquals("data2", ByteBufferUtil.string(cell.value()));
++        assertEquals(column2, cell.name());
+ 
+         // fetch by the second column name; we should get the second version of the column value
+         cmd = new SliceByNamesReadCommand(
+             "Keyspace1", ByteBufferUtil.bytes("k1"), cfname, System.currentTimeMillis(),
 -            new NamesQueryFilter(FBUtilities.singleton(ByteBuffer.wrap(column2), cfs.getComparator())));
++            new NamesQueryFilter(FBUtilities.singleton(column2, cfs.getComparator())));
+ 
+         cf = cmd.getRow(keyspace).cf;
+         assertEquals(1, cf.getColumnCount());
 -        column = cf.getColumn(ByteBuffer.wrap(column2));
 -        assertEquals("data2", ByteBufferUtil.string(column.value()));
 -        assertEquals(ByteBuffer.wrap(column2), column.name());
++        cell = cf.getColumn(column2);
++        assertEquals("data2", ByteBufferUtil.string(cell.value()));
++        assertEquals(column2, cell.name());
+     }
+ 
+     @Test
 -    public void testInclusiveBounds() throws IOException, ExecutionException, InterruptedException
 +    public void testInclusiveBounds()
      {
          ColumnFamilyStore cfs = insertKey1Key2();
  


Mime
View raw message