http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
----------------------------------------------------------------------
diff --cc 
src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
index 15a090b,84c6958..3b7504f
--- a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
@@@ -37,7 -37,7 +38,6 @@@ import org.apache.cassandra.exceptions.
  import org.apache.cassandra.index.Index;
  import org.apache.cassandra.index.SecondaryIndexManager;
  import org.apache.cassandra.net.MessagingService;
--import org.apache.cassandra.utils.ByteBufferUtil;
  import org.apache.cassandra.utils.btree.BTreeSet;
  
  import static 
org.apache.cassandra.cql3.statements.RequestValidations.checkFalse;
@@@ -163,20 -159,12 +163,23 @@@ public final class StatementRestriction
                  for (ColumnDefinition def : relation.toRestriction(cfm, 
boundNames).getColumnDefs())
                      this.notNullColumns.add(def);
              }
 +            else if (relation.isLIKE())
 +            {
 +                Restriction restriction = relation.toRestriction(cfm, 
boundNames);
 +
 +                if (!type.allowUseOfSecondaryIndices() || 
!restriction.hasSupportingIndex(secondaryIndexManager))
 +                    throw new InvalidRequestException(String.format("LIKE 
restriction is only supported on properly " +
 +                                                                    "indexed 
columns. %s is not valid.",
 +                                                                    
relation.toString()));
 +
 +                addRestriction(restriction);
 +            }
              else
              {
-                 addRestriction(relation.toRestriction(cfm, boundNames));
+                 if (cfm.isSuper() && cfm.isDense() && !relation.onToken())
+                     
addRestriction(relation.toSuperColumnAdapter().toRestriction(cfm, boundNames));
+                 else
+                     addRestriction(relation.toRestriction(cfm, boundNames));
              }
          }
  
@@@ -250,11 -237,18 +253,18 @@@
                                       Joiner.on(", 
").join(nonPrimaryKeyColumns));
              }
              if (hasQueriableIndex)
+             {
                  usesSecondaryIndexing = true;
-             else if (!allowFiltering)
+             }
+             else if (!allowFiltering && !cfm.isSuper())
+             {
                  throw 
invalidRequest(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE);
+             }
+ 
+             checkFalse(clusteringColumnsRestrictions.isEmpty() && 
cfm.isSuper(),
+                        "Filtering is not supported on SuperColumn tables");
  
 -            indexRestrictions.add(nonPrimaryKeyRestrictions);
 +            filterRestrictions.add(nonPrimaryKeyRestrictions);
          }
  
          if (usesSecondaryIndexing)
@@@ -824,18 -852,21 +834,29 @@@
      public boolean hasAllPKColumnsRestrictedByEqualities()
      {
          return !isPartitionKeyRestrictionsOnToken()
 -               && !hasUnrestrictedPartitionKeyComponents()
 -               && (partitionKeyRestrictions.isEQ() || 
partitionKeyRestrictions.isIN())
 -               && !hasUnrestrictedClusteringColumns()
 -               && (clusteringColumnsRestrictions.isEQ() || 
clusteringColumnsRestrictions.isIN());
 +                && 
!partitionKeyRestrictions.hasUnrestrictedPartitionKeyComponents(cfm)
 +                && (partitionKeyRestrictions.hasOnlyEqualityRestrictions())
 +                && !hasUnrestrictedClusteringColumns()
 +                && 
(clusteringColumnsRestrictions.hasOnlyEqualityRestrictions());
      }
  
 +    /**
 +     * Checks if one of the restrictions applies to a regular column.
 +     * @return {@code true} if one of the restrictions applies to a regular 
column, {@code false} otherwise.
 +     */
 +    public boolean hasRegularColumnsRestrictions()
 +    {
 +        return hasRegularColumnsRestrictions;
 +    }
