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:33 UTC
[6/6] git commit: Merge branch 'cassandra-2.0' into cassandra-2.1
Merge branch 'cassandra-2.0' into cassandra-2.1
Conflicts:
src/java/org/apache/cassandra/config/CFMetaData.java
src/java/org/apache/cassandra/config/ColumnDefinition.java
src/java/org/apache/cassandra/cql3/CFDefinition.java
src/java/org/apache/cassandra/cql3/Constants.java
src/java/org/apache/cassandra/cql3/Cql.g
src/java/org/apache/cassandra/cql3/Lists.java
src/java/org/apache/cassandra/cql3/Maps.java
src/java/org/apache/cassandra/cql3/Operation.java
src/java/org/apache/cassandra/cql3/Sets.java
src/java/org/apache/cassandra/cql3/functions/TokenFct.java
src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
src/java/org/apache/cassandra/cql3/statements/ColumnGroupMap.java
src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java
src/java/org/apache/cassandra/cql3/statements/CreateTableStatement.java
src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
src/java/org/apache/cassandra/cql3/statements/Selection.java
src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
src/java/org/apache/cassandra/db/filter/ColumnSlice.java
src/java/org/apache/cassandra/db/index/composites/CompositesSearcher.java
src/java/org/apache/cassandra/hadoop/pig/AbstractCassandraStorage.java
src/java/org/apache/cassandra/hadoop/pig/CqlStorage.java
src/java/org/apache/cassandra/thrift/ThriftValidation.java
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/63b1ef4e
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/63b1ef4e
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/63b1ef4e
Branch: refs/heads/cassandra-2.1
Commit: 63b1ef4eebb26523d69b96cfcf20d9e5ae0b15c0
Parents: a73db3f b09d876
Author: Sylvain Lebresne <sy...@datastax.com>
Authored: Thu Feb 20 17:51:13 2014 +0100
Committer: Sylvain Lebresne <sy...@datastax.com>
Committed: Thu Feb 20 17:51:13 2014 +0100
----------------------------------------------------------------------
CHANGES.txt | 1 +
doc/cql3/CQL.textile | 29 +-
.../org/apache/cassandra/config/CFMetaData.java | 30 +-
.../cassandra/config/ColumnDefinition.java | 16 +
src/java/org/apache/cassandra/cql3/CQL3Row.java | 7 +-
.../apache/cassandra/cql3/ColumnCondition.java | 183 ++++++++++
.../org/apache/cassandra/cql3/Constants.java | 8 +-
src/java/org/apache/cassandra/cql3/Cql.g | 29 +-
src/java/org/apache/cassandra/cql3/Lists.java | 12 +-
src/java/org/apache/cassandra/cql3/Maps.java | 14 +-
src/java/org/apache/cassandra/cql3/Sets.java | 12 +-
.../cql3/statements/AlterTableStatement.java | 30 +-
.../cql3/statements/BatchStatement.java | 162 +++++++--
.../cql3/statements/CQL3CasConditions.java | 164 +++++++++
.../cql3/statements/CreateIndexStatement.java | 9 +
.../cql3/statements/CreateTableStatement.java | 41 ++-
.../cql3/statements/DeleteStatement.java | 23 +-
.../cql3/statements/ModificationStatement.java | 330 ++++++++++---------
.../cql3/statements/SelectStatement.java | 238 +++++++++++--
.../cassandra/cql3/statements/Selection.java | 29 +-
.../cql3/statements/UpdateStatement.java | 20 +-
.../org/apache/cassandra/db/CFRowAdder.java | 10 +-
.../cassandra/db/composites/AbstractCType.java | 7 +-
.../db/composites/AbstractCellNameType.java | 188 +++++++----
.../db/composites/AbstractComposite.java | 17 +-
.../AbstractCompoundCellNameType.java | 37 ++-
.../db/composites/BoundedComposite.java | 5 +
.../cassandra/db/composites/CellNameType.java | 21 +-
.../cassandra/db/composites/Composite.java | 2 +
.../cassandra/db/composites/Composites.java | 5 +
.../cassandra/db/composites/CompoundCType.java | 14 +-
.../db/composites/CompoundComposite.java | 16 +-
.../db/composites/CompoundDenseCellName.java | 2 +-
.../composites/CompoundDenseCellNameType.java | 14 +-
.../db/composites/CompoundSparseCellName.java | 34 +-
.../composites/CompoundSparseCellNameType.java | 98 ++++--
.../db/composites/SimpleDenseCellNameType.java | 5 +-
.../db/composites/SimpleSparseCellNameType.java | 7 +-
.../cassandra/db/filter/ExtendedFilter.java | 10 +-
.../CompositesIndexOnCollectionKey.java | 2 +-
.../CompositesIndexOnCollectionValue.java | 2 +-
.../composites/CompositesIndexOnRegular.java | 2 +-
.../db/index/composites/CompositesSearcher.java | 25 +-
.../db/marshal/AbstractCompositeType.java | 47 +--
.../cassandra/db/marshal/CompositeType.java | 72 +++-
.../db/marshal/DynamicCompositeType.java | 6 +
.../hadoop/pig/AbstractCassandraStorage.java | 3 +-
.../apache/cassandra/service/CASConditions.java | 3 +-
48 files changed, 1552 insertions(+), 489 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/CHANGES.txt
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/doc/cql3/CQL.textile
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/config/CFMetaData.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/config/CFMetaData.java
index ba7e6e6,a319930..25b7314
--- a/src/java/org/apache/cassandra/config/CFMetaData.java
+++ b/src/java/org/apache/cassandra/config/CFMetaData.java
@@@ -26,12 -27,12 +26,13 @@@ import java.util.*
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
+import com.google.common.collect.AbstractIterator;
+ import com.google.common.collect.Iterables;
import com.google.common.collect.MapDifference;
import com.google.common.collect.Maps;
+import org.apache.cassandra.db.composites.*;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.slf4j.Logger;
@@@ -474,10 -405,11 +475,11 @@@ public final class CFMetaDat
public static final String DEFAULT_COLUMN_ALIAS = "column";
public static final String DEFAULT_VALUE_ALIAS = "value";
- private volatile Map<ByteBuffer, ColumnDefinition> column_metadata = new HashMap<>();
+ private volatile Map<ByteBuffer, ColumnDefinition> columnMetadata = new HashMap<>();
private volatile List<ColumnDefinition> partitionKeyColumns; // Always of size keyValidator.componentsCount, null padded if necessary
- private volatile List<ColumnDefinition> clusteringKeyColumns; // Of size comparator.componentsCount or comparator.componentsCount -1, null padded if necessary
- private volatile Set<ColumnDefinition> regularColumns;
- private volatile Set<ColumnDefinition> staticColumns;
+ private volatile List<ColumnDefinition> clusteringColumns; // Of size comparator.componentsCount or comparator.componentsCount -1, null padded if necessary
+ private volatile SortedSet<ColumnDefinition> regularColumns; // We use a sorted set so iteration is of predictable order (for SELECT for instance)
++ private volatile SortedSet<ColumnDefinition> staticColumns; // Same as above
private volatile ColumnDefinition compactValueColumn;
public volatile Class<? extends AbstractCompactionStrategy> compactionStrategyClass = DEFAULT_COMPACTION_STRATEGY_CLASS;
@@@ -793,42 -705,7 +795,46 @@@
public Collection<ColumnDefinition> allColumns()
{
- return column_metadata.values();
+ return columnMetadata.values();
+ }
+
+ // An iterator over all column definitions but that respect the order of a SELECT *.
+ public Iterator<ColumnDefinition> allColumnsInSelectOrder()
+ {
+ return new AbstractIterator<ColumnDefinition>()
+ {
+ private final Iterator<ColumnDefinition> partitionKeyIter = partitionKeyColumns.iterator();
+ private final Iterator<ColumnDefinition> clusteringIter = clusteringColumns.iterator();
+ private boolean valueDone;
++ private final Iterator<ColumnDefinition> staticIter = staticColumns.iterator();
+ private final Iterator<ColumnDefinition> regularIter = regularColumns.iterator();
+
+ protected ColumnDefinition computeNext()
+ {
+ if (partitionKeyIter.hasNext())
+ return partitionKeyIter.next();
+
+ if (clusteringIter.hasNext())
+ return clusteringIter.next();
+
++ if (staticIter.hasNext())
++ return staticIter.next();
++
+ if (compactValueColumn != null && !valueDone)
+ {
+ valueDone = true;
+ // If the compactValueColumn is empty, this means we have a dense table but
+ // with only a PK. As far as selects are concerned, we should ignore the value.
+ if (compactValueColumn.name.bytes.hasRemaining())
+ return compactValueColumn;
+ }
+
+ if (regularIter.hasNext())
+ return regularIter.next();
+
+ return endOfData();
+ }
+ };
}
public List<ColumnDefinition> partitionKeyColumns()
@@@ -1507,9 -1340,9 +1523,9 @@@
// Mixing counter with non counter columns is not supported (#2614)
if (defaultValidator instanceof CounterColumnType)
{
- for (ColumnDefinition def : regularColumns)
+ for (ColumnDefinition def : regularAndStaticColumns())
- if (!(def.getValidator() instanceof CounterColumnType))
- throw new ConfigurationException("Cannot add a non counter column (" + getColumnDefinitionComparator(def).getString(def.name) + ") in a counter column family");
+ if (!(def.type instanceof CounterColumnType))
+ throw new ConfigurationException("Cannot add a non counter column (" + def.name + ") in a counter column family");
}
else
{
@@@ -2017,18 -1842,18 +2033,18 @@@
droppedColumns.put(def.name, FBUtilities.timestampMicros());
}
- public void renameColumn(ByteBuffer from, String strFrom, ByteBuffer to, String strTo) throws InvalidRequestException
+ public void renameColumn(ColumnIdentifier from, ColumnIdentifier to) throws InvalidRequestException
{
- ColumnDefinition def = column_metadata.get(from);
+ ColumnDefinition def = getColumnDefinition(from);
if (def == null)
- throw new InvalidRequestException(String.format("Cannot rename unknown column %s in keyspace %s", strFrom, cfName));
+ throw new InvalidRequestException(String.format("Cannot rename unknown column %s in keyspace %s", from, cfName));
- if (column_metadata.get(to) != null)
- throw new InvalidRequestException(String.format("Cannot rename column %s to %s in keyspace %s; another column of that name already exist", strFrom, strTo, cfName));
+ if (getColumnDefinition(to) != null)
+ throw new InvalidRequestException(String.format("Cannot rename column %s to %s in keyspace %s; another column of that name already exist", from, to, cfName));
- if (def.kind == ColumnDefinition.Kind.REGULAR)
- if (def.type == ColumnDefinition.Type.REGULAR || def.type == ColumnDefinition.Type.STATIC)
++ if (def.kind == ColumnDefinition.Kind.REGULAR || def.kind == ColumnDefinition.Kind.STATIC)
{
- throw new InvalidRequestException(String.format("Cannot rename non PRIMARY KEY part %s", strFrom));
+ throw new InvalidRequestException(String.format("Cannot rename non PRIMARY KEY part %s", from));
}
else if (def.isIndexed())
{
@@@ -2044,23 -1869,46 +2060,24 @@@
public CFMetaData rebuild()
{
- /*
- * TODO: There is definitively some repetition between the CQL3 metadata stored in this
- * object (partitionKeyColumns, ...) and the one stored in CFDefinition.
- * Ultimately, we should probably merge both. However, there is enough details to fix that
- * it's worth doing that in a separate issue.
- */
- rebuildCQL3Metadata();
- cqlCfDef = new CFDefinition(this);
- return this;
- }
-
- public CFDefinition getCfDef()
- {
- assert cqlCfDef != null;
- return cqlCfDef;
- }
-
- private void rebuildCQL3Metadata()
- {
List<ColumnDefinition> pkCols = nullInitializedList(keyValidator.componentsCount());
- boolean isDense = isDense(comparator, column_metadata.values());
- int nbCkCols = isDense
- ? comparator.componentsCount()
- : comparator.componentsCount() - (hasCollection() ? 2 : 1);
- List<ColumnDefinition> ckCols = nullInitializedList(nbCkCols);
- Set<ColumnDefinition> regCols = new HashSet<ColumnDefinition>();
- Set<ColumnDefinition> statCols = new HashSet<ColumnDefinition>();
+ List<ColumnDefinition> ckCols = nullInitializedList(comparator.clusteringPrefixSize());
+ // We keep things sorted to get consistent/predicatable order in select queries
+ SortedSet<ColumnDefinition> regCols = new TreeSet<>(regularColumnComparator);
++ SortedSet<ColumnDefinition> statCols = new TreeSet<>(regularColumnComparator);
ColumnDefinition compactCol = null;
- for (ColumnDefinition def : column_metadata.values())
+ for (ColumnDefinition def : allColumns())
{
- switch (def.type)
+ switch (def.kind)
{
case PARTITION_KEY:
- assert !(def.componentIndex == null && keyValidator instanceof CompositeType);
- pkCols.set(def.componentIndex == null ? 0 : def.componentIndex, def);
+ assert !(def.isOnAllComponents() && keyValidator instanceof CompositeType);
+ pkCols.set(def.position(), def);
break;
- case CLUSTERING_KEY:
- assert !(def.componentIndex == null && comparator instanceof CompositeType);
- ckCols.set(def.componentIndex == null ? 0 : def.componentIndex, def);
+ case CLUSTERING_COLUMN:
+ assert !(def.isOnAllComponents() && comparator.isCompound());
+ ckCols.set(def.position(), def);
break;
case REGULAR:
regCols.add(def);
@@@ -2074,10 -1925,10 +2094,11 @@@
// Now actually assign the correct value. This is not atomic, but then again, updating CFMetaData is never atomic anyway.
partitionKeyColumns = addDefaultKeyAliases(pkCols);
- clusteringKeyColumns = addDefaultColumnAliases(ckCols);
+ clusteringColumns = addDefaultColumnAliases(ckCols);
regularColumns = regCols;
+ staticColumns = statCols;
- compactValueColumn = addDefaultValueAlias(compactCol, isDense);
+ compactValueColumn = addDefaultValueAlias(compactCol, comparator.isDense());
+ return this;
}
private List<ColumnDefinition> addDefaultKeyAliases(List<ColumnDefinition> pkCols)
@@@ -2241,15 -2091,24 +2262,20 @@@
return true;
}
- public boolean hasStaticColumns()
+ public boolean isCounter()
{
- return !staticColumns.isEmpty();
+ return defaultValidator.isCounter();
}
- public ColumnNameBuilder getStaticColumnNameBuilder()
++ public boolean hasStaticColumns()
+ {
- assert comparator instanceof CompositeType && clusteringKeyColumns().size() > 0;
- CompositeType.Builder builder = CompositeType.Builder.staticBuilder((CompositeType)comparator);
- for (int i = 0; i < clusteringKeyColumns().size(); i++)
- builder.add(ByteBufferUtil.EMPTY_BYTE_BUFFER);
- return builder;
++ return !staticColumns.isEmpty();
+ }
+
- public void validateColumns(Iterable<Column> columns)
+ public void validateColumns(Iterable<Cell> columns)
{
- for (Column column : columns)
- column.validateFields(this);
+ for (Cell cell : columns)
+ cell.validateFields(this);
}
@Override
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/config/ColumnDefinition.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/config/ColumnDefinition.java
index 79f50bf,11340e7..bb1dd71
--- a/src/java/org/apache/cassandra/config/ColumnDefinition.java
+++ b/src/java/org/apache/cassandra/config/ColumnDefinition.java
@@@ -58,71 -59,57 +58,77 @@@ public class ColumnDefinition extends C
* Note that thrift/CQL2 only know about definitions of type REGULAR (and
* the ones whose componentIndex == null).
*/
- public enum Type
+ public enum Kind
{
PARTITION_KEY,
- CLUSTERING_KEY,
+ CLUSTERING_COLUMN,
REGULAR,
- COMPACT_VALUE,
- STATIC
++ STATIC,
+ COMPACT_VALUE;
+
+ public String serialize()
+ {
+ // For backward compatibility we need to special case CLUSTERING_COLUMN
+ return this == CLUSTERING_COLUMN ? "clustering_key" : this.toString().toLowerCase();
+ }
+
+ public static Kind deserialize(String value)
+ {
+ if (value.equalsIgnoreCase("clustering_key"))
+ return CLUSTERING_COLUMN;
+ return Enum.valueOf(Kind.class, value.toUpperCase());
+ }
}
- public final ByteBuffer name;
- private AbstractType<?> validator;
+ public final Kind kind;
+
+ private String indexName;
private IndexType indexType;
private Map<String,String> indexOptions;
- private String indexName;
- public final Type type;
/*
* If the column comparator is a composite type, indicates to which
* component this definition refers to. If null, the definition refers to
* the full column name.
*/
- public final Integer componentIndex;
+ private final Integer componentIndex;
- public static ColumnDefinition partitionKeyDef(ByteBuffer name, AbstractType<?> validator, Integer componentIndex)
+ public static ColumnDefinition partitionKeyDef(CFMetaData cfm, ByteBuffer name, AbstractType<?> validator, Integer componentIndex)
{
- return new ColumnDefinition(name, validator, componentIndex, Type.PARTITION_KEY);
+ return new ColumnDefinition(cfm, name, validator, componentIndex, Kind.PARTITION_KEY);
}
- public static ColumnDefinition clusteringKeyDef(ByteBuffer name, AbstractType<?> validator, Integer componentIndex)
+ public static ColumnDefinition clusteringKeyDef(CFMetaData cfm, ByteBuffer name, AbstractType<?> validator, Integer componentIndex)
{
- return new ColumnDefinition(name, validator, componentIndex, Type.CLUSTERING_KEY);
+ return new ColumnDefinition(cfm, name, validator, componentIndex, Kind.CLUSTERING_COLUMN);
}
- public static ColumnDefinition regularDef(ByteBuffer name, AbstractType<?> validator, Integer componentIndex)
+ public static ColumnDefinition regularDef(CFMetaData cfm, ByteBuffer name, AbstractType<?> validator, Integer componentIndex)
{
- return new ColumnDefinition(name, validator, componentIndex, Type.REGULAR);
+ return new ColumnDefinition(cfm, name, validator, componentIndex, Kind.REGULAR);
}
- public static ColumnDefinition staticDef(ByteBuffer name, AbstractType<?> validator, Integer componentIndex)
++ public static ColumnDefinition staticDef(CFMetaData cfm, ByteBuffer name, AbstractType<?> validator, Integer componentIndex)
+ {
- return new ColumnDefinition(name, validator, componentIndex, Type.STATIC);
++ return new ColumnDefinition(cfm, name, validator, componentIndex, Kind.STATIC);
+ }
+
- public static ColumnDefinition compactValueDef(ByteBuffer name, AbstractType<?> validator)
+ public static ColumnDefinition compactValueDef(CFMetaData cfm, ByteBuffer name, AbstractType<?> validator)
{
- return new ColumnDefinition(name, validator, null, Type.COMPACT_VALUE);
+ return new ColumnDefinition(cfm, name, validator, null, Kind.COMPACT_VALUE);
}
- public ColumnDefinition(ByteBuffer name, AbstractType<?> validator, Integer componentIndex, Type type)
+ public ColumnDefinition(CFMetaData cfm, ByteBuffer name, AbstractType<?> validator, Integer componentIndex, Kind kind)
{
- this(name, validator, null, null, null, componentIndex, type);
+ this(cfm.ksName,
+ cfm.cfName,
+ new ColumnIdentifier(name, cfm.getComponentComparator(componentIndex, kind)),
+ validator,
+ null,
+ null,
+ null,
+ componentIndex,
+ kind);
}
@VisibleForTesting
@@@ -134,42 -119,25 +140,47 @@@
Map<String, String> indexOptions,
String indexName,
Integer componentIndex,
- Type type)
+ Kind kind)
{
+ super(ksName, cfName, name, validator);
assert name != null && validator != null;
- this.name = name;
+ this.kind = kind;
this.indexName = indexName;
- this.validator = validator;
this.componentIndex = componentIndex;
this.setIndexType(indexType, indexOptions);
- this.type = type;
}
- public ColumnDefinition clone()
+ public ColumnDefinition copy()
+ {
+ return new ColumnDefinition(ksName, cfName, name, type, indexType, indexOptions, indexName, componentIndex, kind);
+ }
+
+ public ColumnDefinition withNewName(ColumnIdentifier newName)
+ {
+ return new ColumnDefinition(ksName, cfName, newName, type, indexType, indexOptions, indexName, componentIndex, kind);
+ }
+
+ public ColumnDefinition withNewType(AbstractType<?> newType)
{
- return new ColumnDefinition(name, validator, indexType, indexOptions, indexName, componentIndex, type);
+ return new ColumnDefinition(ksName, cfName, name, newType, indexType, indexOptions, indexName, componentIndex, kind);
}
- public ColumnDefinition cloneWithNewName(ByteBuffer newName)
+ public boolean isOnAllComponents()
{
- return new ColumnDefinition(newName, validator, indexType, indexOptions, indexName, componentIndex, type);
+ return componentIndex == null;
+ }
+
++ public boolean isStatic()
++ {
++ return kind == Kind.STATIC;
++ }
++
+ // The componentIndex. This never return null however for convenience sake:
+ // if componentIndex == null, this return 0. So caller should first check
+ // isOnAllComponents() to distinguish if that's a possibility.
+ public int position()
+ {
+ return componentIndex == null ? 0 : componentIndex;
}
@Override
@@@ -215,9 -180,10 +226,14 @@@
public boolean isThriftCompatible()
{
- // componentIndex == null should always imply isStatic in practice, but there is no harm in being too careful here.
- return type == ColumnDefinition.Type.REGULAR && componentIndex == null;
+ return kind == ColumnDefinition.Kind.REGULAR && componentIndex == null;
+ }
+
++ public boolean isPrimaryKeyColumn()
++ {
++ return kind == Kind.PARTITION_KEY || kind == Kind.CLUSTERING_COLUMN;
+ }
+
public static List<ColumnDef> toThrift(Map<ByteBuffer, ColumnDefinition> columns)
{
List<ColumnDef> thriftDefs = new ArrayList<>(columns.size());
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/cql3/CQL3Row.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/CQL3Row.java
index afeb095,0000000..6fa2b64
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/cql3/CQL3Row.java
+++ b/src/java/org/apache/cassandra/cql3/CQL3Row.java
@@@ -1,36 -1,0 +1,41 @@@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.cql3;
+
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.cassandra.db.Cell;
+
+public interface CQL3Row
+{
+ public ByteBuffer getClusteringColumn(int i);
+ public Cell getColumn(ColumnIdentifier name);
+ public List<Cell> getCollection(ColumnIdentifier name);
+
+ public interface Builder
+ {
- Iterator<CQL3Row> group(Iterator<Cell> cells);
++ public RowIterator group(Iterator<Cell> cells);
++ }
++
++ public interface RowIterator extends Iterator<CQL3Row>
++ {
++ public CQL3Row getStaticRow();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/cql3/ColumnCondition.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/ColumnCondition.java
index 0000000,797dba6..735388d
mode 000000,100644..100644
--- a/src/java/org/apache/cassandra/cql3/ColumnCondition.java
+++ b/src/java/org/apache/cassandra/cql3/ColumnCondition.java
@@@ -1,0 -1,191 +1,183 @@@
+ /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package org.apache.cassandra.cql3;
+
+ import java.nio.ByteBuffer;
+ import java.util.*;
+
+ import com.google.common.base.Predicate;
+ import com.google.common.collect.Iterators;
+
+ import org.apache.cassandra.config.CFMetaData;
++import org.apache.cassandra.config.ColumnDefinition;
+ import org.apache.cassandra.db.*;
++import org.apache.cassandra.db.composites.CellName;
++import org.apache.cassandra.db.composites.Composite;
+ import org.apache.cassandra.db.filter.ColumnSlice;
+ import org.apache.cassandra.db.marshal.CollectionType;
+ import org.apache.cassandra.db.marshal.CounterColumnType;
+ import org.apache.cassandra.db.marshal.CompositeType;
+ import org.apache.cassandra.exceptions.InvalidRequestException;
+
+ /**
+ * A CQL3 condition.
+ */
+ public class ColumnCondition
+ {
- public final CFDefinition.Name column;
++ public final ColumnDefinition column;
+ private final Term value;
+
+ private List<ByteBuffer> variables;
+
- private ColumnCondition(CFDefinition.Name column, Term value)
++ private ColumnCondition(ColumnDefinition column, Term value)
+ {
+ this.column = column;
+ this.value = value;
+ }
+
+ // The only ones we support so far
- public static ColumnCondition equal(CFDefinition.Name column, Term value)
++ public static ColumnCondition equal(ColumnDefinition column, Term value)
+ {
+ return new ColumnCondition(column, value);
+ }
+
+ // See CQL3CasConditions for why it's convenient to have this
+ public ColumnCondition attach(List<ByteBuffer> variables)
+ {
+ this.variables = variables;
+ return this;
+ }
+
+ /**
+ * Collects the column specification for the bind variables of this operation.
+ *
+ * @param boundNames the list of column specification where to collect the
+ * bind variables of this term in.
+ */
+ public void collectMarkerSpecification(VariableSpecifications boundNames)
+ {
+ value.collectMarkerSpecification(boundNames);
+ }
+
+ // Not overriding equals() because we need the variables to have been attached when this is
+ // called and so having a non standard method name might help avoid mistakes
+ public boolean equalsTo(ColumnCondition other) throws InvalidRequestException
+ {
+ return column.equals(other.column)
+ && value.bindAndGet(variables).equals(other.value.bindAndGet(other.variables));
+ }
+
- private ColumnNameBuilder copyOrUpdatePrefix(CFMetaData cfm, ColumnNameBuilder rowPrefix)
- {
- return column.kind == CFDefinition.Name.Kind.STATIC ? cfm.getStaticColumnNameBuilder() : rowPrefix.copy();
- }
-
+ /**
+ * Validates whether this condition applies to {@code current}.
+ */
- public boolean appliesTo(ColumnNameBuilder rowPrefix, ColumnFamily current, long now) throws InvalidRequestException
++ public boolean appliesTo(Composite rowPrefix, ColumnFamily current, long now) throws InvalidRequestException
+ {
+ if (column.type instanceof CollectionType)
+ return collectionAppliesTo((CollectionType)column.type, rowPrefix, current, now);
+
- Column c = current.getColumn(copyOrUpdatePrefix(current.metadata(), rowPrefix).add(column.name.key).build());
++ Cell c = current.getColumn(current.metadata().comparator.create(rowPrefix, column));
+ ByteBuffer v = value.bindAndGet(variables);
+ return v == null
+ ? c == null || !c.isLive(now)
+ : c != null && c.isLive(now) && c.value().equals(v);
+ }
+
- private boolean collectionAppliesTo(CollectionType type, ColumnNameBuilder rowPrefix, ColumnFamily current, final long now) throws InvalidRequestException
++ private boolean collectionAppliesTo(CollectionType type, Composite rowPrefix, ColumnFamily current, final long now) throws InvalidRequestException
+ {
- ColumnNameBuilder collectionPrefix = copyOrUpdatePrefix(current.metadata(), rowPrefix).add(column.name.key);
++ CellName name = current.metadata().comparator.create(rowPrefix, column);
+ // We are testing for collection equality, so we need to have the expected values *and* only those.
- ColumnSlice[] collectionSlice = new ColumnSlice[]{ new ColumnSlice(collectionPrefix.build(), collectionPrefix.buildAsEndOfRange()) };
++ ColumnSlice[] collectionSlice = new ColumnSlice[]{ name.slice() };
+ // Filter live columns, this makes things simpler afterwards
- Iterator<Column> iter = Iterators.filter(current.iterator(collectionSlice), new Predicate<Column>()
++ Iterator<Cell> iter = Iterators.filter(current.iterator(collectionSlice), new Predicate<Cell>()
+ {
- public boolean apply(Column c)
++ public boolean apply(Cell c)
+ {
+ // we only care about live columns
+ return c.isLive(now);
+ }
+ });
+
+ Term.Terminal v = value.bind(variables);
+ if (v == null)
+ return !iter.hasNext();
+
+ switch (type.kind)
+ {
+ case LIST: return listAppliesTo(current.metadata(), iter, ((Lists.Value)v).elements);
+ case SET: return setAppliesTo(current.metadata(), iter, ((Sets.Value)v).elements);
+ case MAP: return mapAppliesTo(current.metadata(), iter, ((Maps.Value)v).map);
+ }
+ throw new AssertionError();
+ }
+
- private static ByteBuffer collectionKey(CFMetaData cfm, Column c)
- {
- ByteBuffer[] bbs = ((CompositeType)cfm.comparator).split(c.name());
- return bbs[bbs.length - 1];
- }
-
- private boolean listAppliesTo(CFMetaData cfm, Iterator<Column> iter, List<ByteBuffer> elements)
++ private boolean listAppliesTo(CFMetaData cfm, Iterator<Cell> iter, List<ByteBuffer> elements)
+ {
+ for (ByteBuffer e : elements)
+ if (!iter.hasNext() || iter.next().value().equals(e))
+ return false;
+ // We must not have more elements than expected
+ return !iter.hasNext();
+ }
+
- private boolean setAppliesTo(CFMetaData cfm, Iterator<Column> iter, Set<ByteBuffer> elements)
++ private boolean setAppliesTo(CFMetaData cfm, Iterator<Cell> iter, Set<ByteBuffer> elements)
+ {
+ Set<ByteBuffer> remaining = new HashSet<>(elements);
+ while (iter.hasNext())
+ {
+ if (remaining.isEmpty())
+ return false;
+
- if (!remaining.remove(collectionKey(cfm, iter.next())))
++ if (!remaining.remove(iter.next().name().collectionElement()))
+ return false;
+ }
+ return remaining.isEmpty();
+ }
+
- private boolean mapAppliesTo(CFMetaData cfm, Iterator<Column> iter, Map<ByteBuffer, ByteBuffer> elements)
++ private boolean mapAppliesTo(CFMetaData cfm, Iterator<Cell> iter, Map<ByteBuffer, ByteBuffer> elements)
+ {
+ Map<ByteBuffer, ByteBuffer> remaining = new HashMap<>(elements);
+ while (iter.hasNext())
+ {
+ if (remaining.isEmpty())
+ return false;
+
- Column c = iter.next();
- if (!remaining.remove(collectionKey(cfm, c)).equals(c.value()))
++ Cell c = iter.next();
++ if (!remaining.remove(c.name().collectionElement()).equals(c.value()))
+ return false;
+ }
+ return remaining.isEmpty();
+ }
+
+ public static class Raw
+ {
+ private final Term.Raw value;
+
+ public Raw(Term.Raw value)
+ {
+ this.value = value;
+ }
+
- public ColumnCondition prepare(CFDefinition.Name receiver) throws InvalidRequestException
++ public ColumnCondition prepare(String keyspace, ColumnDefinition receiver) throws InvalidRequestException
+ {
+ if (receiver.type instanceof CounterColumnType)
+ throw new InvalidRequestException("Condtions on counters are not supported");
+
- return ColumnCondition.equal(receiver, value.prepare(receiver));
++ return ColumnCondition.equal(receiver, value.prepare(keyspace, receiver));
+ }
+ }
+ }
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/cql3/Constants.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/Constants.java
index 44e96ef,f99fd02..3b7b4c4
--- a/src/java/org/apache/cassandra/cql3/Constants.java
+++ b/src/java/org/apache/cassandra/cql3/Constants.java
@@@ -296,9 -294,10 +296,9 @@@ public abstract class Constant
super(column, t);
}
- public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+ public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
{
- CellName cname = cf.getComparator().create(prefix, column.name);
- prefix = maybeUpdatePrefix(cf.metadata(), prefix);
- ByteBuffer cname = columnName == null ? prefix.build() : prefix.add(columnName.key).build();
++ CellName cname = cf.getComparator().create(prefix, column);
ByteBuffer value = t.bindAndGet(params.variables);
cf.addColumn(value == null ? params.makeTombstone(cname) : params.makeColumn(cname, value));
}
@@@ -317,7 -316,8 +317,7 @@@
if (bytes == null)
throw new InvalidRequestException("Invalid null value for counter increment");
long increment = ByteBufferUtil.toLong(bytes);
- CellName cname = cf.getComparator().create(prefix, column.name);
- prefix = maybeUpdatePrefix(cf.metadata(), prefix);
- ByteBuffer cname = columnName == null ? prefix.build() : prefix.add(columnName.key).build();
++ CellName cname = cf.getComparator().create(prefix, column);
cf.addCounter(cname, increment);
}
}
@@@ -339,7 -339,8 +339,7 @@@
if (increment == Long.MIN_VALUE)
throw new InvalidRequestException("The negation of " + increment + " overflows supported counter precision (signed 8 bytes integer)");
- CellName cname = cf.getComparator().create(prefix, column.name);
- prefix = maybeUpdatePrefix(cf.metadata(), prefix);
- ByteBuffer cname = columnName == null ? prefix.build() : prefix.add(columnName.key).build();
++ CellName cname = cf.getComparator().create(prefix, column);
cf.addCounter(cname, -increment);
}
}
@@@ -348,18 -349,22 +348,18 @@@
// duplicating this further
public static class Deleter extends Operation
{
- private final boolean isCollection;
-
- public Deleter(ColumnIdentifier column, boolean isCollection)
+ public Deleter(ColumnDefinition column)
{
super(column, null);
- this.isCollection = isCollection;
}
- public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+ public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
{
- CellName cname = cf.getComparator().create(prefix, column.name);
- ColumnNameBuilder column = maybeUpdatePrefix(cf.metadata(), prefix).add(columnName.key);
-
- if (isCollection)
- cf.addAtom(params.makeRangeTombstone(column.build(), column.buildAsEndOfRange()));
++ CellName cname = cf.getComparator().create(prefix, column);
+ if (column.type.isCollection())
+ cf.addAtom(params.makeRangeTombstone(cname.slice()));
else
- cf.addColumn(params.makeTombstone(column.build()));
+ cf.addColumn(params.makeTombstone(cname));
}
};
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/cql3/Cql.g
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/Cql.g
index 55d8aac,a11a818..0ec283c
--- a/src/java/org/apache/cassandra/cql3/Cql.g
+++ b/src/java/org/apache/cassandra/cql3/Cql.g
@@@ -1081,8 -988,9 +1088,9 @@@ basic_unreserved_keyword returns [Strin
| K_CUSTOM
| K_TRIGGER
| K_DISTINCT
+ | K_CONTAINS
+ | K_STATIC
) { $str = $k.text; }
- | t=native_type { $str = t.toString(); }
;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/cql3/Lists.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/Lists.java
index 8dbe59c,4ad39db..580a2c9
--- a/src/java/org/apache/cassandra/cql3/Lists.java
+++ b/src/java/org/apache/cassandra/cql3/Lists.java
@@@ -265,12 -263,12 +265,12 @@@ public abstract class List
super(column, t);
}
- public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+ public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
{
// delete + append
- CellName name = cf.getComparator().create(prefix, column.name);
- ColumnNameBuilder column = maybeUpdatePrefix(cf.metadata(), prefix).add(columnName.key);
- cf.addAtom(params.makeTombstoneForOverwrite(column.build(), column.buildAsEndOfRange()));
- Appender.doAppend(t, cf, column, params);
++ CellName name = cf.getComparator().create(prefix, column);
+ cf.addAtom(params.makeTombstoneForOverwrite(name.slice()));
- Appender.doAppend(t, cf, prefix, column.name, params);
++ Appender.doAppend(t, cf, prefix, column, params);
}
}
@@@ -335,12 -335,12 +335,12 @@@
super(column, t);
}
- public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+ public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
{
- doAppend(t, cf, prefix, column.name, params);
- doAppend(t, cf, maybeUpdatePrefix(cf.metadata(), prefix).add(columnName.key), params);
++ doAppend(t, cf, prefix, column, params);
}
- static void doAppend(Term t, ColumnFamily cf, Composite prefix, ColumnIdentifier columnName, UpdateParameters params) throws InvalidRequestException
- static void doAppend(Term t, ColumnFamily cf, ColumnNameBuilder columnName, UpdateParameters params) throws InvalidRequestException
++ static void doAppend(Term t, ColumnFamily cf, Composite prefix, ColumnDefinition column, UpdateParameters params) throws InvalidRequestException
{
Term.Terminal value = t.bind(params.variables);
// If we append null, do nothing. Note that for Setter, we've
@@@ -352,8 -352,10 +352,8 @@@
List<ByteBuffer> toAdd = ((Lists.Value)value).elements;
for (int i = 0; i < toAdd.size(); i++)
{
- ColumnNameBuilder b = i == toAdd.size() - 1 ? columnName : columnName.copy();
ByteBuffer uuid = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes());
- cf.addColumn(params.makeColumn(cf.getComparator().create(prefix, columnName, uuid), toAdd.get(i)));
- ByteBuffer cellName = b.add(uuid).build();
- cf.addColumn(params.makeColumn(cellName, toAdd.get(i)));
++ cf.addColumn(params.makeColumn(cf.getComparator().create(prefix, column, uuid), toAdd.get(i)));
}
}
}
@@@ -375,11 -377,14 +375,11 @@@
long time = PrecisionTime.REFERENCE_TIME - (System.currentTimeMillis() - PrecisionTime.REFERENCE_TIME);
List<ByteBuffer> toAdd = ((Lists.Value)value).elements;
- ColumnNameBuilder column = maybeUpdatePrefix(cf.metadata(), prefix).add(columnName.key);
for (int i = 0; i < toAdd.size(); i++)
{
- ColumnNameBuilder b = i == toAdd.size() - 1 ? column : column.copy();
PrecisionTime pt = PrecisionTime.getNext(time);
ByteBuffer uuid = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(pt.millis, pt.nanos));
- cf.addColumn(params.makeColumn(cf.getComparator().create(prefix, column.name, uuid), toAdd.get(i)));
- ByteBuffer cellName = b.add(uuid).build();
- cf.addColumn(params.makeColumn(cellName, toAdd.get(i)));
++ cf.addColumn(params.makeColumn(cf.getComparator().create(prefix, column, uuid), toAdd.get(i)));
}
}
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/cql3/Maps.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/Maps.java
index 3f9cc95,c332999..d113b57
--- a/src/java/org/apache/cassandra/cql3/Maps.java
+++ b/src/java/org/apache/cassandra/cql3/Maps.java
@@@ -244,12 -241,12 +244,12 @@@ public abstract class Map
super(column, t);
}
- public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+ public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
{
// delete + put
- CellName name = cf.getComparator().create(prefix, column.name);
- ColumnNameBuilder column = maybeUpdatePrefix(cf.metadata(), prefix).add(columnName.key);
- cf.addAtom(params.makeTombstoneForOverwrite(column.build(), column.buildAsEndOfRange()));
- Putter.doPut(t, cf, column, params);
++ CellName name = cf.getComparator().create(prefix, column);
+ cf.addAtom(params.makeTombstoneForOverwrite(name.slice()));
- Putter.doPut(t, cf, prefix, column.name, params);
++ Putter.doPut(t, cf, prefix, column, params);
}
}
@@@ -277,7 -274,7 +277,7 @@@
if (key == null)
throw new InvalidRequestException("Invalid null map key");
- CellName cellName = cf.getComparator().create(prefix, column.name, key);
- ByteBuffer cellName = maybeUpdatePrefix(cf.metadata(), prefix).add(columnName.key).add(key).build();
++ CellName cellName = cf.getComparator().create(prefix, column, key);
if (value == null)
{
@@@ -303,12 -300,12 +303,12 @@@
super(column, t);
}
- public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+ public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
{
- doPut(t, cf, prefix, column.name, params);
- doPut(t, cf, maybeUpdatePrefix(cf.metadata(), prefix).add(columnName.key), params);
++ doPut(t, cf, prefix, column, params);
}
- static void doPut(Term t, ColumnFamily cf, Composite prefix, ColumnIdentifier columnName, UpdateParameters params) throws InvalidRequestException
- static void doPut(Term t, ColumnFamily cf, ColumnNameBuilder columnName, UpdateParameters params) throws InvalidRequestException
++ static void doPut(Term t, ColumnFamily cf, Composite prefix, ColumnDefinition column, UpdateParameters params) throws InvalidRequestException
{
Term.Terminal value = t.bind(params.variables);
if (value == null)
@@@ -318,7 -315,7 +318,7 @@@
Map<ByteBuffer, ByteBuffer> toAdd = ((Maps.Value)value).map;
for (Map.Entry<ByteBuffer, ByteBuffer> entry : toAdd.entrySet())
{
- CellName cellName = cf.getComparator().create(prefix, columnName, entry.getKey());
- ByteBuffer cellName = columnName.copy().add(entry.getKey()).build();
++ CellName cellName = cf.getComparator().create(prefix, column, entry.getKey());
cf.addColumn(params.makeColumn(cellName, entry.getValue()));
}
}
@@@ -338,7 -335,7 +338,7 @@@
throw new InvalidRequestException("Invalid null map key");
assert key instanceof Constants.Value;
- CellName cellName = cf.getComparator().create(prefix, column.name, ((Constants.Value)key).bytes);
- ByteBuffer cellName = maybeUpdatePrefix(cf.metadata(), prefix).add(columnName.key).add(((Constants.Value)key).bytes).build();
++ CellName cellName = cf.getComparator().create(prefix, column, ((Constants.Value)key).bytes);
cf.addColumn(params.makeTombstone(cellName));
}
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/cql3/Sets.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/Sets.java
index dddea09,69bc3d3..e48a3ce
--- a/src/java/org/apache/cassandra/cql3/Sets.java
+++ b/src/java/org/apache/cassandra/cql3/Sets.java
@@@ -230,12 -227,12 +230,12 @@@ public abstract class Set
super(column, t);
}
- public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+ public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
{
// delete + add
- CellName name = cf.getComparator().create(prefix, column.name);
- ColumnNameBuilder column = maybeUpdatePrefix(cf.metadata(), prefix).add(columnName.key);
- cf.addAtom(params.makeTombstoneForOverwrite(column.build(), column.buildAsEndOfRange()));
- Adder.doAdd(t, cf, column, params);
++ CellName name = cf.getComparator().create(prefix, column);
+ cf.addAtom(params.makeTombstoneForOverwrite(name.slice()));
- Adder.doAdd(t, cf, prefix, column.name, params);
++ Adder.doAdd(t, cf, prefix, column, params);
}
}
@@@ -246,12 -243,12 +246,12 @@@
super(column, t);
}
- public void execute(ByteBuffer rowKey, ColumnFamily cf, ColumnNameBuilder prefix, UpdateParameters params) throws InvalidRequestException
+ public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
{
- doAdd(t, cf, prefix, column.name, params);
- doAdd(t, cf, maybeUpdatePrefix(cf.metadata(), prefix).add(columnName.key), params);
++ doAdd(t, cf, prefix, column, params);
}
- static void doAdd(Term t, ColumnFamily cf, Composite prefix, ColumnIdentifier columnName, UpdateParameters params) throws InvalidRequestException
- static void doAdd(Term t, ColumnFamily cf, ColumnNameBuilder columnName, UpdateParameters params) throws InvalidRequestException
++ static void doAdd(Term t, ColumnFamily cf, Composite prefix, ColumnDefinition column, UpdateParameters params) throws InvalidRequestException
{
Term.Terminal value = t.bind(params.variables);
if (value == null)
@@@ -262,7 -259,7 +262,7 @@@
Set<ByteBuffer> toAdd = ((Sets.Value)value).elements;
for (ByteBuffer bb : toAdd)
{
- CellName cellName = cf.getComparator().create(prefix, columnName, bb);
- ByteBuffer cellName = columnName.copy().add(bb).build();
++ CellName cellName = cf.getComparator().create(prefix, column, bb);
cf.addColumn(params.makeColumn(cellName, ByteBufferUtil.EMPTY_BYTE_BUFFER));
}
}
@@@ -286,9 -283,11 +286,9 @@@
? Collections.singleton(((Constants.Value)value).bytes)
: ((Sets.Value)value).elements;
- ColumnNameBuilder column = maybeUpdatePrefix(cf.metadata(), prefix).add(columnName.key);
for (ByteBuffer bb : toDiscard)
{
- cf.addColumn(params.makeTombstone(cf.getComparator().create(prefix, column.name, bb)));
- ByteBuffer cellName = column.copy().add(bb).build();
- cf.addColumn(params.makeTombstone(cellName));
++ cf.addColumn(params.makeTombstone(cf.getComparator().create(prefix, column, bb)));
}
}
}
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
index 0932b5c,85b3547..9c097a3
--- a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
@@@ -45,8 -47,15 +45,15 @@@ public class AlterTableStatement extend
public final ColumnIdentifier columnName;
private final CFPropDefs cfProps;
private final Map<ColumnIdentifier, ColumnIdentifier> renames;
-
- public AlterTableStatement(CFName name, Type type, ColumnIdentifier columnName, CQL3Type.Raw validator, CFPropDefs cfProps, Map<ColumnIdentifier, ColumnIdentifier> renames)
+ private final boolean isStatic; // Only for ALTER ADD
+
+ public AlterTableStatement(CFName name,
+ Type type,
+ ColumnIdentifier columnName,
- CQL3Type validator,
++ CQL3Type.Raw validator,
+ CFPropDefs cfProps,
+ Map<ColumnIdentifier, ColumnIdentifier> renames,
+ boolean isStatic)
{
super(name);
this.oType = type;
@@@ -77,16 -86,20 +85,18 @@@
switch (oType)
{
case ADD:
- if (cfDef.isCompact)
+ if (cfm.comparator.isDense())
- throw new InvalidRequestException("Cannot add new column to a compact CF");
+ throw new InvalidRequestException("Cannot add new column to a COMPACT STORAGE table");
-
- if (isStatic && !cfDef.isComposite)
++ if (isStatic && !cfm.comparator.isCompound())
+ throw new InvalidRequestException("Static columns are not allowed in COMPACT STORAGE tables");
-
- if (name != null)
+ if (def != null)
{
- switch (name.kind)
+ switch (def.kind)
{
- case KEY_ALIAS:
- case COLUMN_ALIAS:
+ case PARTITION_KEY:
+ case CLUSTERING_COLUMN:
throw new InvalidRequestException(String.format("Invalid column name %s because it conflicts with a PRIMARY KEY part", columnName));
- case REGULAR:
+ default:
throw new InvalidRequestException(String.format("Invalid column name %s because it conflicts with an existing column", columnName));
}
}
@@@ -94,16 -107,31 +104,18 @@@
AbstractType<?> type = validator.getType();
if (type instanceof CollectionType)
{
- if (!cfDef.isComposite)
+ if (!cfm.comparator.supportCollections())
throw new InvalidRequestException("Cannot use collection types with non-composite PRIMARY KEY");
- if (cfDef.cfm.isSuper())
+ if (cfm.isSuper())
throw new InvalidRequestException("Cannot use collection types with Super column family");
- Map<ByteBuffer, CollectionType> collections = cfDef.hasCollections
- ? new HashMap<ByteBuffer, CollectionType>(cfDef.getCollectionType().defined)
- : new HashMap<ByteBuffer, CollectionType>();
-
- collections.put(columnName.key, (CollectionType)type);
- ColumnToCollectionType newColType = ColumnToCollectionType.getInstance(collections);
- List<AbstractType<?>> ctypes = new ArrayList<AbstractType<?>>(((CompositeType)cfm.comparator).types);
- if (cfDef.hasCollections)
- ctypes.set(ctypes.size() - 1, newColType);
- else
- ctypes.add(newColType);
- cfm.comparator = CompositeType.getInstance(ctypes);
+ cfm.comparator = cfm.comparator.addCollection(columnName, (CollectionType)type);
}
- Integer componentIndex = cfDef.isComposite
- ? ((CompositeType)meta.comparator).types.size() - (cfDef.hasCollections ? 2 : 1)
- : null;
+ Integer componentIndex = cfm.comparator.isCompound() ? cfm.comparator.clusteringPrefixSize() : null;
- cfm.addColumnDefinition(ColumnDefinition.regularDef(cfm, columnName.bytes, type, componentIndex));
+ cfm.addColumnDefinition(isStatic
- ? ColumnDefinition.staticDef(columnName.key, type, componentIndex)
- : ColumnDefinition.regularDef(columnName.key, type, componentIndex));
++ ? ColumnDefinition.staticDef(cfm, columnName.bytes, type, componentIndex)
++ : ColumnDefinition.regularDef(cfm, columnName.bytes, type, componentIndex));
break;
case ALTER:
@@@ -161,7 -191,9 +173,8 @@@
validator));
cfm.defaultValidator(validator.getType());
break;
- case COLUMN_METADATA:
+ case REGULAR:
+ case STATIC:
- ColumnDefinition column = cfm.getColumnDefinition(columnName.key);
// Thrift allows to change a column validator so CFMetaData.validateCompatibility will let it slide
// if we change to an incompatible type (contrarily to the comparator case). But we don't want to
// allow it for CQL3 (see #5882) so validating it explicitly here. We only care about value compatibility
@@@ -180,21 -211,22 +193,22 @@@
break;
case DROP:
- if (cfDef.isCompact || !cfDef.isComposite)
- throw new InvalidRequestException("Cannot drop columns from a COMPACT STORAGE table");
- if (name == null)
+ if (!cfm.isCQL3Table())
- throw new InvalidRequestException("Cannot drop columns from a non-CQL3 CF");
++ throw new InvalidRequestException("Cannot drop columns from a non-CQL3 table");
+ if (def == null)
- throw new InvalidRequestException(String.format("Cell %s was not found in table %s", columnName, columnFamily()));
+ throw new InvalidRequestException(String.format("Column %s was not found in table %s", columnName, columnFamily()));
- switch (name.kind)
+ switch (def.kind)
{
- case KEY_ALIAS:
- case COLUMN_ALIAS:
+ case PARTITION_KEY:
+ case CLUSTERING_COLUMN:
throw new InvalidRequestException(String.format("Cannot drop PRIMARY KEY part %s", columnName));
- case COLUMN_METADATA:
+ case REGULAR:
+ case STATIC:
ColumnDefinition toDelete = null;
- for (ColumnDefinition columnDef : cfm.regularColumns())
+ for (ColumnDefinition columnDef : cfm.regularAndStaticColumns())
{
- if (columnDef.name.equals(columnName.key))
+ if (columnDef.name.equals(columnName))
toDelete = columnDef;
}
assert toDelete != null;
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
index 2c8b2b7,d4acbae..ab2b4bc
--- a/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
@@@ -20,12 -20,11 +20,13 @@@ package org.apache.cassandra.cql3.state
import java.nio.ByteBuffer;
import java.util.*;
+ import com.google.common.collect.Iterables;
import org.github.jamm.MemoryMeter;
++import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.cql3.*;
- import org.apache.cassandra.db.ConsistencyLevel;
- import org.apache.cassandra.db.IMutation;
- import org.apache.cassandra.db.Mutation;
+ import org.apache.cassandra.db.*;
++import org.apache.cassandra.db.composites.Composite;
import org.apache.cassandra.exceptions.*;
import org.apache.cassandra.service.ClientState;
import org.apache.cassandra.service.QueryState;
@@@ -175,17 -182,103 +184,108 @@@ public class BatchStatement implements
StorageProxy.mutateWithTriggers(mutations, cl, mutateAtomic);
}
+ private ResultMessage executeWithConditions(BatchVariables variables, ConsistencyLevel cl, ConsistencyLevel serialCf, long now)
+ throws RequestExecutionException, RequestValidationException
+ {
+ ByteBuffer key = null;
+ String ksName = null;
+ String cfName = null;
+ ColumnFamily updates = null;
+ CQL3CasConditions conditions = null;
- Set<ColumnIdentifier> columnsWithConditions = new LinkedHashSet<ColumnIdentifier>();
++ Set<ColumnDefinition> columnsWithConditions = new LinkedHashSet<ColumnDefinition>();
+
+ for (int i = 0; i < statements.size(); i++)
+ {
+ ModificationStatement statement = statements.get(i);
+ List<ByteBuffer> statementVariables = variables.getVariablesForStatement(i);
+ long timestamp = attrs.getTimestamp(now, statementVariables);
+ List<ByteBuffer> pks = statement.buildPartitionKeyNames(statementVariables);
+ if (pks.size() > 1)
+ throw new IllegalArgumentException("Batch with conditions cannot span multiple partitions (you cannot use IN on the partition key)");
+ if (key == null)
+ {
+ key = pks.get(0);
+ ksName = statement.cfm.ksName;
+ cfName = statement.cfm.cfName;
+ conditions = new CQL3CasConditions(statement.cfm, now);
- updates = UnsortedColumns.factory.create(statement.cfm);
++ updates = ArrayBackedSortedColumns.factory.create(statement.cfm);
+ }
+ else if (!key.equals(pks.get(0)))
+ {
+ throw new InvalidRequestException("Batch with conditions cannot span multiple partitions");
+ }
+
+ if (statement.hasConditions())
+ {
- ColumnNameBuilder clusteringPrefix = statement.createClusteringPrefixBuilder(statementVariables);
++ Composite clusteringPrefix = statement.createClusteringPrefix(statementVariables);
+ statement.addUpdatesAndConditions(key, clusteringPrefix, updates, conditions, statementVariables, timestamp);
+ // As soon as we have a ifNotExists, we set columnsWithConditions to null so that everything is in the resultSet
+ if (statement.hasIfNotExistCondition())
+ columnsWithConditions = null;
+ else if (columnsWithConditions != null)
+ Iterables.addAll(columnsWithConditions, statement.getColumnsWithConditions());
+ }
+ else
+ {
+ // getPartitionKey will already have thrown if there is more than one key involved
+ IMutation mut = statement.getMutations(statementVariables, false, cl, timestamp, true).iterator().next();
- updates.resolve(mut.getColumnFamilies().iterator().next());
++ updates.addAll(mut.getColumnFamilies().iterator().next());
+ }
+ }
+
+ ColumnFamily result = StorageProxy.cas(ksName, cfName, key, conditions, updates, serialCf, cl);
+ return new ResultMessage.Rows(ModificationStatement.buildCasResultSet(ksName, key, cfName, result, columnsWithConditions, true));
+ }
+
public ResultMessage executeInternal(QueryState queryState) throws RequestValidationException, RequestExecutionException
{
- for (IMutation mutation : getMutations(Collections.<ByteBuffer>emptyList(), true, null, queryState.getTimestamp()))
+ assert !hasConditions;
-
- for (IMutation mutation : getMutations(new PreparedBatchVariables(Collections.<ByteBuffer>emptyList()), true, null, queryState.getTimestamp()))
- mutation.apply();
++ for (IMutation mutation : getMutations(PreparedBatchVariables.EMPTY, true, null, queryState.getTimestamp()))
+ {
+ // We don't use counters internally.
+ assert mutation instanceof Mutation;
+ ((Mutation) mutation).apply();
+ }
return null;
}
+ public interface BatchVariables
+ {
+ public List<ByteBuffer> getVariablesForStatement(int statementInBatch);
+ }
+
+ public static class PreparedBatchVariables implements BatchVariables
+ {
++ public static final BatchVariables EMPTY = new PreparedBatchVariables(Collections.<ByteBuffer>emptyList());
++
+ private final List<ByteBuffer> variables;
+
+ public PreparedBatchVariables(List<ByteBuffer> variables)
+ {
+ this.variables = variables;
+ }
+
+ public List<ByteBuffer> getVariablesForStatement(int statementInBatch)
+ {
+ return variables;
+ }
+ }
+
+ public static class BatchOfPreparedVariables implements BatchVariables
+ {
+ private final List<List<ByteBuffer>> variables;
+
+ public BatchOfPreparedVariables(List<List<ByteBuffer>> variables)
+ {
+ this.variables = variables;
+ }
+
+ public List<ByteBuffer> getVariablesForStatement(int statementInBatch)
+ {
+ return variables.get(statementInBatch);
+ }
+ }
+
public String toString()
{
return String.format("BatchStatement(type=%s, statements=%s)", type, statements);
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/cql3/statements/CQL3CasConditions.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/CQL3CasConditions.java
index 0000000,194ff0c..56692f9
mode 000000,100644..100644
--- a/src/java/org/apache/cassandra/cql3/statements/CQL3CasConditions.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CQL3CasConditions.java
@@@ -1,0 -1,164 +1,164 @@@
+ /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package org.apache.cassandra.cql3.statements;
+
+ import java.nio.ByteBuffer;
+ import java.util.*;
+
+ import org.apache.cassandra.cql3.*;
+ import org.apache.cassandra.config.CFMetaData;
+ import org.apache.cassandra.db.*;
++import org.apache.cassandra.db.composites.Composite;
+ import org.apache.cassandra.db.filter.*;
+ import org.apache.cassandra.exceptions.InvalidRequestException;
+ import org.apache.cassandra.service.CASConditions;
+
+ /**
+ * Processed CAS conditions on potentially multiple rows of the same partition.
+ */
+ public class CQL3CasConditions implements CASConditions
+ {
+ private final CFMetaData cfm;
+ private final long now;
+
+ // We index RowCondition by the prefix of the row they applied to for 2 reasons:
+ // 1) this allows to keep things sorted to build the ColumnSlice array below
+ // 2) this allows to detect when contradictory conditions are set (not exists with some other conditions on the same row)
- private final SortedMap<ByteBuffer, RowCondition> conditions;
++ private final SortedMap<Composite, RowCondition> conditions;
+
+ public CQL3CasConditions(CFMetaData cfm, long now)
+ {
+ this.cfm = cfm;
+ this.now = now;
+ this.conditions = new TreeMap<>(cfm.comparator);
+ }
+
- public void addNotExist(ColumnNameBuilder prefix) throws InvalidRequestException
++ public void addNotExist(Composite prefix) throws InvalidRequestException
+ {
- RowCondition previous = conditions.put(prefix.build(), new NotExistCondition(prefix, now));
++ RowCondition previous = conditions.put(prefix, new NotExistCondition(prefix, now));
+ if (previous != null && !(previous instanceof NotExistCondition))
+ throw new InvalidRequestException("Cannot mix IF conditions and IF NOT EXISTS for the same row");
+ }
+
- public void addConditions(ColumnNameBuilder prefix, Collection<ColumnCondition> conds, List<ByteBuffer> variables) throws InvalidRequestException
++ public void addConditions(Composite prefix, Collection<ColumnCondition> conds, List<ByteBuffer> variables) throws InvalidRequestException
+ {
- ByteBuffer b = prefix.build();
- RowCondition condition = conditions.get(b);
++ RowCondition condition = conditions.get(prefix);
+ if (condition == null)
+ {
+ condition = new ColumnsConditions(prefix, now);
- conditions.put(b, condition);
++ conditions.put(prefix, condition);
+ }
+ else if (!(condition instanceof ColumnsConditions))
+ {
+ throw new InvalidRequestException("Cannot mix IF conditions and IF NOT EXISTS for the same row");
+ }
+ ((ColumnsConditions)condition).addConditions(conds, variables);
+ }
+
+ public IDiskAtomFilter readFilter()
+ {
+ assert !conditions.isEmpty();
+ ColumnSlice[] slices = new ColumnSlice[conditions.size()];
+ int i = 0;
+ // We always read CQL rows entirely as on CAS failure we want to be able to distinguish between "row exists
- // but all values on why there were conditions are null" and "row doesn't exists", and we can't rely on the
++ // but all values for which there were conditions are null" and "row doesn't exists", and we can't rely on the
+ // row marker for that (see #6623)
- for (Map.Entry<ByteBuffer, RowCondition> entry : conditions.entrySet())
- slices[i++] = new ColumnSlice(entry.getKey(), entry.getValue().rowPrefix.buildAsEndOfRange());
++ for (Composite prefix : conditions.keySet())
++ slices[i++] = prefix.slice();
+
- return new SliceQueryFilter(slices, false, slices.length, cfm.clusteringKeyColumns().size());
++ return new SliceQueryFilter(slices, false, slices.length, cfm.clusteringColumns().size());
+ }
+
+ public boolean appliesTo(ColumnFamily current) throws InvalidRequestException
+ {
+ for (RowCondition condition : conditions.values())
+ {
+ if (!condition.appliesTo(current))
+ return false;
+ }
+ return true;
+ }
+
+ private static abstract class RowCondition
+ {
- public final ColumnNameBuilder rowPrefix;
++ public final Composite rowPrefix;
+ protected final long now;
+
- protected RowCondition(ColumnNameBuilder rowPrefix, long now)
++ protected RowCondition(Composite rowPrefix, long now)
+ {
+ this.rowPrefix = rowPrefix;
+ this.now = now;
+ }
+
+ public abstract boolean appliesTo(ColumnFamily current) throws InvalidRequestException;
+ }
+
+ private static class NotExistCondition extends RowCondition
+ {
- private NotExistCondition(ColumnNameBuilder rowPrefix, long now)
++ private NotExistCondition(Composite rowPrefix, long now)
+ {
+ super(rowPrefix, now);
+ }
+
+ public boolean appliesTo(ColumnFamily current)
+ {
+ if (current == null)
+ return true;
+
- Iterator<Column> iter = current.iterator(new ColumnSlice[]{ new ColumnSlice(rowPrefix.build(), rowPrefix.buildAsEndOfRange()) });
++ Iterator<Cell> iter = current.iterator(new ColumnSlice[]{ rowPrefix.slice() });
+ while (iter.hasNext())
+ if (iter.next().isLive(now))
+ return false;
+ return true;
+ }
+ }
+
+ private static class ColumnsConditions extends RowCondition
+ {
+ private final Map<ColumnIdentifier, ColumnCondition> conditions = new HashMap<>();
+
- private ColumnsConditions(ColumnNameBuilder rowPrefix, long now)
++ private ColumnsConditions(Composite rowPrefix, long now)
+ {
+ super(rowPrefix, now);
+ }
+
+ public void addConditions(Collection<ColumnCondition> conds, List<ByteBuffer> variables) throws InvalidRequestException
+ {
+ for (ColumnCondition condition : conds)
+ {
+ // We will need the variables in appliesTo but with protocol batches, each condition in this object can have a
+ // different list of variables. So attach them to the condition directly, it's not particulary elegant but its simpler
+ ColumnCondition previous = conditions.put(condition.column.name, condition.attach(variables));
+ // If 2 conditions are actually equal, let it slide
+ if (previous != null && !previous.equalsTo(condition))
+ throw new InvalidRequestException("Duplicate and incompatible conditions for column " + condition.column.name);
+ }
+ }
+
+ public boolean appliesTo(ColumnFamily current) throws InvalidRequestException
+ {
+ if (current == null)
+ return conditions.isEmpty();
+
+ for (ColumnCondition condition : conditions.values())
+ if (!condition.appliesTo(rowPrefix, current, now))
+ return false;
+ return true;
+ }
+ }
+ }
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java
index fe5508b,376fa4a..49a669f
--- a/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateIndexStatement.java
@@@ -101,11 -84,23 +101,20 @@@ public class CreateIndexStatement exten
properties.validate();
// TODO: we could lift that limitation
- if (cfm.getCfDef().isCompact && cd.type != ColumnDefinition.Type.REGULAR)
- throw new InvalidRequestException(String.format("Secondary index on %s column %s is not yet supported for compact table", cd.type, columnName));
+ if (cfm.comparator.isDense() && cd.kind != ColumnDefinition.Kind.REGULAR)
+ throw new InvalidRequestException(String.format("Secondary index on %s column %s is not yet supported for compact table", cd.kind, target.column));
+ // It would be possible to support 2ndary index on static columns (but not without modifications of at least ExtendedFilter and
+ // CompositesIndex) and maybe we should, but that means a query like:
+ // SELECT * FROM foo WHERE static_column = 'bar'
+ // would pull the full partition every time the static column of partition is 'bar', which sounds like offering a
+ // fair potential for foot-shooting, so I prefer leaving that to a follow up ticket once we have identified cases where
+ // such indexing is actually useful.
- if (cd.type == ColumnDefinition.Type.STATIC)
++ if (cd.isStatic())
+ throw new InvalidRequestException("Secondary indexes are not allowed on static columns");
+
- if (cd.getValidator().isCollection() && !properties.isCustom)
- throw new InvalidRequestException("Indexes on collections are no yet supported");
-
- if (cd.type == ColumnDefinition.Type.PARTITION_KEY && cd.componentIndex == null)
- throw new InvalidRequestException(String.format("Cannot add secondary index to already primarily indexed column %s", columnName));
+ if (cd.kind == ColumnDefinition.Kind.PARTITION_KEY && cd.isOnAllComponents())
+ throw new InvalidRequestException(String.format("Cannot add secondary index to already primarily indexed column %s", target.column));
}
public void announceMigration() throws RequestValidationException
http://git-wip-us.apache.org/repos/asf/cassandra/blob/63b1ef4e/src/java/org/apache/cassandra/cql3/statements/CreateTableStatement.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/CreateTableStatement.java
index 8351e71,632194c..7cef999
--- a/src/java/org/apache/cassandra/cql3/statements/CreateTableStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateTableStatement.java
@@@ -88,12 -89,25 +90,17 @@@ public class CreateTableStatement exten
}
// Column definitions
- private Map<ByteBuffer, ColumnDefinition> getColumns()
+ private List<ColumnDefinition> getColumns(CFMetaData cfm)
{
- Map<ByteBuffer, ColumnDefinition> columnDefs = new HashMap<ByteBuffer, ColumnDefinition>();
- Integer componentIndex = null;
- if (comparator instanceof CompositeType)
- {
- CompositeType ct = (CompositeType) comparator;
- componentIndex = ct.types.get(ct.types.size() - 1) instanceof ColumnToCollectionType
- ? ct.types.size() - 2
- : ct.types.size() - 1;
- }
-
+ List<ColumnDefinition> columnDefs = new ArrayList<>(columns.size());
+ Integer componentIndex = comparator.isCompound() ? comparator.clusteringPrefixSize() : null;
for (Map.Entry<ColumnIdentifier, AbstractType> col : columns.entrySet())
- columnDefs.add(ColumnDefinition.regularDef(cfm, col.getKey().bytes, col.getValue(), componentIndex));
+ {
+ ColumnIdentifier id = col.getKey();
- columnDefs.put(id.key, staticColumns.contains(id)
- ? ColumnDefinition.staticDef(id.key, col.getValue(), componentIndex)
- : ColumnDefinition.regularDef(id.key, col.getValue(), componentIndex));
++ columnDefs.add(staticColumns.contains(id)
++ ? ColumnDefinition.staticDef(cfm, col.getKey().bytes, col.getValue(), componentIndex)
++ : ColumnDefinition.regularDef(cfm, col.getKey().bytes, col.getValue(), componentIndex));
+ }
return columnDefs;
}
@@@ -185,13 -201,13 +193,13 @@@
properties.validate();
- CreateTableStatement stmt = new CreateTableStatement(cfName, properties, ifNotExists);
+ CreateTableStatement stmt = new CreateTableStatement(cfName, properties, ifNotExists, staticColumns);
Map<ByteBuffer, CollectionType> definedCollections = null;
- for (Map.Entry<ColumnIdentifier, CQL3Type> entry : definitions.entrySet())
+ for (Map.Entry<ColumnIdentifier, CQL3Type.Raw> entry : definitions.entrySet())
{
ColumnIdentifier id = entry.getKey();
- CQL3Type pt = entry.getValue();
+ CQL3Type pt = entry.getValue().prepare(keyspace());
if (pt.isCollection())
{
if (definedCollections == null)
@@@ -248,11 -268,13 +258,16 @@@
{
if (definedCollections != null)
throw new InvalidRequestException("Collection types are not supported with COMPACT STORAGE");
- stmt.columnAliases.add(columnAliases.get(0).bytes);
- AbstractType<?> at = getTypeAndRemove(stmt.columns, columnAliases.get(0));
++
+ ColumnIdentifier alias = columnAliases.get(0);
- stmt.columnAliases.add(alias.key);
- stmt.comparator = getTypeAndRemove(stmt.columns, alias);
- if (stmt.comparator instanceof CounterColumnType)
- throw new InvalidRequestException(String.format("counter type is not supported for PRIMARY KEY part %s", alias));
+ if (staticColumns.contains(alias))
+ throw new InvalidRequestException(String.format("Static column %s cannot be part of the PRIMARY KEY", alias));
++
++ stmt.columnAliases.add(alias.bytes);
++ AbstractType<?> at = getTypeAndRemove(stmt.columns, alias);
+ if (at instanceof CounterColumnType)
+ throw new InvalidRequestException(String.format("counter type is not supported for PRIMARY KEY part %s", stmt.columnAliases.get(0)));
+ stmt.comparator = new SimpleDenseCellNameType(at);
}
else
{
@@@ -263,7 -285,9 +278,9 @@@
AbstractType<?> type = getTypeAndRemove(stmt.columns, t);
if (type instanceof CounterColumnType)
- throw new InvalidRequestException(String.format("counter type is not supported for PRIMARY KEY part %s", t.key));
+ throw new InvalidRequestException(String.format("counter type is not supported for PRIMARY KEY part %s", t));
+ if (staticColumns.contains(t))
+ throw new InvalidRequestException(String.format("Static column %s cannot be part of the PRIMARY KEY", t));
types.add(type);
}
@@@ -358,7 -396,7 +385,7 @@@
return isReversed != null && isReversed ? ReversedType.getInstance(type) : type;
}
- public void addDefinition(ColumnIdentifier def, CQL3Type.Raw type)
- public void addDefinition(ColumnIdentifier def, CQL3Type type, boolean isStatic)
++ public void addDefinition(ColumnIdentifier def, CQL3Type.Raw type, boolean isStatic)
{
definedNames.add(def);
definitions.put(def, type);