Updated Branches: refs/heads/trunk 6cc509463 -> 371e7bf69
Better validation when accessing CQL3 table from thrift patch by slebresne; reviewed by jbellis for CASSANDRA-5138 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/371e7bf6 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/371e7bf6 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/371e7bf6 Branch: refs/heads/trunk Commit: 371e7bf69bbfdca0f5415e32a8c0f652711f5257 Parents: 6cc5094 Author: Sylvain Lebresne <sylv...@datastax.com> Authored: Mon Jul 22 16:48:24 2013 +0200 Committer: Sylvain Lebresne <sylv...@datastax.com> Committed: Wed Jul 24 17:04:13 2013 +0200 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cassandra/thrift/ThriftValidation.java | 34 ++++++++++++++++++++ 2 files changed, 35 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/371e7bf6/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index c9e229c..c081b45 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,7 @@ 2.0.0-rc1 * fix potential spurious wakeup in AsyncOneResponse (CASSANDRA-5690) * fix schema-related trigger issues (CASSANDRA-5774) + * Better validation when accessing CQL3 table from thrift (CASSANDRA-5138) 2.0.0-beta2 http://git-wip-us.apache.org/repos/asf/cassandra/blob/371e7bf6/src/java/org/apache/cassandra/thrift/ThriftValidation.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/thrift/ThriftValidation.java b/src/java/org/apache/cassandra/thrift/ThriftValidation.java index 23d21f8..ce8fdcb 100644 --- a/src/java/org/apache/cassandra/thrift/ThriftValidation.java +++ b/src/java/org/apache/cassandra/thrift/ThriftValidation.java @@ -25,13 +25,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.cassandra.config.*; +import org.apache.cassandra.cql3.CFDefinition; +import org.apache.cassandra.cql3.ColumnIdentifier; import org.apache.cassandra.db.*; import org.apache.cassandra.db.filter.IDiskAtomFilter; import org.apache.cassandra.db.filter.NamesQueryFilter; import org.apache.cassandra.db.filter.SliceQueryFilter; import org.apache.cassandra.db.index.SecondaryIndexManager; import org.apache.cassandra.db.marshal.AbstractType; +import org.apache.cassandra.db.marshal.ColumnToCollectionType; import org.apache.cassandra.db.marshal.CompositeType; +import org.apache.cassandra.db.marshal.UTF8Type; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.Token; import org.apache.cassandra.service.StorageService; @@ -207,6 +211,8 @@ public class ThriftValidation throw new org.apache.cassandra.exceptions.InvalidRequestException("supercolumn specified to ColumnFamily " + metadata.cfName + " containing normal columns"); } AbstractType<?> comparator = SuperColumns.getComparatorFor(metadata, superColumnName); + CFDefinition cfDef = metadata.getCfDef(); + boolean isCQL3Table = cfDef.isComposite && !cfDef.isCompact && !metadata.isSuper(); for (ByteBuffer name : column_names) { if (name.remaining() > maxNameLength) @@ -221,6 +227,34 @@ public class ThriftValidation { throw new org.apache.cassandra.exceptions.InvalidRequestException(e.getMessage()); } + + if (isCQL3Table) + { + // CQL3 table don't support having only part of their composite column names set + CompositeType composite = (CompositeType)comparator; + ByteBuffer[] components = composite.split(name); + int minComponents = composite.types.size() - (cfDef.hasCollections ? 1 : 0); + if (components.length < minComponents) + throw new org.apache.cassandra.exceptions.InvalidRequestException(String.format("Not enough component (found %d but %d expected) for column name since %s is a CQL3 table", + metadata.cfName, components.length, minComponents)); + + // Furthermore, the column name must be a declared one. + int columnIndex = composite.types.size() - (cfDef.hasCollections ? 2 : 1); + ByteBuffer CQL3ColumnName = components[columnIndex]; + ColumnIdentifier columnId = new ColumnIdentifier(CQL3ColumnName, composite.types.get(columnIndex)); + if (cfDef.columns.get(columnId) == null) + throw new org.apache.cassandra.exceptions.InvalidRequestException(String.format("Invalid cell for CQL3 table %s. The CQL3 column component (%s) does not correspond to a defined CQL3 column", + metadata.cfName, columnId)); + + // On top of that, if we have a collection component, he (CQL3) column must be a collection + if (cfDef.hasCollections && components.length == composite.types.size()) + { + assert components.length >= 2; + ColumnToCollectionType collectionType = (ColumnToCollectionType)composite.types.get(composite.types.size() - 1); + if (!collectionType.defined.containsKey(CQL3ColumnName)) + throw new org.apache.cassandra.exceptions.InvalidRequestException(String.format("Invalid collection component, %s is not a collection", UTF8Type.instance.getString(CQL3ColumnName))); + } + } } }