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 2014/02/20 17:51:58 UTC
[3/7] Merge branch 'cassandra-2.0' into cassandra-2.1
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/composites/CompoundSparseCellNameType.java
index d0e66f8,0000000..e0cbc0f
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,245 -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);
++ 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 addCollection(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 CellName create(Composite prefix, ColumnIdentifier columnName)
++ 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);
++ return new CompoundSparseCellName(columnName, isStatic);
+
+ assert prefix instanceof CompoundComposite;
+ CompoundComposite lc = (CompoundComposite)prefix;
- return new CompoundSparseCellName(lc.elements, clusteringSize, columnName);
++ 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);
++ 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)
++ 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).withEOC(eoc);
++ return new CompoundComposite(components, size, isStatic).withEOC(eoc);
+
- return new CompoundSparseCellName(components, clusteringSize, idFor(components[clusteringSize]));
++ return new CompoundSparseCellName(components, clusteringSize, idFor(components[clusteringSize]), isStatic);
+ }
+
- protected Composite copyAndMakeWith(ByteBuffer[] components, int size, Composite.EOC eoc)
++ 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).withEOC(eoc);
++ 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]));
++ 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);
+ }
+
+ 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 addCollection(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, ColumnIdentifier columnName, ByteBuffer collectionElement)
++ public CellName create(Composite prefix, ColumnDefinition column, ByteBuffer collectionElement)
+ {
- // We ignore the columnName because it's just the COMPACT_VALUE name which is not store in the cell name
++ if (column.isStatic())
++ prefix = staticPrefix();
++
+ assert prefix.size() == clusteringSize;
+
+ if (prefix.isEmpty())
- return new CompoundSparseCellName.WithCollection(columnName, collectionElement);
++ return new CompoundSparseCellName.WithCollection(column.name, collectionElement, column.isStatic());
+
+ assert prefix instanceof CompoundComposite;
+ CompoundComposite lc = (CompoundComposite)prefix;
- return new CompoundSparseCellName.WithCollection(lc.elements, clusteringSize, columnName, collectionElement);
++ 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)
++ protected Composite makeWith(ByteBuffer[] components, int size, Composite.EOC eoc, boolean isStatic)
+ {
+ if (size < fullSize)
- return super.makeWith(components, size, eoc);
++ return super.makeWith(components, size, eoc, isStatic);
+
- return new CompoundSparseCellName.WithCollection(components, clusteringSize, idFor(components[clusteringSize]), components[fullSize - 1]);
++ return new CompoundSparseCellName.WithCollection(components, clusteringSize, idFor(components[clusteringSize]), components[fullSize - 1], isStatic);
+ }
+
- protected Composite copyAndMakeWith(ByteBuffer[] components, int size, Composite.EOC eoc)
++ protected Composite copyAndMakeWith(ByteBuffer[] components, int size, Composite.EOC eoc, boolean isStatic)
+ {
+ if (size < fullSize)
- return super.copyAndMakeWith(components, size, eoc);
++ 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]);
++ return new CompoundSparseCellName.WithCollection(clusteringColumns, idFor(components[clusteringSize]), components[clusteringSize + 1], isStatic);
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/db/composites/SimpleDenseCellNameType.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/composites/SimpleDenseCellNameType.java
index cafb521,0000000..1aae580
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/composites/SimpleDenseCellNameType.java
+++ b/src/java/org/apache/cassandra/db/composites/SimpleDenseCellNameType.java
@@@ -1,78 -1,0 +1,79 @@@
+/*
+ * 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.config.ColumnDefinition;
+import org.apache.cassandra.cql3.CQL3Row;
+import org.apache.cassandra.cql3.ColumnIdentifier;
+import org.apache.cassandra.db.marshal.AbstractType;
+
+public class SimpleDenseCellNameType extends AbstractSimpleCellNameType
+{
+ public SimpleDenseCellNameType(AbstractType<?> type)
+ {
+ super(type);
+ }
+
+ public int clusteringPrefixSize()
+ {
+ return 1;
+ }
+
+ public CBuilder prefixBuilder()
+ {
+ // Simple dense is "all" prefix
+ return builder();
+ }
+
+ public CellNameType setSubtype(int position, AbstractType<?> newType)
+ {
+ if (position != 0)
+ throw new IllegalArgumentException();
+ return new SimpleDenseCellNameType(newType);
+ }
+
+ public boolean isDense()
+ {
+ return true;
+ }
+
- public CellName create(Composite prefix, ColumnIdentifier columnName)
++ public CellName create(Composite prefix, ColumnDefinition column)
+ {
+ assert prefix.size() == 1;
- // We ignore the columnName because it's just the COMPACT_VALUE name which is not store in the cell name
++ // We ignore the column because it's just the COMPACT_VALUE name which is not store in the cell name
+ return new SimpleDenseCellName(prefix.get(0));
+ }
+
+ @Override
+ public Composite fromByteBuffer(ByteBuffer bb)
+ {
+ return !bb.hasRemaining()
+ ? Composites.EMPTY
+ : new SimpleDenseCellName(bb);
+ }
+
+ public void addCQL3Column(ColumnIdentifier id) {}
+ public void removeCQL3Column(ColumnIdentifier id) {}
+
+ public CQL3Row.Builder CQL3RowBuilder(long now)
+ {
+ return makeDenseCQL3RowBuilder(now);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/db/composites/SimpleSparseCellNameType.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/composites/SimpleSparseCellNameType.java
index 9c99680,0000000..0f63a6a
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,98 -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, ColumnIdentifier columnName)
++ public CellName create(Composite prefix, ColumnDefinition column)
+ {
+ assert prefix.isEmpty();
- CellName cn = internedNames.get(columnName.bytes);
- return cn == null ? new SimpleSparseCellName(columnName) : cn;
++ 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);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/db/filter/ExtendedFilter.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/filter/ExtendedFilter.java
index 29976f6,5aa1ea9..7326d80
--- a/src/java/org/apache/cassandra/db/filter/ExtendedFilter.java
+++ b/src/java/org/apache/cassandra/db/filter/ExtendedFilter.java
@@@ -322,49 -320,20 +322,49 @@@ public abstract class ExtendedFilte
return true;
}
- private ByteBuffer extractDataValue(ColumnDefinition def, ByteBuffer rowKey, ColumnFamily data, ColumnNameBuilder builder)
+ private static boolean collectionSatisfies(ColumnDefinition def, ColumnFamily data, Composite prefix, IndexExpression expr, ByteBuffer collectionElement)
+ {
+ assert def.type.isCollection();
+
+ CollectionType type = (CollectionType)def.type;
+ switch (type.kind)
+ {
+ case LIST:
+ assert collectionElement != null;
- return type.valueComparator().compare(data.getColumn(data.getComparator().create(prefix, def.name, collectionElement)).value(), expr.value) == 0;
++ return type.valueComparator().compare(data.getColumn(data.getComparator().create(prefix, def, collectionElement)).value(), expr.value) == 0;
+ case SET:
- return data.getColumn(data.getComparator().create(prefix, def.name, expr.value)) != null;
++ return data.getColumn(data.getComparator().create(prefix, def, expr.value)) != null;
+ case MAP:
+ if (expr.operator == IndexExpression.Operator.CONTAINS_KEY)
+ {
- return data.getColumn(data.getComparator().create(prefix, def.name, expr.value)) != null;
++ return data.getColumn(data.getComparator().create(prefix, def, expr.value)) != null;
+ }
+ else
+ {
+ assert collectionElement != null;
- return type.valueComparator().compare(data.getColumn(data.getComparator().create(prefix, def.name, collectionElement)).value(), expr.value) == 0;
++ return type.valueComparator().compare(data.getColumn(data.getComparator().create(prefix, def, collectionElement)).value(), expr.value) == 0;
+ }
+ }
+ throw new AssertionError();
+ }
+
+ private ByteBuffer extractDataValue(ColumnDefinition def, ByteBuffer rowKey, ColumnFamily data, Composite prefix)
{
- switch (def.type)
+ switch (def.kind)
{
case PARTITION_KEY:
- return def.componentIndex == null
+ return def.isOnAllComponents()
? rowKey
- : ((CompositeType)data.metadata().getKeyValidator()).split(rowKey)[def.componentIndex];
- case CLUSTERING_KEY:
- return builder.get(def.componentIndex);
+ : ((CompositeType)data.metadata().getKeyValidator()).split(rowKey)[def.position()];
+ case CLUSTERING_COLUMN:
+ return prefix.get(def.position());
case REGULAR:
- ByteBuffer colName = builder == null ? def.name : builder.copy().add(def.name).build();
- Column column = data.getColumn(colName);
- return column == null ? null : column.value();
+ CellName cname = prefix == null
+ ? data.getComparator().cellFromByteBuffer(def.name.bytes)
- : data.getComparator().create(prefix, def.name);
++ : data.getComparator().create(prefix, def);
+
+ Cell cell = data.getColumn(cname);
+ return cell == null ? null : cell.value();
case COMPACT_VALUE:
assert data.getColumnCount() == 1;
return data.getSortedColumns().iterator().next().value();
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/db/index/composites/CompositesIndexOnCollectionKey.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/index/composites/CompositesIndexOnCollectionKey.java
index 36504ca,0000000..c8fc56c
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/index/composites/CompositesIndexOnCollectionKey.java
+++ b/src/java/org/apache/cassandra/db/index/composites/CompositesIndexOnCollectionKey.java
@@@ -1,106 -1,0 +1,106 @@@
+/*
+ * 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.index.composites;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cassandra.config.CFMetaData;
+import org.apache.cassandra.config.ColumnDefinition;
+import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.composites.CBuilder;
+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.composites.CompoundDenseCellNameType;
+import org.apache.cassandra.db.index.SecondaryIndex;
+import org.apache.cassandra.db.marshal.*;
+
+/**
+ * Index on the collection element of the cell name of a collection.
+ *
+ * A cell indexed by this index will have the general form:
+ * ck_0 ... ck_n c_name [col_elt] : v
+ * where ck_i are the cluster keys, c_name the CQL3 column name, col_elt the
+ * collection element that we want to index (which may or may not be there depending
+ * on whether c_name is the collection we're indexing) and v the cell value.
+ *
+ * Such a cell is indexed if c_name is the indexed collection (in which case we are guaranteed to have
+ * col_elt). The index entry will be:
+ * - row key will be col_elt value (getIndexedValue()).
+ * - cell name will be 'rk ck_0 ... ck_n' where rk is the row key of the initial cell.
+ */
+public class CompositesIndexOnCollectionKey extends CompositesIndex
+{
+ public static CellNameType buildIndexComparator(CFMetaData baseMetadata, ColumnDefinition columnDef)
+ {
+ int count = 1 + baseMetadata.clusteringColumns().size(); // row key + clustering prefix
+ List<AbstractType<?>> types = new ArrayList<AbstractType<?>>(count);
+ types.add(SecondaryIndex.keyComparator);
+ for (int i = 0; i < count - 1; i++)
+ types.add(baseMetadata.comparator.subtype(i));
+ return new CompoundDenseCellNameType(types);
+ }
+
+ @Override
+ protected AbstractType<?> getIndexKeyComparator()
+ {
+ return ((CollectionType)columnDef.type).nameComparator();
+ }
+
+ protected ByteBuffer getIndexedValue(ByteBuffer rowKey, Cell cell)
+ {
+ return cell.name().get(columnDef.position() + 1);
+ }
+
+ protected Composite makeIndexColumnPrefix(ByteBuffer rowKey, Composite cellName)
+ {
+ int count = 1 + baseCfs.metadata.clusteringColumns().size();
+ CBuilder builder = getIndexComparator().builder();
+ builder.add(rowKey);
+ for (int i = 0; i < count - 1; i++)
+ builder.add(cellName.get(i));
+ return builder.build();
+ }
+
+ public IndexedEntry decodeEntry(DecoratedKey indexedValue, Cell indexEntry)
+ {
+ int count = 1 + baseCfs.metadata.clusteringColumns().size();
+ CBuilder builder = baseCfs.getComparator().builder();
+ for (int i = 0; i < count - 1; i++)
+ builder.add(indexEntry.name().get(i + 1));
+ return new IndexedEntry(indexedValue, indexEntry.name(), indexEntry.timestamp(), indexEntry.name().get(0), builder.build());
+ }
+
+ @Override
+ public boolean indexes(CellName name)
+ {
+ // We index if the CQL3 column name is the one of the collection we index
+ AbstractType<?> comp = baseCfs.metadata.getColumnDefinitionComparator(columnDef);
+ return name.size() > columnDef.position()
+ && comp.compare(name.get(columnDef.position()), columnDef.name.bytes) == 0;
+ }
+
+ public boolean isStale(IndexedEntry entry, ColumnFamily data, long now)
+ {
- CellName name = data.getComparator().create(entry.indexedEntryPrefix, columnDef.name, entry.indexValue.key);
++ CellName name = data.getComparator().create(entry.indexedEntryPrefix, columnDef, entry.indexValue.key);
+ Cell liveCell = data.getColumn(name);
+ return (liveCell == null || liveCell.isMarkedForDelete(now));
+ }
+}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/db/index/composites/CompositesIndexOnCollectionValue.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/index/composites/CompositesIndexOnCollectionValue.java
index 1d780cd,0000000..9536e2e
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/index/composites/CompositesIndexOnCollectionValue.java
+++ b/src/java/org/apache/cassandra/db/index/composites/CompositesIndexOnCollectionValue.java
@@@ -1,108 -1,0 +1,108 @@@
+/*
+ * 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.index.composites;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cassandra.config.CFMetaData;
+import org.apache.cassandra.config.ColumnDefinition;
+import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.composites.CBuilder;
+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.composites.CompoundDenseCellNameType;
+import org.apache.cassandra.db.index.SecondaryIndex;
+import org.apache.cassandra.db.marshal.*;
+
+/**
+ * Index the value of a collection cell.
+ *
+ * This is a lot like an index on REGULAR, except that we also need to make
+ * the collection key part of the index entry so that:
+ * 1) we don't have to scan the whole collection at query time to know the
+ * entry is stale and if it still satisfies the query.
+ * 2) if a collection has multiple time the same value, we need one entry
+ * for each so that if we delete one of the value only we only delete the
+ * entry corresponding to that value.
+ */
+public class CompositesIndexOnCollectionValue extends CompositesIndex
+{
+ public static CellNameType buildIndexComparator(CFMetaData baseMetadata, ColumnDefinition columnDef)
+ {
+ int prefixSize = columnDef.position();
+ List<AbstractType<?>> types = new ArrayList<AbstractType<?>>(prefixSize + 2);
+ types.add(SecondaryIndex.keyComparator);
+ for (int i = 0; i < prefixSize; i++)
+ types.add(baseMetadata.comparator.subtype(i));
+ types.add(((CollectionType)columnDef.type).nameComparator()); // collection key
+ return new CompoundDenseCellNameType(types);
+ }
+
+ @Override
+ protected AbstractType<?> getIndexKeyComparator()
+ {
+ return ((CollectionType)columnDef.type).valueComparator();
+ }
+
+ protected ByteBuffer getIndexedValue(ByteBuffer rowKey, Cell cell)
+ {
+ return cell.value();
+ }
+
+ protected Composite makeIndexColumnPrefix(ByteBuffer rowKey, Composite cellName)
+ {
+ CBuilder builder = getIndexComparator().prefixBuilder();
+ builder.add(rowKey);
+ for (int i = 0; i < Math.min(columnDef.position(), cellName.size()); i++)
+ builder.add(cellName.get(i));
+ builder.add(cellName.get(columnDef.position() + 1));
+ return builder.build();
+ }
+
+ public IndexedEntry decodeEntry(DecoratedKey indexedValue, Cell indexEntry)
+ {
+ int prefixSize = columnDef.position();
+ CellName name = indexEntry.name();
+ CBuilder builder = baseCfs.getComparator().builder();
+ for (int i = 0; i < prefixSize; i++)
+ builder.add(name.get(i + 1));
+ return new IndexedEntry(indexedValue, name, indexEntry.timestamp(), name.get(0), builder.build(), name.get(prefixSize + 1));
+ }
+
+ @Override
+ public boolean indexes(CellName name)
+ {
+ AbstractType<?> comp = baseCfs.metadata.getColumnDefinitionComparator(columnDef);
+ return name.size() > columnDef.position()
+ && comp.compare(name.get(columnDef.position()), columnDef.name.bytes) == 0;
+ }
+
+ public boolean isStale(IndexedEntry entry, ColumnFamily data, long now)
+ {
- CellName name = data.getComparator().create(entry.indexedEntryPrefix, columnDef.name, entry.indexedEntryCollectionKey);
++ CellName name = data.getComparator().create(entry.indexedEntryPrefix, columnDef, entry.indexedEntryCollectionKey);
+ Cell liveCell = data.getColumn(name);
+ if (liveCell == null || liveCell.isMarkedForDelete(now))
+ return true;
+
+ ByteBuffer liveValue = liveCell.value();
+ return ((CollectionType)columnDef.type).valueComparator().compare(entry.indexValue.key, liveValue) != 0;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/db/index/composites/CompositesIndexOnRegular.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/index/composites/CompositesIndexOnRegular.java
index f1b0954,7159c23..fc2f9db
--- a/src/java/org/apache/cassandra/db/index/composites/CompositesIndexOnRegular.java
+++ b/src/java/org/apache/cassandra/db/index/composites/CompositesIndexOnRegular.java
@@@ -89,12 -93,12 +89,12 @@@ public class CompositesIndexOnRegular e
public boolean isStale(IndexedEntry entry, ColumnFamily data, long now)
{
- CellName name = data.getComparator().create(entry.indexedEntryPrefix, columnDef.name);
- ByteBuffer bb = entry.indexedEntryNameBuilder.copy().add(columnDef.name).build();
- Column liveColumn = data.getColumn(bb);
- if (liveColumn == null || liveColumn.isMarkedForDelete(now))
++ CellName name = data.getComparator().create(entry.indexedEntryPrefix, columnDef);
+ Cell liveCell = data.getColumn(name);
+ if (liveCell == null || liveCell.isMarkedForDelete(now))
return true;
- ByteBuffer liveValue = liveColumn.value();
- return columnDef.getValidator().compare(entry.indexValue.key, liveValue) != 0;
+ ByteBuffer liveValue = liveCell.value();
+ return columnDef.type.compare(entry.indexValue.key, liveValue) != 0;
}
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/db/index/composites/CompositesSearcher.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/index/composites/CompositesSearcher.java
index 41c9f41,eb618f4..e09b2d1
--- a/src/java/org/apache/cassandra/db/index/composites/CompositesSearcher.java
+++ b/src/java/org/apache/cassandra/db/index/composites/CompositesSearcher.java
@@@ -24,17 -24,14 +24,14 @@@ import java.util.*
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.cassandra.cql3.ColumnNameBuilder;
import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.composites.CellNameType;
+import org.apache.cassandra.db.composites.Composite;
+import org.apache.cassandra.db.composites.Composites;
- import org.apache.cassandra.db.filter.ExtendedFilter;
- import org.apache.cassandra.db.filter.IDiskAtomFilter;
- import org.apache.cassandra.db.filter.QueryFilter;
- import org.apache.cassandra.db.filter.SliceQueryFilter;
+ import org.apache.cassandra.db.filter.*;
import org.apache.cassandra.db.index.SecondaryIndexManager;
import org.apache.cassandra.db.index.SecondaryIndexSearcher;
-import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.dht.AbstractBounds;
-import org.apache.cassandra.thrift.IndexExpression;
import org.apache.cassandra.utils.ByteBufferUtil;
public class CompositesSearcher extends SecondaryIndexSearcher
@@@ -249,11 -235,28 +246,21 @@@
// We always query the whole CQL3 row. In the case where the original filter was a name filter this might be
// slightly wasteful, but this probably doesn't matter in practice and it simplify things.
- SliceQueryFilter dataFilter = new SliceQueryFilter(start,
- entry.indexedEntryPrefix.end(),
- false,
- Integer.MAX_VALUE,
- baseCfs.metadata.clusteringColumns().size());
- ColumnSlice dataSlice = new ColumnSlice(start, entry.indexedEntryEnd());
- ColumnSlice[] slices;
- if (baseCfs.metadata.hasStaticColumns())
- {
- // If the table has static columns, we must fetch them too as they may need to be returned too.
- // Note that this is potentially wasteful for 2 reasons:
- // 1) we will retrieve the static parts for each indexed row, even if we have more than one row in
- // the same partition. If we were to group data queries to rows on the same slice, which would
- // speed up things in general, we would also optimize here since we would fetch static columns only
- // once for each group.
- // 2) at this point we don't know if the user asked for static columns or not, so we might be fetching
- // them for nothing. We would however need to ship the list of "CQL3 columns selected" with getRangeSlice
- // to be able to know that.
- // TODO: we should improve both point above
- ColumnSlice staticSlice = new ColumnSlice(ByteBufferUtil.EMPTY_BYTE_BUFFER, baseCfs.metadata.getStaticColumnNameBuilder().buildAsEndOfRange());
- slices = new ColumnSlice[]{ staticSlice, dataSlice };
- }
- else
- {
- slices = new ColumnSlice[]{ dataSlice };
- }
- SliceQueryFilter dataFilter = new SliceQueryFilter(slices, false, Integer.MAX_VALUE, baseCfs.metadata.clusteringKeyColumns().size());
++ ColumnSlice dataSlice = new ColumnSlice(start, entry.indexedEntryPrefix.end());
++ // If the table has static columns, we must fetch them too as they may need to be returned too.
++ // Note that this is potentially wasteful for 2 reasons:
++ // 1) we will retrieve the static parts for each indexed row, even if we have more than one row in
++ // the same partition. If we were to group data queries to rows on the same slice, which would
++ // speed up things in general, we would also optimize here since we would fetch static columns only
++ // once for each group.
++ // 2) at this point we don't know if the user asked for static columns or not, so we might be fetching
++ // them for nothing. We would however need to ship the list of "CQL3 columns selected" with getRangeSlice
++ // to be able to know that.
++ // TODO: we should improve both point above
++ ColumnSlice[] slices = baseCfs.metadata.hasStaticColumns()
++ ? new ColumnSlice[]{ baseCfs.metadata.comparator.staticPrefix().slice(), dataSlice }
++ : new ColumnSlice[]{ dataSlice };
++ SliceQueryFilter dataFilter = new SliceQueryFilter(slices, false, Integer.MAX_VALUE, baseCfs.metadata.clusteringColumns().size());
ColumnFamily newData = baseCfs.getColumnFamily(new QueryFilter(dk, baseCfs.name, dataFilter, filter.timestamp));
if (newData == null || index.isStale(entry, newData, filter.timestamp))
{
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
index be66d21,9250b0f..3184741
--- a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
+++ b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
@@@ -34,15 -34,23 +34,23 @@@ import java.util.List
*/
public abstract class AbstractCompositeType extends AbstractType<ByteBuffer>
{
+
// changes bb position
- protected static int getShortLength(ByteBuffer bb)
+ public static int getShortLength(ByteBuffer bb)
{
int length = (bb.get() & 0xFF) << 8;
return length | (bb.get() & 0xFF);
}
+ // Doesn't change bb position
+ protected static int getShortLength(ByteBuffer bb, int position)
+ {
+ int length = (bb.get(position) & 0xFF) << 8;
+ return length | (bb.get(position + 1) & 0xFF);
+ }
+
// changes bb position
- protected static void putShortLength(ByteBuffer bb, int length)
+ public static void putShortLength(ByteBuffer bb, int length)
{
bb.put((byte) ((length >> 8) & 0xFF));
bb.put((byte) (length & 0xFF));
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/db/marshal/CompositeType.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/hadoop/pig/AbstractCassandraStorage.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/hadoop/pig/AbstractCassandraStorage.java
index 25ffc29,65e3be1..af88853
--- a/src/java/org/apache/cassandra/hadoop/pig/AbstractCassandraStorage.java
+++ b/src/java/org/apache/cassandra/hadoop/pig/AbstractCassandraStorage.java
@@@ -25,8 -25,8 +25,9 @@@ import java.nio.ByteBuffer
import java.nio.charset.CharacterCodingException;
import java.util.*;
+ import com.google.common.collect.Iterables;
+import org.apache.cassandra.db.Cell;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.auth.IAuthenticator;
@@@ -675,12 -674,12 +676,12 @@@ public abstract class AbstractCassandra
return columnDefs;
// otherwise for CqlStorage, check metadata for classic thrift tables
- CFDefinition cfDefinition = getCfDefinition(keyspace, column_family, client);
- for (CFDefinition.Name column : Iterables.concat(cfDefinition.staticColumns(), cfDefinition.regularColumns()))
+ CFMetaData cfm = getCFMetaData(keyspace, column_family, client);
- for (ColumnDefinition def : cfm.regularColumns())
++ for (ColumnDefinition def : cfm.regularAndStaticColumns())
{
ColumnDef cDef = new ColumnDef();
- String columnName = column.name.toString();
- String type = column.type.toString();
+ String columnName = def.name.toString();
+ String type = def.type.toString();
logger.debug("name: {}, type: {} ", columnName, type);
cDef.name = ByteBufferUtil.bytes(columnName);
cDef.validation_class = type;