+ 
+     private SuperColumnCompatibility.SuperColumnRestrictions cached;
+     public SuperColumnCompatibility.SuperColumnRestrictions 
getSuperColumnRestrictions()
+     {
+         assert cfm.isSuper() && cfm.isDense();
+ 
+         if (cached == null)
 -            cached = new 
SuperColumnCompatibility.SuperColumnRestrictions(Iterators.concat(((PrimaryKeyRestrictionSet)
 clusteringColumnsRestrictions).iterator(),
++            cached = new 
SuperColumnCompatibility.SuperColumnRestrictions(Iterators.concat(clusteringColumnsRestrictions.iterator(),
+                                                                               
             nonPrimaryKeyRestrictions.iterator()));
+         return cached;
+     }
  }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/cql3/restrictions/TermSlice.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/cql3/statements/CreateViewStatement.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
index 26b25de,a0919d7..a343fb4
--- a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
@@@ -139,17 -139,25 +139,25 @@@ public class DeleteStatement extends Mo
          {
              Operations operations = new Operations(type);
  
-             for (Operation.RawDeletion deletion : deletions)
+             if (cfm.isSuper() && cfm.isDense())
              {
-                 ColumnDefinition def = getColumnDefinition(cfm, 
deletion.affectedColumn());
- 
-                 // For compact, we only have one value except the key, so the 
only form of DELETE that make sense is without a column
-                 // list. However, we support having the value name for 
coherence with the static/sparse case
-                 checkFalse(def.isPrimaryKeyColumn(), "Invalid identifier %s 
for deletion (should not be a PRIMARY KEY part)", def.name);
- 
-                 Operation op = deletion.prepare(cfm.ksName, def, cfm);
-                 op.collectMarkerSpecification(boundNames);
-                 operations.add(op);
+                 conditions = 
SuperColumnCompatibility.rebuildLWTColumnConditions(conditions, cfm, 
whereClause);
+                 whereClause = 
SuperColumnCompatibility.prepareDeleteOperations(cfm, whereClause, boundNames, 
operations);
+             }
+             else
+             {
+                 for (Operation.RawDeletion deletion : deletions)
+                 {
+                     ColumnDefinition def = getColumnDefinition(cfm, 
deletion.affectedColumn());
+ 
+                     // For compact, we only have one value except the key, so 
the only form of DELETE that make sense is without a column
+                     // list. However, we support having the value name for 
coherence with the static/sparse case
+                     checkFalse(def.isPrimaryKeyColumn(), "Invalid identifier 
%s for deletion (should not be a PRIMARY KEY part)", def.name);
+ 
 -                    Operation op = deletion.prepare(cfm.ksName, def);
++                    Operation op = deletion.prepare(cfm.ksName, def, cfm);
+                     op.collectMarkerSpecification(boundNames);
+                     operations.add(op);
+                 }
              }
  
              StatementRestrictions restrictions = newRestrictions(cfm,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
----------------------------------------------------------------------
diff --cc 
src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
index c925128,28fc90f..c8c7570
--- a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
@@@ -549,19 -544,25 +549,28 @@@ public abstract class ModificationState
                  defs.addAll(cfm.partitionKeyColumns());
                  defs.addAll(cfm.clusteringColumns());
              }
-             for (ColumnDefinition def : columnsWithConditions)
-                 defs.add(def);
-             selection = Selection.forColumns(cfm, new ArrayList<>(defs));
  
+ 
+             if (cfm.isSuper() && cfm.isDense())
+             {
+                 defs.add(cfm.superColumnValueColumn());
+             }
+             else
+             {
+                 for (ColumnDefinition def : columnsWithConditions)
+                     defs.add(def);
+             }
+ 
+             selection = Selection.forColumns(cfm, new ArrayList<>(defs));
          }
  
 -        Selection.ResultSetBuilder builder = 
selection.resultSetBuilder(false);
 -        SelectStatement.forSelection(cfm, 
selection).processPartition(partition, options, builder, 
FBUtilities.nowInSeconds());
 +        Selection.ResultSetBuilder builder = 
selection.resultSetBuilder(options, false);
 +        SelectStatement.forSelection(cfm, 
selection).processPartition(partition,
 +                                                                      options,
 +                                                                      builder,
 +                                                                      
FBUtilities.nowInSeconds());
  
 -        return builder.build(options.getProtocolVersion());
 +        return builder.build();
      }
  
      public ResultMessage executeInternal(QueryState queryState, QueryOptions 
options) throws RequestValidationException, RequestExecutionException

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
index 85efafb,2e090fa..33a69e7
--- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
@@@ -18,10 -18,20 +18,19 @@@
  package org.apache.cassandra.cql3.statements;
  
  import java.nio.ByteBuffer;
- import java.util.*;
+ import java.util.ArrayList;
+ import java.util.Collection;
+ import java.util.Collections;
+ import java.util.Comparator;
+ import java.util.HashMap;
+ import java.util.Iterator;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.NavigableSet;
+ import java.util.SortedSet;
  
 -import com.google.common.base.Objects;
 -import com.google.common.base.Predicate;
 -import com.google.common.collect.Iterables;
 +import com.google.common.base.MoreObjects;
 +
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
@@@ -33,9 -53,25 +52,26 @@@ import org.apache.cassandra.cql3.functi
  import org.apache.cassandra.cql3.restrictions.StatementRestrictions;
  import org.apache.cassandra.cql3.selection.RawSelector;
  import org.apache.cassandra.cql3.selection.Selection;
 +import org.apache.cassandra.db.*;
 +import org.apache.cassandra.db.aggregation.AggregationSpecification;
- import org.apache.cassandra.db.filter.*;
+ import org.apache.cassandra.db.Clustering;
+ import org.apache.cassandra.db.ColumnFamilyStore;
+ import org.apache.cassandra.db.ConsistencyLevel;
+ import org.apache.cassandra.db.DataRange;
+ import org.apache.cassandra.db.DecoratedKey;
+ import org.apache.cassandra.db.Keyspace;
+ import org.apache.cassandra.db.PartitionPosition;
+ import org.apache.cassandra.db.PartitionRangeReadCommand;
 -import org.apache.cassandra.db.ReadOrderGroup;
+ import org.apache.cassandra.db.ReadQuery;
+ import org.apache.cassandra.db.SinglePartitionReadCommand;
+ import org.apache.cassandra.db.Slice;
+ import org.apache.cassandra.db.Slices;
+ import org.apache.cassandra.db.filter.ClusteringIndexFilter;
+ import org.apache.cassandra.db.filter.ClusteringIndexNamesFilter;
+ import org.apache.cassandra.db.filter.ClusteringIndexSliceFilter;
+ import org.apache.cassandra.db.filter.ColumnFilter;
+ import org.apache.cassandra.db.filter.DataLimits;
+ import org.apache.cassandra.db.filter.RowFilter;
  import org.apache.cassandra.db.marshal.CollectionType;
  import org.apache.cassandra.db.marshal.CompositeType;
  import org.apache.cassandra.db.marshal.Int32Type;
@@@ -46,7 -81,11 +82,10 @@@ import org.apache.cassandra.db.rows.Row
  import org.apache.cassandra.db.rows.RowIterator;
  import org.apache.cassandra.db.view.View;
  import org.apache.cassandra.dht.AbstractBounds;
- import org.apache.cassandra.exceptions.*;
+ import org.apache.cassandra.exceptions.InvalidRequestException;
+ import org.apache.cassandra.exceptions.RequestExecutionException;
+ import org.apache.cassandra.exceptions.RequestValidationException;
+ import org.apache.cassandra.exceptions.UnauthorizedException;
 -import org.apache.cassandra.exceptions.UnrecognizedEntityException;
  import org.apache.cassandra.index.SecondaryIndexManager;
  import org.apache.cassandra.serializers.MarshalException;
  import org.apache.cassandra.service.ClientState;
@@@ -778,7 -771,13 +818,13 @@@ public class SelectStatement implement
      void processPartition(RowIterator partition, QueryOptions options, 
Selection.ResultSetBuilder result, int nowInSec)
      throws InvalidRequestException
      {
+         if (cfm.isSuper() && cfm.isDense())
+         {
+             SuperColumnCompatibility.processPartition(cfm, selection, 
partition, result, options.getProtocolVersion(), 
restrictions.getSuperColumnRestrictions(), options);
+             return;
+         }
+ 
 -        int protocolVersion = options.getProtocolVersion();
 +        ProtocolVersion protocolVersion = options.getProtocolVersion();
  
          ByteBuffer[] keyComponents = getComponents(cfm, 
partition.partitionKey());
  

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
index 6bcfd9c,641b6bb..6638752
--- a/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
@@@ -155,24 -155,33 +155,33 @@@ public class UpdateStatement extends Mo
              Operations operations = new Operations(type);
              boolean hasClusteringColumnsSet = false;
  
-             for (int i = 0; i < columnNames.size(); i++)
+             if (cfm.isSuper() && cfm.isDense())
              {
-                 ColumnDefinition def = getColumnDefinition(cfm, 
columnNames.get(i));
- 
-                 if (def.isClusteringColumn())
-                     hasClusteringColumnsSet = true;
- 
-                 Term.Raw value = columnValues.get(i);
- 
-                 if (def.isPrimaryKeyColumn())
-                 {
-                     whereClause.add(new 
SingleColumnRelation(columnNames.get(i), Operator.EQ, value));
-                 }
-                 else
+                 // SuperColumn familiy updates are always row-level
+                 hasClusteringColumnsSet = true;
+                 SuperColumnCompatibility.prepareInsertOperations(cfm, 
columnNames, whereClause, columnValues, boundNames, operations);
+             }
+             else
+             {
+                 for (int i = 0; i < columnNames.size(); i++)
                  {
-                     Operation operation = new 
Operation.SetValue(value).prepare(cfm, def);
-                     operation.collectMarkerSpecification(boundNames);
-                     operations.add(operation);
+                     ColumnDefinition def = getColumnDefinition(cfm, 
columnNames.get(i));
+ 
+                     if (def.isClusteringColumn())
+                         hasClusteringColumnsSet = true;
+ 
+                     Term.Raw value = columnValues.get(i);
+ 
+                     if (def.isPrimaryKeyColumn())
+                     {
+                         whereClause.add(new 
SingleColumnRelation(columnNames.get(i), Operator.EQ, value));
+                     }
+                     else
+                     {
 -                        Operation operation = new 
Operation.SetValue(value).prepare(cfm.ksName, def);
++                        Operation operation = new 
Operation.SetValue(value).prepare(cfm, def);
+                         operation.collectMarkerSpecification(boundNames);
+                         operations.add(operation);
+                     }
                  }
              }
  
@@@ -227,25 -234,33 +236,42 @@@
              Operations operations = new Operations(type);
              boolean hasClusteringColumnsSet = false;
  
+             if (cfm.isSuper() && cfm.isDense())
+             {
+                 hasClusteringColumnsSet = true;
+                 SuperColumnCompatibility.prepareInsertJSONOperations(cfm, 
defs, boundNames, prepared, whereClause, operations);
+             }
+             else
+             {
 -                for (ColumnDefinition def : defs)
 -                {
 -                    if (def.isClusteringColumn())
 -                        hasClusteringColumnsSet = true;
+ 
 -                    Term.Raw raw = prepared.getRawTermForColumn(def);
 -                    if (def.isPrimaryKeyColumn())
 -                    {
 -                        whereClause.add(new SingleColumnRelation(new 
ColumnIdentifier.ColumnIdentifierValue(def.name), Operator.EQ, raw));
 -                    }
 -                    else
 -                    {
 -                        Operation operation = new 
Operation.SetValue(raw).prepare(cfm.ksName, def);
 -                        operation.collectMarkerSpecification(boundNames);
 -                        operations.add(operation);
 -                    }
++
++
++// TODO: indent
++
 +            for (ColumnDefinition def : defs)
 +            {
 +                if (def.isClusteringColumn())
 +                    hasClusteringColumnsSet = true;
 +
 +                Term.Raw raw = prepared.getRawTermForColumn(def, 
defaultUnset);
 +                if (def.isPrimaryKeyColumn())
 +                {
 +                    whereClause.add(new 
SingleColumnRelation(ColumnDefinition.Raw.forColumn(def), Operator.EQ, raw));
                  }
 +                else
 +                {
 +                    Operation operation = new 
Operation.SetValue(raw).prepare(cfm, def);
 +                    operation.collectMarkerSpecification(boundNames);
 +                    operations.add(operation);
 +                }
 +            }
 +
++
++
++
+             }
+ 
 -            boolean applyOnlyToStaticColumns = 
appliesOnlyToStaticColumns(operations, conditions) && !hasClusteringColumnsSet;
 +            boolean applyOnlyToStaticColumns = !hasClusteringColumnsSet && 
appliesOnlyToStaticColumns(operations, conditions);
  
              StatementRestrictions restrictions = new 
StatementRestrictions(type,
                                                                             
cfm,
@@@ -269,8 -284,8 +295,8 @@@
      public static class ParsedUpdate extends ModificationStatement.Parsed
      {
          // Provided for an UPDATE
 -        private final List<Pair<ColumnIdentifier.Raw, Operation.RawUpdate>> 
updates;
 +        private final List<Pair<ColumnDefinition.Raw, Operation.RawUpdate>> 
updates;
-         private final WhereClause whereClause;
+         private WhereClause whereClause;
  
          /**
           * Creates a new UpdateStatement from a column family name, columns 
map, consistency
@@@ -302,17 -317,25 +328,25 @@@
          {
              Operations operations = new Operations(type);
  
-             for (Pair<ColumnDefinition.Raw, Operation.RawUpdate> entry : 
updates)
+             if (cfm.isSuper() && cfm.isDense())
+             {
+                 conditions = 
SuperColumnCompatibility.rebuildLWTColumnConditions(conditions, cfm, 
whereClause);
+                 whereClause = 
SuperColumnCompatibility.prepareUpdateOperations(cfm, whereClause, updates, 
boundNames, operations);
+             }
+             else
              {
-                 ColumnDefinition def = getColumnDefinition(cfm, entry.left);
 -                for (Pair<ColumnIdentifier.Raw, Operation.RawUpdate> entry : 
updates)
++                for (Pair<ColumnDefinition.Raw, Operation.RawUpdate> entry : 
updates)
+                 {
+                     ColumnDefinition def = getColumnDefinition(cfm, 
entry.left);
  
-                 checkFalse(def.isPrimaryKeyColumn(), "PRIMARY KEY part %s 
found in SET part", def.name);
+                     checkFalse(def.isPrimaryKeyColumn(), "PRIMARY KEY part %s 
found in SET part", def.name);
  
-                 Operation operation = entry.right.prepare(cfm, def);
-                 operation.collectMarkerSpecification(boundNames);
-                 operations.add(operation);
 -                    Operation operation = entry.right.prepare(cfm.ksName, 
def);
++                    Operation operation = entry.right.prepare(cfm, def);
+                     operation.collectMarkerSpecification(boundNames);
+                     operations.add(operation);
+                 }
              }
- 
+             
              StatementRestrictions restrictions = newRestrictions(cfm,
                                                                   boundNames,
                                                                   operations,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/db/Columns.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/db/LegacyLayout.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/LegacyLayout.java
index 10fa021,40b9fd3..77aa59a
--- a/src/java/org/apache/cassandra/db/LegacyLayout.java
+++ b/src/java/org/apache/cassandra/db/LegacyLayout.java
@@@ -24,7 -24,7 +24,8 @@@ import java.nio.ByteBuffer
  import java.security.MessageDigest;
  import java.util.*;
  
+ import org.apache.cassandra.cql3.SuperColumnCompatibility;
 +import org.apache.cassandra.config.SchemaConstants;
  import org.apache.cassandra.utils.AbstractIterator;
  import com.google.common.collect.Iterators;
  import com.google.common.collect.Lists;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/db/SerializationHeader.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
index 97d60d5,01c5e3e..04d5f4e
--- a/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
+++ b/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
@@@ -29,8 -29,8 +29,9 @@@ import org.slf4j.LoggerFactory
  
  import org.apache.cassandra.config.*;
  import org.apache.cassandra.cql3.ColumnIdentifier;
 +import org.apache.cassandra.cql3.FieldIdentifier;
  import org.apache.cassandra.cql3.QueryProcessor;
+ import org.apache.cassandra.cql3.SuperColumnCompatibility;
  import org.apache.cassandra.cql3.UntypedResultSet;
  import org.apache.cassandra.cql3.functions.FunctionName;
  import org.apache.cassandra.cql3.functions.UDAggregate;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/thrift/CassandraServer.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/src/java/org/apache/cassandra/thrift/ThriftConversion.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/test/unit/org/apache/cassandra/SchemaLoader.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/SchemaLoader.java
index 2bf4805,1686973..567da19
--- a/test/unit/org/apache/cassandra/SchemaLoader.java
+++ b/test/unit/org/apache/cassandra/SchemaLoader.java
@@@ -407,28 -391,17 +406,22 @@@ public class SchemaLoade
      {
          return superCFMD(ksName, cfName, BytesType.instance, subcc);
      }
+ 
      public static CFMetaData superCFMD(String ksName, String cfName, 
AbstractType cc, AbstractType subcc)
      {
-         return superCFMD(ksName, cfName, "cols", cc, subcc);
-     }
-     public static CFMetaData superCFMD(String ksName, String cfName, String 
ccName, AbstractType cc, AbstractType subcc)
-     {
-         //This is busted
- //        return CFMetaData.Builder.createSuper(ksName, cfName, false)
- //            .addPartitionKey("0", BytesType.instance)
- //            .addClusteringColumn("1", cc)
- //            .addClusteringColumn("2", subcc)
- //            .addRegularColumn("3", AsciiType.instance)
- //            .build();
-         return standardCFMD(ksName, cfName);
+         return CFMetaData.Builder.createSuper(ksName, cfName, false)
+                                  .addPartitionKey("key", BytesType.instance)
+                                  .addClusteringColumn("column1", cc)
+                                  .addRegularColumn("", 
MapType.getInstance(AsciiType.instance, subcc, true))
+                                  .build();
  
      }
 -    public static CFMetaData compositeIndexCFMD(String ksName, String cfName, 
boolean withIndex) throws ConfigurationException
 +    public static CFMetaData compositeIndexCFMD(String ksName, String cfName, 
boolean withRegularIndex) throws ConfigurationException
 +    {
 +        return compositeIndexCFMD(ksName, cfName, withRegularIndex, false);
 +    }
 +
 +    public static CFMetaData compositeIndexCFMD(String ksName, String cfName, 
boolean withRegularIndex, boolean withStaticIndex) throws ConfigurationException
      {
          // the withIndex flag exists to allow tests index creation
          // on existing columns

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/test/unit/org/apache/cassandra/cql3/ViewTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/ViewTest.java
index 8428e42,4a4fe1a..7717a4d
--- a/test/unit/org/apache/cassandra/cql3/ViewTest.java
+++ b/test/unit/org/apache/cassandra/cql3/ViewTest.java
@@@ -45,9 -47,12 +47,13 @@@ import org.apache.cassandra.db.ColumnFa
  import org.apache.cassandra.db.Keyspace;
  import org.apache.cassandra.db.SystemKeyspace;
  import org.apache.cassandra.db.compaction.CompactionManager;
+ import org.apache.cassandra.db.marshal.AsciiType;
+ import org.apache.cassandra.schema.KeyspaceParams;
 +import org.apache.cassandra.transport.ProtocolVersion;
  import org.apache.cassandra.utils.FBUtilities;
  
+ import static org.junit.Assert.assertEquals;
+ import static org.junit.Assert.assertTrue;
  
  public class ViewTest extends CQLTester
  {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/test/unit/org/apache/cassandra/cql3/validation/ThriftIntegrationTest.java
----------------------------------------------------------------------
diff --cc 
test/unit/org/apache/cassandra/cql3/validation/ThriftIntegrationTest.java
index 0000000,def489e..7e89228
mode 000000,100644..100644
--- a/test/unit/org/apache/cassandra/cql3/validation/ThriftIntegrationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/ThriftIntegrationTest.java
@@@ -1,0 -1,942 +1,942 @@@
+ /*
+  * 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.validation;
+ 
+ import java.nio.ByteBuffer;
+ import java.util.Arrays;
+ import java.util.Collections;
+ import java.util.List;
+ import java.util.concurrent.atomic.AtomicInteger;
+ 
+ import org.junit.After;
+ import org.junit.Before;
+ import org.junit.Test;
+ 
+ import org.apache.cassandra.cql3.ColumnIdentifier;
+ import org.apache.cassandra.cql3.UntypedResultSet;
+ import org.apache.cassandra.cql3.validation.operations.ThriftCQLTester;
+ import org.apache.cassandra.db.Keyspace;
+ import org.apache.cassandra.db.marshal.AsciiType;
+ import org.apache.cassandra.db.marshal.CounterColumnType;
+ import org.apache.cassandra.db.marshal.Int32Type;
+ import org.apache.cassandra.db.marshal.LongType;
+ import org.apache.cassandra.locator.SimpleStrategy;
+ import org.apache.cassandra.service.StorageService;
+ import org.apache.cassandra.thrift.Cassandra;
+ import org.apache.cassandra.thrift.CfDef;
+ import org.apache.cassandra.thrift.Column;
+ import org.apache.cassandra.thrift.ColumnDef;
+ import org.apache.cassandra.thrift.ColumnOrSuperColumn;
+ import org.apache.cassandra.thrift.ColumnParent;
+ import org.apache.cassandra.thrift.ColumnPath;
+ import org.apache.cassandra.thrift.CounterColumn;
+ import org.apache.cassandra.thrift.CounterSuperColumn;
+ import org.apache.cassandra.thrift.Deletion;
+ import org.apache.cassandra.thrift.KsDef;
+ import org.apache.cassandra.thrift.Mutation;
+ import org.apache.cassandra.thrift.SlicePredicate;
+ import org.apache.cassandra.thrift.SliceRange;
+ import org.apache.cassandra.thrift.SuperColumn;
+ import org.apache.cassandra.utils.ByteBufferUtil;
+ import org.apache.cassandra.utils.FBUtilities;
+ 
+ import static org.apache.cassandra.thrift.ConsistencyLevel.ONE;
+ import static org.junit.Assert.assertEquals;
+ 
+ public class ThriftIntegrationTest extends ThriftCQLTester
+ {
+     final static AtomicInteger seqNumber = new AtomicInteger();
+     final String KEYSPACE = "thrift_compact_table_with_supercolumns_test_" + 
seqNumber.incrementAndGet();
+ 
+     @Before
+     public void setupSuperColumnFamily() throws Throwable
+     {
+         StorageService.instance.setRpcReady(true);
+ 
+         final String denseTableName = createTableName();
+         final String sparseTableName =  currentSparseTable();
+         final String counterTableName = currentCounterTable();
+ 
+         CfDef cfDef = new CfDef().setColumn_type("Super")
+                                  
.setSubcomparator_type(Int32Type.instance.toString())
+                                  
.setComparator_type(AsciiType.instance.toString())
+                                  
.setDefault_validation_class(AsciiType.instance.toString())
+                                  
.setKey_validation_class(AsciiType.instance.toString())
+                                  .setKeyspace(KEYSPACE)
+                                  .setName(denseTableName);
+ 
+         CfDef sparseCfDef = new CfDef().setColumn_type("Super")
+                                        
.setComparator_type(AsciiType.instance.toString())
+                                        
.setSubcomparator_type(AsciiType.instance.toString())
+                                        
.setKey_validation_class(AsciiType.instance.toString())
+                                        .setColumn_metadata(Arrays.asList(new 
ColumnDef(ByteBufferUtil.bytes("col1"), LongType.instance.toString()),
+                                                                          new 
ColumnDef(ByteBufferUtil.bytes("col2"), LongType.instance.toString())))
+                                        .setKeyspace(KEYSPACE)
+                                        .setName(sparseTableName);
+ 
+         CfDef counterCfDef = new CfDef().setColumn_type("Super")
+                                         
.setSubcomparator_type(AsciiType.instance.toString())
+                                         
.setComparator_type(AsciiType.instance.toString())
+                                         
.setDefault_validation_class(CounterColumnType.instance.toString())
+                                         
.setKey_validation_class(AsciiType.instance.toString())
+                                         .setKeyspace(KEYSPACE)
+                                         .setName(counterTableName);
+ 
+         KsDef ksDef = new KsDef(KEYSPACE,
+                                 SimpleStrategy.class.getName(),
+                                 Arrays.asList(cfDef, sparseCfDef, 
counterCfDef));
+ 
+         
ksDef.setStrategy_options(Collections.singletonMap("replication_factor", "1"));
+ 
+         Cassandra.Client client = getClient();
+         client.system_add_keyspace(ksDef);
+         client.set_keyspace(KEYSPACE);
+     }
+ 
+     @After
+     public void tearDown() throws Throwable
+     {
+         getClient().send_system_drop_keyspace(KEYSPACE);
+     }
+ 
+     @Test
+     public void testCounterTableReads() throws Throwable
+     {
+         populateCounterTable();
+         beforeAndAfterFlush(this::testCounterTableReadsInternal);
+     }
+ 
+     private void testCounterTableReadsInternal() throws Throwable
+     {
+         UntypedResultSet resultSet = execute(String.format("select * from 
%s.%s", KEYSPACE, currentCounterTable()));
+         assertRows(resultSet,
+                    row("key1", "ck1", "counter1", 10L),
+                    row("key1", "ck1", "counter2", 5L),
+                    row("key2", "ck1", "counter1", 10L),
+                    row("key2", "ck1", "counter2", 5L));
+     }
+ 
+     @Test
+     public void testCounterTableThriftUpdates() throws Throwable
+     {
+         populateCounterTable();
+ 
+         Cassandra.Client client = getClient();
+         Mutation mutation = new Mutation();
+         ColumnOrSuperColumn csoc = new ColumnOrSuperColumn();
+         csoc.setCounter_super_column(new 
CounterSuperColumn(ByteBufferUtil.bytes("ck1"),
+                                                             Arrays.asList(new 
CounterColumn(ByteBufferUtil.bytes("counter1"), 1))));
+         mutation.setColumn_or_supercolumn(csoc);
+ 
+         Mutation mutation2 = new Mutation();
+         ColumnOrSuperColumn csoc2 = new ColumnOrSuperColumn();
+         csoc2.setCounter_super_column(new 
CounterSuperColumn(ByteBufferUtil.bytes("ck1"),
+                                                              
Arrays.asList(new CounterColumn(ByteBufferUtil.bytes("counter1"), 100))));
+         mutation2.setColumn_or_supercolumn(csoc2);
+         
client.batch_mutate(Collections.singletonMap(ByteBufferUtil.bytes("key1"),
+                                                      
Collections.singletonMap(currentCounterTable(), Arrays.asList(mutation))),
+                             ONE);
+         
client.batch_mutate(Collections.singletonMap(ByteBufferUtil.bytes("key2"),
+                                                      
Collections.singletonMap(currentCounterTable(), Arrays.asList(mutation2))),
+                             ONE);
+ 
+         beforeAndAfterFlush(() -> {
+             UntypedResultSet resultSet = execute(String.format("select * from 
%s.%s", KEYSPACE, currentCounterTable()));
+             assertRows(resultSet,
+                        row("key1", "ck1", "counter1", 11L),
+                        row("key1", "ck1", "counter2", 5L),
+                        row("key2", "ck1", "counter1", 110L),
+                        row("key2", "ck1", "counter2", 5L));
+         });
+     }
+ 
+     @Test
+     public void testCounterTableCqlUpdates() throws Throwable
+     {
+         populateCounterTable();
+ 
+         execute(String.format("UPDATE %s.%s set value = value + 1 WHERE key = 
? AND column1 = ? AND column2 = ?", KEYSPACE, currentCounterTable()),
+                 "key1", "ck1", "counter1");
+         execute(String.format("UPDATE %s.%s set value = value + 100 WHERE key 
= 'key2' AND column1 = 'ck1' AND column2 = 'counter1'", KEYSPACE, 
currentCounterTable()));
+ 
+         execute(String.format("UPDATE %s.%s set value = value - ? WHERE key = 
'key1' AND column1 = 'ck1' AND column2 = 'counter2'", KEYSPACE, 
currentCounterTable()), 2L);
+         execute(String.format("UPDATE %s.%s set value = value - ? WHERE key = 
'key2' AND column1 = 'ck1' AND column2 = 'counter2'", KEYSPACE, 
currentCounterTable()), 100L);
+ 
+         beforeAndAfterFlush(() -> {
+             UntypedResultSet resultSet = execute(String.format("select * from 
%s.%s", KEYSPACE, currentCounterTable()));
+             assertRows(resultSet,
+                        row("key1", "ck1", "counter1", 11L),
+                        row("key1", "ck1", "counter2", 3L),
+                        row("key2", "ck1", "counter1", 110L),
+                        row("key2", "ck1", "counter2", -95L));
+         });
+     }
+ 
+     @Test
+     public void testCounterTableCqlDeletes() throws Throwable
+     {
+         populateCounterTable();
+ 
+         assertRows(execute(String.format("select * from %s.%s", KEYSPACE, 
currentCounterTable())),
+                    row("key1", "ck1", "counter1", 10L),
+                    row("key1", "ck1", "counter2", 5L),
+                    row("key2", "ck1", "counter1", 10L),
+                    row("key2", "ck1", "counter2", 5L));
+ 
+         execute(String.format("DELETE value FROM %s.%s WHERE key = ? AND 
column1 = ? AND column2 = ?", KEYSPACE, currentCounterTable()),
+                 "key1", "ck1", "counter1");
+ 
+         assertRows(execute(String.format("select * from %s.%s", KEYSPACE, 
currentCounterTable())),
+                    row("key1", "ck1", "counter2", 5L),
+                    row("key2", "ck1", "counter1", 10L),
+                    row("key2", "ck1", "counter2", 5L));
+ 
+         execute(String.format("DELETE FROM %s.%s WHERE key = ? AND column1 = 
?", KEYSPACE, currentCounterTable()),
+                 "key1", "ck1");
+ 
+         assertRows(execute(String.format("select * from %s.%s", KEYSPACE, 
currentCounterTable())),
+                    row("key2", "ck1", "counter1", 10L),
+                    row("key2", "ck1", "counter2", 5L));
+ 
+         execute(String.format("DELETE FROM %s.%s WHERE key = ?", KEYSPACE, 
currentCounterTable()),
+                 "key2");
+ 
+         assertEmpty(execute(String.format("select * from %s.%s", KEYSPACE, 
currentCounterTable())));
+     }
+ 
+     @Test
+     public void testDenseTableAlter() throws Throwable
+     {
+         populateDenseTable();
+ 
+         alterTable(String.format("ALTER TABLE %s.%s RENAME column1 TO 
renamed_column1", KEYSPACE, currentDenseTable()));
+         alterTable(String.format("ALTER TABLE %s.%s RENAME column2 TO 
renamed_column2", KEYSPACE, currentDenseTable()));
+         alterTable(String.format("ALTER TABLE %s.%s RENAME key TO 
renamed_key", KEYSPACE, currentDenseTable()));
+         alterTable(String.format("ALTER TABLE %s.%s RENAME value TO 
renamed_value", KEYSPACE, currentDenseTable()));
+ 
+         beforeAndAfterFlush(() -> {
+             UntypedResultSet resultSet = execute(String.format("select * from 
%s.%s", KEYSPACE, currentDenseTable()));
+             assertEquals("renamed_key", 
resultSet.metadata().get(0).name.toString());
+             assertEquals("renamed_column1", 
resultSet.metadata().get(1).name.toString());
+                                 assertEquals("renamed_column2", 
resultSet.metadata().get(2).name.toString());
+                                 assertEquals("renamed_value", 
resultSet.metadata().get(3).name.toString());
+             assertRows(resultSet,
+                        row("key1", "val1", 1, "value1"),
+                        row("key1", "val1", 2, "value2"),
+                        row("key1", "val2", 4, "value4"),
+                        row("key1", "val2", 5, "value5"),
+                        row("key2", "val1", 1, "value1"),
+                        row("key2", "val1", 2, "value2"),
+                        row("key2", "val2", 4, "value4"),
+                        row("key2", "val2", 5, "value5"));
+         });
+     }
+ 
+     @Test
+     public void testDenseTableReads() throws Throwable
+     {
+         populateDenseTable();
+         beforeAndAfterFlush(this::testDenseTableReadsInternal);
+     }
+ 
+     private void testDenseTableReadsInternal() throws Throwable
+     {
+         UntypedResultSet resultSet = execute(String.format("select * from 
%s.%s", KEYSPACE, currentDenseTable()));
+         assertEquals("key", resultSet.metadata().get(0).name.toString());
+         assertEquals("column1", resultSet.metadata().get(1).name.toString());
+         assertEquals("column2", resultSet.metadata().get(2).name.toString());
+         assertEquals("value", resultSet.metadata().get(3).name.toString());
+ 
+ 
+         assertRows(resultSet,
+                    row("key1", "val1", 1, "value1"),
+                    row("key1", "val1", 2, "value2"),
+                    row("key1", "val2", 4, "value4"),
+                    row("key1", "val2", 5, "value5"),
+                    row("key2", "val1", 1, "value1"),
+                    row("key2", "val1", 2, "value2"),
+                    row("key2", "val2", 4, "value4"),
+                    row("key2", "val2", 5, "value5"));
+ 
+         assertRows(execute(String.format("select * from %s.%s LIMIT 5", 
KEYSPACE, currentDenseTable())),
+                    row("key1", "val1", 1, "value1"),
+                    row("key1", "val1", 2, "value2"),
+                    row("key1", "val2", 4, "value4"),
+                    row("key1", "val2", 5, "value5"),
+                    row("key2", "val1", 1, "value1"));
+ 
+         assertRows(execute(String.format("select value, column2, column1, key 
from %s.%s", KEYSPACE, currentDenseTable())),
+                    row("value1", 1, "val1", "key1"),
+                    row("value2", 2, "val1", "key1"),
+                    row("value4", 4, "val2", "key1"),
+                    row("value5", 5, "val2", "key1"),
+                    row("value1", 1, "val1", "key2"),
+                    row("value2", 2, "val1", "key2"),
+                    row("value4", 4, "val2", "key2"),
+                    row("value5", 5, "val2", "key2"));
+ 
+         assertRows(execute(String.format("select * from %s.%s WHERE key = ? 
AND column1 = ?", KEYSPACE, currentDenseTable()), "key1", "val2"),
+                    row("key1", "val2", 4, "value4"),
+                    row("key1", "val2", 5, "value5"));
+ 
+         assertRows(execute(String.format("select * from %s.%s where key IN 
('key1', 'key2') and column1 = 'val1' and column2 = 2", KEYSPACE, 
currentDenseTable())),
+                    row("key1", "val1", 2, "value2"),
+                    row("key2", "val1", 2, "value2"));
+         assertRows(execute(String.format("select * from %s.%s where key IN 
('key1', 'key2') and column1 = 'val1' and column2 > 1", KEYSPACE, 
currentDenseTable())),
+                    row("key1", "val1", 2, "value2"),
+                    row("key2", "val1", 2, "value2"));
+         assertRows(execute(String.format("select * from %s.%s where key IN 
('key1', 'key2') and column1 = 'val1' and column2 >= 2", KEYSPACE, 
currentDenseTable())),
+                    row("key1", "val1", 2, "value2"),
+                    row("key2", "val1", 2, "value2"));
+         assertEmpty(execute(String.format("select * from %s.%s where key IN 
('key1', 'key2') and column1 = 'val1' and column2 > 2", KEYSPACE, 
currentDenseTable())));
+ 
+         assertRows(execute(String.format("select column2, key from %s.%s 
WHERE key = ? AND column1 = ? and column2 = 5", KEYSPACE, currentDenseTable()), 
"key1", "val2"),
+                    row(5, "key1"));
+         assertRows(execute(String.format("select * from %s.%s WHERE key = ? 
AND column1 = ? and column2 >= ?", KEYSPACE, currentDenseTable()), "key1", 
"val2", 5),
+                    row("key1", "val2", 5, "value5"));
+         assertRows(execute(String.format("select * from %s.%s WHERE key = ? 
AND column1 = ? and column2 > ?", KEYSPACE, currentDenseTable()), "key1", 
"val2", 4),
+                    row("key1", "val2", 5, "value5"));
+         assertRows(execute(String.format("select * from %s.%s WHERE key = ? 
AND column1 = ? and column2 < ?", KEYSPACE, currentDenseTable()), "key1", 
"val2", 5),
+                    row("key1", "val2", 4, "value4"));
+         assertRows(execute(String.format("select * from %s.%s WHERE key = ? 
AND column1 = ? and column2 <= ?", KEYSPACE, currentDenseTable()), "key1", 
"val2", 5),
+                    row("key1", "val2", 4, "value4"),
+                    row("key1", "val2", 5, "value5"));
+ 
+         assertRows(execute(String.format("select * from %s.%s where key = 
'key1' and column1 in ('val1', 'val2') and column2 IN (1, 4)", KEYSPACE, 
currentDenseTable())),
+                    row("key1", "val1", 1, "value1"),
+                    row("key1", "val2", 4, "value4"));
+ 
+         assertRows(execute(String.format("select * from %s.%s where key = 
'key1' and column1 in ('val1', 'val2')", KEYSPACE, currentDenseTable())),
+                    row("key1", "val1", 1, "value1"),
+                    row("key1", "val1", 2, "value2"),
+                    row("key1", "val2", 4, "value4"),
+                    row("key1", "val2", 5, "value5"));
+ 
+         assertRows(execute(String.format("select * from %s.%s where key = 
'key1' and column1 in ('val1', 'val2') and column2 = 1", KEYSPACE, 
currentDenseTable())),
+                    row("key1", "val1", 1, "value1"));
+ 
+         assertRows(execute(String.format("select * from %s.%s where key = 
'key1' and (column1, column2) = ('val2', 4)", KEYSPACE, currentDenseTable())),
+                    row("key1", "val2", 4, "value4"));
+ 
+         assertRows(execute(String.format("select * from %s.%s where key = 
'key1' and (column1, column2) >= ('val2', 4)", KEYSPACE, currentDenseTable())),
+                    row("key1", "val2", 4, "value4"),
+                    row("key1", "val2", 5, "value5"));
+ 
+         assertRows(execute(String.format("select * from %s.%s where key = 
'key1' and (column1, column2) > ('val1', 1)", KEYSPACE, currentDenseTable())),
+                    row("key1", "val1", 2, "value2"),
+                    row("key1", "val2", 4, "value4"),
+                    row("key1", "val2", 5, "value5"));
+ 
+         assertRows(execute(String.format("select * from %s.%s where key = 
'key1' and (column1, column2) > ('val2', 1)", KEYSPACE, currentDenseTable())),
+                    row("key1", "val2", 4, "value4"),
+                    row("key1", "val2", 5, "value5"));
+ 
+         resultSet = execute(String.format("select key as a, column1 as b, 
column2 as c, value as d " +
+                                           "from %s.%s WHERE key = ? AND 
column1 = ?", KEYSPACE, currentDenseTable()), "key1", "val2");
+         assertRows(resultSet,
+                    row("key1", "val2", 4, "value4"),
+                    row("key1", "val2", 5, "value5"));
+         assertEquals(resultSet.metadata().get(2).type, Int32Type.instance);
+         assertEquals(resultSet.metadata().get(3).type, AsciiType.instance);
+ 
+         assertRows(execute(String.format("select column2, value from %s.%s 
WHERE key = ? AND column1 = ?", KEYSPACE, currentDenseTable()), "key1", "val2"),
+                    row(4, "value4"),
+                    row(5, "value5"));
+ 
+         assertRows(execute(String.format("select column1, value from %s.%s 
WHERE key = ? AND column1 = ?", KEYSPACE, currentDenseTable()), "key2", "val1"),
+                    row("val1", "value1"),
+                    row("val1", "value2"));
+ 
+         assertInvalidMessage("Secondary indexes are not supported on COMPACT 
STORAGE tables that have clustering columns",
+                              String.format("CREATE INDEX ON %s.%s (column2)", 
KEYSPACE, currentDenseTable()));
+         assertInvalidMessage("Secondary indexes are not supported on COMPACT 
STORAGE tables that have clustering columns",
+                              String.format("CREATE INDEX ON %s.%s (value)", 
KEYSPACE, currentDenseTable()));
+ 
+         assertRows(execute(String.format("SELECT JSON * FROM %s.%s WHERE key 
= ? AND column1 = ?", KEYSPACE, currentDenseTable()), "key1", "val2"),
+                    row("{\"key\": \"key1\", \"column1\": \"val2\", 
\"column2\": 4, \"value\": \"value4\"}"),
+                    row("{\"key\": \"key1\", \"column1\": \"val2\", 
\"column2\": 5, \"value\": \"value5\"}"));
+     }
+ 
+     @Test
+     public void testDenseTablePartialCqlInserts() throws Throwable
+     {
+         assertInvalidMessage("Column value is mandatory for SuperColumn 
tables",
+                              String.format("INSERT INTO %s.%s (key, column1, 
column2) VALUES ('key1', 'val1', 1)", KEYSPACE, currentDenseTable()));
+ 
+         // That's slightly different from 2.X, since null map keys are not 
allowed
+         assertInvalidMessage("Column key is mandatory for SuperColumn tables",
+                              String.format("INSERT INTO %s.%s (key, column1, 
value) VALUES ('key1', 'val1', 'value1')", KEYSPACE, currentDenseTable()));
+ 
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key1', 'val1', 1, NULL)", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key1', 'val1', 1, ?)", KEYSPACE, currentDenseTable()), unset());
+         assertEmpty(execute(String.format("select * from %s.%s", KEYSPACE, 
currentDenseTable())));
+     }
+ 
+     @Test
+     public void testDenseTableCqlInserts() throws Throwable
+     {
+         Cassandra.Client client = getClient();
+ 
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES (?, ?, ?, ?)", KEYSPACE, currentDenseTable()),
+                 "key1", "val1", 1, "value1");
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES (?, ?, 2, ?)", KEYSPACE, currentDenseTable()),
+                 "key1", "val1", "value2");
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key1', 'val2', 4, 'value4')", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key1', 'val2', 5, 'value5')", KEYSPACE, currentDenseTable()));
+ 
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key2', 'val1', 1, 'value1')", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key2', 'val1', 2, 'value2')", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key2', 'val2', 4, 'value4')", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key2', 'val2', 5, 'value5')", KEYSPACE, currentDenseTable()));
+ 
+         ColumnPath path = new ColumnPath(currentDenseTable());
+         path.setSuper_column(ByteBufferUtil.bytes("val1"));
+ 
+         ColumnOrSuperColumn cosc = client.get(ByteBufferUtil.bytes("key1"), 
path, ONE);
+         assertEquals(cosc.getSuper_column().columns.get(0).name, 
ByteBufferUtil.bytes(1));
+         assertEquals(cosc.getSuper_column().columns.get(0).value, 
ByteBufferUtil.bytes("value1"));
+         assertEquals(cosc.getSuper_column().columns.get(1).name, 
ByteBufferUtil.bytes(2));
+         assertEquals(cosc.getSuper_column().columns.get(1).value, 
ByteBufferUtil.bytes("value2"));
+     }
+ 
+     @Test
+     public void testDenseTableCqlUpdates() throws Throwable
+     {
+         assertInvalidMessage("Column key is mandatory for SuperColumn tables",
+                              String.format("UPDATE %s.%s SET column2 = 1, 
value = 'value1' WHERE key = 'key1' AND column1 = 'val1'", KEYSPACE, 
currentDenseTable()));
+         assertInvalidMessage("Column `column2` of type `int` found in SET 
part",
+                              String.format("UPDATE %s.%s SET column2 = 1, 
value = 'value1' WHERE key = 'key1' AND column1 = 'val1' AND column2 = 1", 
KEYSPACE, currentDenseTable()));
+         assertInvalidMessage("Some clustering keys are missing: column1",
+                              String.format("UPDATE %s.%s SET value = 'value1' 
WHERE key = 'key1' AND column2 = 1", KEYSPACE, currentDenseTable()));
+ 
+         execute(String.format("UPDATE %s.%s SET value = 'value1' WHERE key = 
'key1' AND column1 = 'val1' AND column2 = 1", KEYSPACE, currentDenseTable()));
+         execute(String.format("UPDATE %s.%s SET value = 'value2' WHERE key = 
'key1' AND column1 = 'val1' AND column2 = 2", KEYSPACE, currentDenseTable()));
+ 
+         execute(String.format("UPDATE %s.%s SET value = ? WHERE key = ? AND 
column1 = ? AND column2 = ?", KEYSPACE, currentDenseTable()),
+                 "value1", "key2", "val2", 1);
+         execute(String.format("UPDATE %s.%s SET value = 'value2' WHERE key = 
'key2' AND column1 = ? AND column2 = ?", KEYSPACE, currentDenseTable()),
+                 "val2", 2);
+ 
+         Cassandra.Client client = getClient();
+         ColumnPath path = new ColumnPath(currentDenseTable());
+         path.setSuper_column(ByteBufferUtil.bytes("val1"));
+ 
+         ColumnOrSuperColumn cosc = client.get(ByteBufferUtil.bytes("key1"), 
path, ONE);
+         assertEquals(cosc.getSuper_column().columns.get(0).name, 
ByteBufferUtil.bytes(1));
+         assertEquals(cosc.getSuper_column().columns.get(0).value, 
ByteBufferUtil.bytes("value1"));
+         assertEquals(cosc.getSuper_column().columns.get(1).name, 
ByteBufferUtil.bytes(2));
+         assertEquals(cosc.getSuper_column().columns.get(1).value, 
ByteBufferUtil.bytes("value2"));
+ 
+         path = new ColumnPath(currentDenseTable());
+         path.setSuper_column(ByteBufferUtil.bytes("val2"));
+ 
+         cosc = client.get(ByteBufferUtil.bytes("key2"), path, ONE);
+         assertEquals(cosc.getSuper_column().columns.get(0).name, 
ByteBufferUtil.bytes(1));
+         assertEquals(cosc.getSuper_column().columns.get(0).value, 
ByteBufferUtil.bytes("value1"));
+         assertEquals(cosc.getSuper_column().columns.get(1).name, 
ByteBufferUtil.bytes(2));
+         assertEquals(cosc.getSuper_column().columns.get(1).value, 
ByteBufferUtil.bytes("value2"));
+     }
+ 
+ 
+     @Test
+     public void testDenseTableCqlDeletes() throws Throwable
+     {
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key1', 'val1', 1, 'value1')", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key1', 'val1', 2, 'value2')", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key1', 'val2', 4, 'value4')", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key1', 'val2', 5, 'value5')", KEYSPACE, currentDenseTable()));
+ 
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key2', 'val1', 1, 'value1')", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key2', 'val1', 2, 'value2')", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key2', 'val2', 4, 'value4')", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key2', 'val2', 5, 'value5')", KEYSPACE, currentDenseTable()));
+ 
+         execute(String.format("DELETE FROM %s.%s WHERE key = 'key1' AND 
column1 = 'val2' AND column2 = 5", KEYSPACE, currentDenseTable()));
+         assertRows(execute(String.format("SELECT * FROM %s.%s WHERE key = 
'key1'", KEYSPACE, currentDenseTable())),
+                    row("key1", "val1", 1, "value1"),
+                    row("key1", "val1", 2, "value2"),
+                    row("key1", "val2", 4, "value4"));
+         execute(String.format("DELETE FROM %s.%s WHERE key = 'key1' AND 
column1 = 'val2'", KEYSPACE, currentDenseTable()));
+         assertRows(execute(String.format("SELECT * FROM %s.%s WHERE key = 
'key1'", KEYSPACE, currentDenseTable())),
+                    row("key1", "val1", 1, "value1"),
+                    row("key1", "val1", 2, "value2"));
+         execute(String.format("DELETE FROM %s.%s WHERE key = 'key1'", 
KEYSPACE, currentDenseTable()));
+         assertEmpty(execute(String.format("SELECT * FROM %s.%s WHERE key = 
'key1'", KEYSPACE, currentDenseTable())));
+ 
+         Cassandra.Client client = getClient();
+ 
+         Mutation mutation1 = new Mutation();
+         SlicePredicate slicePredicate = new SlicePredicate();
+         slicePredicate.setSlice_range(new 
SliceRange(ByteBufferUtil.bytes("val1"), ByteBufferUtil.bytes("val1"), false, 
1));
+         Deletion deletion1 = new Deletion();
+         deletion1.setTimestamp(FBUtilities.timestampMicros());
+         deletion1.setPredicate(slicePredicate);
+         mutation1.setDeletion(deletion1);
+         
client.batch_mutate(Collections.singletonMap(ByteBufferUtil.bytes("key2"),
+                                                      
Collections.singletonMap(currentDenseTable(), Arrays.asList(mutation1))),
+                             ONE);
+         assertRows(execute(String.format("SELECT * FROM %s.%s WHERE key = 
'key2'", KEYSPACE, currentDenseTable())),
+                    row("key2", "val2", 4, "value4"),
+                    row("key2", "val2", 5, "value5"));
+ 
+         Mutation mutation2 = new Mutation();
+         Deletion deletion2 = new Deletion();
+         deletion2.setTimestamp(FBUtilities.timestampMicros());
+         deletion2.setSuper_column(ByteBufferUtil.bytes("val2"));
+         mutation2.setDeletion(deletion2);
+         
client.batch_mutate(Collections.singletonMap(ByteBufferUtil.bytes("key2"),
+                                                      
Collections.singletonMap(currentDenseTable(), Arrays.asList(mutation2))),
+                             ONE);
+ 
+         assertEmpty(execute(String.format("SELECT * FROM %s.%s WHERE key = 
'key2'", KEYSPACE, currentDenseTable())));
+ 
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key1', 'val1', 1, 'value1')", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key2', 'val1', 1, 'value1')", KEYSPACE, currentDenseTable()));
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES ('key3', 'val1', 1, 'value1')", KEYSPACE, currentDenseTable()));
+ 
+         execute(String.format("DELETE FROM %s.%s WHERE key IN ('key1', 
'key2')", KEYSPACE, currentDenseTable()));
+         assertRows(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentDenseTable())),
+                    row("key3", "val1", 1, "value1"));
+ 
+         assertInvalidMessage("Multi-column relations cannot be used in WHERE 
clauses for UPDATE and DELETE statements",
+                              String.format("DELETE FROM %s.%s WHERE key = 
'key3' AND (column1, column2) = ('val1', 1)", KEYSPACE, currentDenseTable()));
+ 
+         assertInvalidMessage("Token relations cannot be used in WHERE clauses 
for UPDATE and DELETE statements: token(key) > token('key3')",
+                              String.format("DELETE FROM %s.%s WHERE 
token(key) > token('key3')", KEYSPACE, currentDenseTable()));
+     }
+ 
+     @Test
+     public void testSparseTableAlter() throws Throwable
+     {
+         populateSparseTable();
+ 
+         alterTable(String.format("ALTER TABLE %s.%s RENAME column1 TO 
renamed_column1", KEYSPACE, currentSparseTable()));
+         alterTable(String.format("ALTER TABLE %s.%s RENAME key TO 
renamed_key", KEYSPACE, currentSparseTable()));
+         assertInvalidMessage("Cannot rename non PRIMARY KEY part col1",
+                              String.format("ALTER TABLE %s.%s RENAME col1 TO 
renamed_col1", KEYSPACE, currentSparseTable()));
+         assertInvalidMessage("Cannot rename non PRIMARY KEY part col2",
+                              String.format("ALTER TABLE %s.%s RENAME col2 TO 
renamed_col2", KEYSPACE, currentSparseTable()));
+         assertInvalidMessage("Cannot rename unknown column column2 in 
keyspace",
+                              String.format("ALTER TABLE %s.%s RENAME column2 
TO renamed_column2", KEYSPACE, currentSparseTable()));
+         assertInvalidMessage("Cannot rename unknown column value in keyspace",
+                              String.format("ALTER TABLE %s.%s RENAME value TO 
renamed_value", KEYSPACE, currentSparseTable()));
+ 
+ 
+         UntypedResultSet resultSet = execute(String.format("select * from 
%s.%s", KEYSPACE, currentSparseTable()));
+         assertEquals("renamed_key", 
resultSet.metadata().get(0).name.toString());
+         assertEquals("renamed_column1", 
resultSet.metadata().get(1).name.toString());
+         assertEquals("col1", resultSet.metadata().get(2).name.toString());
+         assertEquals("col2", resultSet.metadata().get(3).name.toString());
+ 
+         assertRows(resultSet,
+                    row("key1", "val1", 3L, 4L),
+                    row("key1", "val2", 3L, 4L),
+                    row("key2", "val1", 3L, 4L),
+                    row("key2", "val2", 3L, 4L));
+     }
+ 
+     @Test
+     public void testSparseTableCqlReads() throws Throwable
+     {
+         populateSparseTable();
+         beforeAndAfterFlush(this::testSparseTableCqlReadsInternal);
+     }
+ 
+     private void testSparseTableCqlReadsInternal() throws Throwable
+     {
+         UntypedResultSet resultSet = execute(String.format("select * from 
%s.%s", KEYSPACE, currentSparseTable()));
+         assertEquals("key", resultSet.metadata().get(0).name.toString());
+         assertEquals("column1", resultSet.metadata().get(1).name.toString());
+         assertEquals("col1", resultSet.metadata().get(2).name.toString());
+         assertEquals("col2", resultSet.metadata().get(3).name.toString());
+ 
+         assertRows(resultSet,
+                    row("key1", "val1", 3L, 4L),
+                    row("key1", "val2", 3L, 4L),
+                    row("key2", "val1", 3L, 4L),
+                    row("key2", "val2", 3L, 4L));
+ 
+         assertRows(execute(String.format("select col1, col2, column1, key 
from %s.%s", KEYSPACE, currentSparseTable())),
+                    row(3L, 4L, "val1", "key1"),
+                    row(3L, 4L, "val2", "key1"),
+                    row(3L, 4L, "val1", "key2"),
+                    row(3L, 4L, "val2", "key2"));
+ 
 -        assertInvalidMessage("Undefined name value in selection clause",
++        assertInvalidMessage("Undefined column name value",
+                              String.format("select value from %s.%s", 
KEYSPACE, currentSparseTable()));
+ 
+         assertRows(execute(String.format("select * from %s.%s WHERE key = ? 
AND column1 = ?", KEYSPACE, currentSparseTable()), "key1", "val2"),
+                    row("key1", "val2", 3L, 4L));
+ 
+         resultSet = execute(String.format("select col1 as a, col2 as b, 
column1 as c, key as d from %s.%s WHERE key = ? AND column1 = ?", KEYSPACE, 
currentSparseTable()), "key1", "val2");
+         assertRows(resultSet,
+                    row(3L, 4L, "val2", "key1"));
+         assertEquals(resultSet.metadata().get(0).name, 
ColumnIdentifier.getInterned("a", true));
+         assertEquals(resultSet.metadata().get(1).name, 
ColumnIdentifier.getInterned("b", true));
+         assertEquals(resultSet.metadata().get(2).name, 
ColumnIdentifier.getInterned("c", true));
+         assertEquals(resultSet.metadata().get(3).name, 
ColumnIdentifier.getInterned("d", true));
+ 
+         assertRows(execute(String.format("select col1, col2 from %s.%s WHERE 
key = ? AND column1 = ?", KEYSPACE, currentSparseTable()), "key1", "val2"),
+                    row(3L, 4L));
+ 
+         assertInvalidMessage("Secondary indexes are not supported on COMPACT 
STORAGE tables that have clustering columns",
+                              String.format("CREATE INDEX ON %s.%s (column1)", 
KEYSPACE, currentSparseTable()));
+         assertInvalidMessage("Secondary indexes are not supported on COMPACT 
STORAGE tables that have clustering columns",
+                              String.format("CREATE INDEX ON %s.%s (col1)", 
KEYSPACE, currentSparseTable()));
+ 
+         assertRows(execute(String.format("SELECT JSON * FROM %s.%s WHERE key 
= ? AND column1 = ?", KEYSPACE, currentSparseTable()), "key1", "val2"),
+                    row("{\"key\": \"key1\", \"column1\": \"val2\", \"col1\": 
3, \"col2\": 4}"));
+     }
+ 
+     @Test
+     public void testSparseTableCqlInserts() throws Throwable
+     {
+         execute(String.format("insert into %s.%s (key, column1, col1, col2) 
values ('key1', 'val1', 1, 2)", KEYSPACE, currentSparseTable()));
+         execute(String.format("insert into %s.%s (key, column1, col1, col2) 
values ('key1', 'val2', 3, 4)", KEYSPACE, currentSparseTable()));
+         execute(String.format("insert into %s.%s (key, column1, col1, col2) 
values ('key2', 'val1', 5, 6)", KEYSPACE, currentSparseTable()));
+         execute(String.format("insert into %s.%s (key, column1, col1, col2) 
values ('key2', 'val2', 7, 8)", KEYSPACE, currentSparseTable()));
+ 
+         assertRows(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentSparseTable())),
+                    row("key1", "val1", 1L, 2L),
+                    row("key1", "val2", 3L, 4L),
+                    row("key2", "val1", 5L, 6L),
+                    row("key2", "val2", 7L, 8L));
+ 
+         execute(String.format("truncate %s.%s", KEYSPACE, 
currentSparseTable()));
+ 
+         execute(String.format("insert into %s.%s (key, column1) values 
('key1', 'val1')", KEYSPACE, currentSparseTable()));
+         assertRows(execute(String.format("select * from %s.%s", KEYSPACE, 
currentSparseTable())));
+ 
+         execute(String.format("insert into %s.%s (key, column1, col1) values 
('key1', 'val1', 1)", KEYSPACE, currentSparseTable()));
+         execute(String.format("insert into %s.%s (key, column1, col2) values 
('key1', 'val1', 2)", KEYSPACE, currentSparseTable()));
+         assertRows(execute(String.format("select * from %s.%s", KEYSPACE, 
currentSparseTable())),
+                    row("key1", "val1", 1L, 2L));
+ 
+         Cassandra.Client client = getClient();
+         ColumnPath path = new ColumnPath(currentSparseTable());
+         path.setSuper_column(ByteBufferUtil.bytes("val1"));
+ 
+         ColumnOrSuperColumn cosc = client.get(ByteBufferUtil.bytes("key1"), 
path, ONE);
+         assertEquals(cosc.getSuper_column().columns.get(0).value, 
ByteBufferUtil.bytes(1L));
+         assertEquals(cosc.getSuper_column().columns.get(0).name, 
ByteBufferUtil.bytes("col1"));
+         assertEquals(cosc.getSuper_column().columns.get(1).value, 
ByteBufferUtil.bytes(2L));
+         assertEquals(cosc.getSuper_column().columns.get(1).name, 
ByteBufferUtil.bytes("col2"));
+     }
+ 
+     @Test
+     public void testSparseTableCqlUpdates() throws Throwable
+     {
+         execute(String.format("UPDATE %s.%s set col1 = 1, col2 = 2 WHERE key 
= 'key1' AND column1 = 'val1'", KEYSPACE, currentSparseTable()));
+         execute(String.format("UPDATE %s.%s set col1 = 3, col2 = 4 WHERE key 
= 'key1' AND column1 = 'val2'", KEYSPACE, currentSparseTable()));
+         execute(String.format("UPDATE %s.%s set col1 = 5, col2 = 6 WHERE key 
= 'key2' AND column1 = 'val1'", KEYSPACE, currentSparseTable()));
+         execute(String.format("UPDATE %s.%s set col1 = 7, col2 = 8 WHERE key 
= 'key2' AND column1 = 'val2'", KEYSPACE, currentSparseTable()));
+ 
+         assertRows(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentSparseTable())),
+                    row("key1", "val1", 1L, 2L),
+                    row("key1", "val2", 3L, 4L),
+                    row("key2", "val1", 5L, 6L),
+                    row("key2", "val2", 7L, 8L));
+ 
+         Cassandra.Client client = getClient();
+         ColumnPath path = new ColumnPath(currentSparseTable());
+         path.setSuper_column(ByteBufferUtil.bytes("val1"));
+ 
+         ColumnOrSuperColumn cosc = client.get(ByteBufferUtil.bytes("key1"), 
path, ONE);
+         assertEquals(cosc.getSuper_column().columns.get(0).value, 
ByteBufferUtil.bytes(1L));
+         assertEquals(cosc.getSuper_column().columns.get(0).name, 
ByteBufferUtil.bytes("col1"));
+         assertEquals(cosc.getSuper_column().columns.get(1).value, 
ByteBufferUtil.bytes(2L));
+         assertEquals(cosc.getSuper_column().columns.get(1).name, 
ByteBufferUtil.bytes("col2"));
+     }
+ 
+     @Test
+     public void testSparseTableCqlDeletes() throws Throwable
+     {
+         execute(String.format("insert into %s.%s (key, column1, col1, col2) 
values ('key1', 'val1', 1, 2)", KEYSPACE, currentSparseTable()));
+         execute(String.format("insert into %s.%s (key, column1, col1, col2) 
values ('key1', 'val2', 3, 4)", KEYSPACE, currentSparseTable()));
+         execute(String.format("insert into %s.%s (key, column1, col1, col2) 
values ('key2', 'val1', 5, 6)", KEYSPACE, currentSparseTable()));
+         execute(String.format("insert into %s.%s (key, column1, col1, col2) 
values ('key2', 'val2', 7, 8)", KEYSPACE, currentSparseTable()));
+ 
+         execute(String.format("DELETE col1 FROM %s.%s WHERE key = 'key1' AND 
column1 = 'val1'", KEYSPACE, currentSparseTable()));
+ 
+         assertRows(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentSparseTable())),
+                    row("key1", "val1", null, 2L),
+                    row("key1", "val2", 3L, 4L),
+                    row("key2", "val1", 5L, 6L),
+                    row("key2", "val2", 7L, 8L));
+ 
+         execute(String.format("DELETE FROM %s.%s WHERE key = 'key1' AND 
column1 = 'val2'", KEYSPACE, currentSparseTable()));
+ 
+         assertRows(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentSparseTable())),
+                    row("key1", "val1", null, 2L),
+                    row("key2", "val1", 5L, 6L),
+                    row("key2", "val2", 7L, 8L));
+ 
+         execute(String.format("DELETE FROM %s.%s WHERE key = 'key2'", 
KEYSPACE, currentSparseTable()));
+ 
+         assertRows(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentSparseTable())),
+                    row("key1", "val1", null, 2L));
+     }
+ 
+     @Test
+     public void testInsertJson() throws Throwable
+     {
+         execute(String.format("INSERT INTO %s.%s JSON ?", KEYSPACE, 
currentDenseTable()),
+                 "{\"key\": \"key5\", \"column1\": \"val2\", \"column2\": 4, 
\"value\": \"value4\"}");
+         assertRows(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentDenseTable())),
+                    row("key5", "val2", 4, "value4"));
+ 
+         execute(String.format("INSERT INTO %s.%s JSON ?", KEYSPACE, 
currentSparseTable()),
+                 "{\"key\": \"key1\", \"column1\": \"val1\", \"col1\": 1, 
\"col2\": 2}");
+         assertRows(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentSparseTable())),
+                    row("key1", "val1", 1L, 2L));
+     }
+ 
+     @Test
+     public void testFiltering() throws Throwable
+     {
+         assertInvalidMessage("Filtering is not supported on SuperColumn 
tables",
+                              String.format("select * from %s.%s WHERE value = 
?", KEYSPACE, currentDenseTable()),
+                              "value5");
+         assertInvalidMessage("Filtering is not supported on SuperColumn 
tables",
+                              String.format("select * from %s.%s WHERE value = 
? ALLOW FILTERING", KEYSPACE, currentDenseTable()),
+                              "value5");
+         assertInvalidMessage("Filtering is not supported on SuperColumn 
tables",
+                              String.format("SELECT * FROM %s.%s WHERE value = 
'value2' ALLOW FILTERING", KEYSPACE, currentDenseTable()));
+         assertInvalidMessage("Filtering is not supported on SuperColumn 
tables",
+                              String.format("SELECT * FROM %s.%s WHERE column2 
= 1 ALLOW FILTERING", KEYSPACE, currentDenseTable()));
+     }
+ 
+     @Test
+     public void testLwt() throws Throwable
+     {
+         assertRows(execute(String.format("INSERT INTO %s.%s (key, column1, 
column2, value) VALUES (?, ?, ?, ?) IF NOT EXISTS", KEYSPACE, 
currentDenseTable()),
+                            "key1", "val1", 1, "value1"),
+                    row(true));
+         assertRows(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentDenseTable())),
+                    row("key1", "val1", 1, "value1"));
+         assertRows(execute(String.format("INSERT INTO %s.%s (key, column1, 
column2, value) VALUES (?, ?, ?, ?) IF NOT EXISTS", KEYSPACE, 
currentDenseTable()),
+                            "key1", "val1", 1, "value1"),
+                    row(false, "key1", "val1", 1, "value1"));
+ 
+         // in 2.2 this query was a no-op
+         assertInvalidMessage("Lightweight transactions on SuperColumn tables 
are only supported with supplied SuperColumn key",
+                              String.format("UPDATE %s.%s SET value = 
'changed' WHERE key = ? AND column1 = ? IF value = ?", KEYSPACE, 
currentDenseTable()));
+ 
+         assertRows(execute(String.format("UPDATE %s.%s SET value = 'changed' 
WHERE key = ? AND column1 = ? AND column2 = ? IF value = ?", KEYSPACE, 
currentDenseTable()),
+                            "key1", "val1", 1, "value1"),
+                    row(true));
+         assertRows(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentDenseTable())),
+                    row("key1", "val1", 1, "changed"));
+         assertRows(execute(String.format("UPDATE %s.%s SET value = 'changed' 
WHERE key = ? AND column1 = ? AND column2 = ? IF value = ?", KEYSPACE, 
currentDenseTable()),
+                            "key1", "val1", 1, "value1"),
+                    row(false, "changed"));
+ 
+         assertRows(execute(String.format("UPDATE %s.%s SET value = 'changed2' 
WHERE key = ? AND column1 = ? AND column2 = ? IF value > ?", KEYSPACE, 
currentDenseTable()),
+                            "key1", "val1", 1, "a"),
+                    row(true));
+         assertRows(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentDenseTable())),
+                    row("key1", "val1", 1, "changed2"));
+         assertRows(execute(String.format("UPDATE %s.%s SET value = 'changed2' 
WHERE key = ? AND column1 = ? AND column2 = ? IF value < ?", KEYSPACE, 
currentDenseTable()),
+                            "key1", "val1", 1, "a"),
+                    row(false, "changed2"));
+ 
+         assertInvalidMessage("PRIMARY KEY column 'column2' cannot have IF 
conditions",
+                              String.format("UPDATE %s.%s SET value = 
'changed2' WHERE key = ? AND column1 = ? AND column2 = ? IF value > ? AND 
column2 = ?", KEYSPACE, currentDenseTable()));
+ 
+         assertInvalidMessage("Lightweight transactions on SuperColumn tables 
are only supported with supplied SuperColumn key",
+                              String.format("UPDATE %s.%s SET value = 
'changed2' WHERE key = ? AND column1 = ? IF value > ?", KEYSPACE, 
currentDenseTable()));
+ 
+         execute(String.format("DELETE FROM %s.%s WHERE key = 'key1' AND 
column1 = 'val1' AND column2 = 1 IF EXISTS", KEYSPACE, currentDenseTable()));
+         assertEmpty(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentDenseTable())));
+ 
+         execute(String.format("INSERT INTO %s.%s (key, column1, column2, 
value) VALUES (?, ?, ?, ?)", KEYSPACE, currentDenseTable()),
+                 "key1", "val1", 1, "value1");
+ 
+         assertRows(execute(String.format("DELETE FROM %s.%s WHERE key = 
'key1' AND column1 = 'val1' AND column2 = 1 IF value = 'value1'", KEYSPACE, 
currentDenseTable())),
+                    row(true));
+         assertEmpty(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentDenseTable())));
+ 
+         assertRows(execute(String.format("DELETE FROM %s.%s WHERE key = 
'key1' AND column1 = 'val1' AND column2 = 1 IF value = 'value1'", KEYSPACE, 
currentDenseTable())),
+                    row(false));
+         assertEmpty(execute(String.format("SELECT * FROM %s.%s", KEYSPACE, 
currentDenseTable())));
+     }
+ 
+     @Test
+     public void testCqlAggregateFunctions() throws Throwable
+     {
+         populateDenseTable();
+         populateSparseTable();
+ 
+         assertRows(execute(String.format("select count(*) from %s.%s", 
KEYSPACE, currentDenseTable())),
+                    row(8L));
+         assertRows(execute(String.format("select count(*) from %s.%s", 
KEYSPACE, currentSparseTable())),
+                    row(4L));
+ 
+         assertRows(execute(String.format("select count(*) from %s.%s where 
key = ? AND column1 = ?", KEYSPACE, currentDenseTable()), "key1", "val1"),
+                    row(2L));
+         assertRows(execute(String.format("select count(*) from %s.%s where 
key = ? AND column1 = ?", KEYSPACE, currentSparseTable()), "key1", "val1"),
+                    row(1L));
+         assertRows(execute(String.format("select count(*) from %s.%s where 
key = ?", KEYSPACE, currentSparseTable()), "key1"),
+                    row(2L));
+ 
+         assertRows(execute(String.format("select max(value) from %s.%s", 
KEYSPACE, currentDenseTable())),
+                    row("value5"));
+         assertRows(execute(String.format("select max(col1) from %s.%s", 
KEYSPACE, currentSparseTable())),
+                    row(3L));
+ 
+         assertRows(execute(String.format("select avg(column2) from %s.%s", 
KEYSPACE, currentDenseTable())),
+                    row(3));
+         assertRows(execute(String.format("select avg(col1) from %s.%s", 
KEYSPACE, currentSparseTable())),
+                    row(3L));
+     }
+ 
+     private void populateDenseTable() throws Throwable
+     {
+         Cassandra.Client client = getClient();
+ 
+         Mutation mutation = new Mutation();
+         ColumnOrSuperColumn csoc = new ColumnOrSuperColumn();
+         
csoc.setSuper_column(getSuperColumnForInsert(ByteBufferUtil.bytes("val1"),
+                                                      
Arrays.asList(getColumnForInsert(ByteBufferUtil.bytes(1), 
ByteBufferUtil.bytes("value1")),
+                                                                    
getColumnForInsert(ByteBufferUtil.bytes(2), ByteBufferUtil.bytes("value2")))));
+         mutation.setColumn_or_supercolumn(csoc);
+ 
+         Mutation mutation2 = new Mutation();
+         ColumnOrSuperColumn csoc2 = new ColumnOrSuperColumn();
+         
csoc2.setSuper_column(getSuperColumnForInsert(ByteBufferUtil.bytes("val2"),
+                                                       
Arrays.asList(getColumnForInsert(ByteBufferUtil.bytes(4), 
ByteBufferUtil.bytes("value4")),
+                                                                     
getColumnForInsert(ByteBufferUtil.bytes(5), ByteBufferUtil.bytes("value5")))));
+         mutation2.setColumn_or_supercolumn(csoc2);
+ 
+         
client.batch_mutate(Collections.singletonMap(ByteBufferUtil.bytes("key1"),
+                                                      
Collections.singletonMap(currentDenseTable(), Arrays.asList(mutation, 
mutation2))),
+                             ONE);
+ 
+         
client.batch_mutate(Collections.singletonMap(ByteBufferUtil.bytes("key2"),
+                                                      
Collections.singletonMap(currentDenseTable(), Arrays.asList(mutation, 
mutation2))),
+                             ONE);
+     }
+ 
+     private void populateSparseTable() throws Throwable
+     {
+         Cassandra.Client client = getClient();
+ 
+         Mutation mutation = new Mutation();
+         ColumnOrSuperColumn csoc = new ColumnOrSuperColumn();
+         
csoc.setSuper_column(getSuperColumnForInsert(ByteBufferUtil.bytes("val1"),
+                                                      
Arrays.asList(getColumnForInsert(ByteBufferUtil.bytes("value1"), 
ByteBufferUtil.bytes(1L)),
+                                                                    
getColumnForInsert(ByteBufferUtil.bytes("value2"), ByteBufferUtil.bytes(2L)),
+                                                                    
getColumnForInsert(ByteBufferUtil.bytes("col1"), ByteBufferUtil.bytes(3L)),
+                                                                    
getColumnForInsert(ByteBufferUtil.bytes("col2"), ByteBufferUtil.bytes(4L)))));
+         mutation.setColumn_or_supercolumn(csoc);
+ 
+         Mutation mutation2 = new Mutation();
+         ColumnOrSuperColumn csoc2 = new ColumnOrSuperColumn();
+         
csoc2.setSuper_column(getSuperColumnForInsert(ByteBufferUtil.bytes("val2"),
+                                                       
Arrays.asList(getColumnForInsert(ByteBufferUtil.bytes("value1"), 
ByteBufferUtil.bytes(1L)),
+                                                                     
getColumnForInsert(ByteBufferUtil.bytes("value2"), ByteBufferUtil.bytes(2L)),
+                                                                     
getColumnForInsert(ByteBufferUtil.bytes("col1"), ByteBufferUtil.bytes(3L)),
+                                                                     
getColumnForInsert(ByteBufferUtil.bytes("col2"), ByteBufferUtil.bytes(4L)))));
+         mutation2.setColumn_or_supercolumn(csoc2);
+ 
+         
client.batch_mutate(Collections.singletonMap(ByteBufferUtil.bytes("key1"),
+                                                      
Collections.singletonMap(currentSparseTable(), Arrays.asList(mutation, 
mutation2))),
+                             ONE);
+ 
+         
client.batch_mutate(Collections.singletonMap(ByteBufferUtil.bytes("key2"),
+                                                      
Collections.singletonMap(currentSparseTable(), Arrays.asList(mutation, 
mutation2))),
+                             ONE);
+     }
+ 
+     private void populateCounterTable() throws Throwable
+     {
+         Cassandra.Client client = getClient();
+ 
+         ColumnParent cp = new ColumnParent(currentCounterTable());
+         cp.setSuper_column(ByteBufferUtil.bytes("ck1"));
+         client.add(ByteBufferUtil.bytes("key1"),
+                    cp,
+                    new CounterColumn(ByteBufferUtil.bytes("counter1"), 10L),
+                    ONE);
+         cp = new ColumnParent(currentCounterTable());
+         cp.setSuper_column(ByteBufferUtil.bytes("ck1"));
+         client.add(ByteBufferUtil.bytes("key1"),
+                    cp,
+                    new CounterColumn(ByteBufferUtil.bytes("counter2"), 5L),
+                    ONE);
+         cp = new ColumnParent(currentCounterTable());
+         cp.setSuper_column(ByteBufferUtil.bytes("ck1"));
+         client.add(ByteBufferUtil.bytes("key2"),
+                    cp,
+                    new CounterColumn(ByteBufferUtil.bytes("counter1"), 10L),
+                    ONE);
+         cp = new ColumnParent(currentCounterTable());
+         cp.setSuper_column(ByteBufferUtil.bytes("ck1"));
+         client.add(ByteBufferUtil.bytes("key2"),
+                    cp,
+                    new CounterColumn(ByteBufferUtil.bytes("counter2"), 5L),
+                    ONE);
+     }
+ 
+     private String currentCounterTable()
+     {
+         return currentTable() + "_counter";
+     }
+ 
+     private String currentSparseTable()
+     {
+         return currentTable() + "_sparse";
+     }
+ 
+     private String currentDenseTable()
+     {
+         return currentTable();
+     }
+ 
+     private Column getColumnForInsert(ByteBuffer columnName, ByteBuffer value)
+     {
+         Column column = new Column();
+         column.setName(columnName);
+         column.setValue(value);
+         column.setTimestamp(System.currentTimeMillis());
+         return column;
+     }
+ 
+     private SuperColumn getSuperColumnForInsert(ByteBuffer columnName, 
List<Column> columns)
+     {
+         SuperColumn column = new SuperColumn();
+         column.setName(columnName);
+         for (Column c : columns)
+             column.addToColumns(c);
+         return column;
+     }
+ 
+     public void beforeAndAfterFlush(CheckedFunction runnable) throws Throwable
+     {
+         runnable.apply();
+         flushAll();
+         runnable.apply();
+     }
+ 
+     private void flushAll()
+     {
+         for (String cfName : new String[]{ currentTable(), 
currentSparseTable(), currentCounterTable() })
+             Keyspace.open(KEYSPACE).getColumnFamilyStore(cfName);
+     }
+ }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/test/unit/org/apache/cassandra/db/ColumnFamilyStoreCQLHelperTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4734ce7d/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java
----------------------------------------------------------------------


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to