cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ifesdj...@apache.org
Subject [4/8] cassandra git commit: Fix support for SuperColumn tables
Date Mon, 25 Sep 2017 07:42:47 GMT
http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/cql3/restrictions/SingleColumnRestriction.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/SingleColumnRestriction.java b/src/java/org/apache/cassandra/cql3/restrictions/SingleColumnRestriction.java
index 6296b97..5985962 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/SingleColumnRestriction.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/SingleColumnRestriction.java
@@ -118,9 +118,9 @@ public abstract class SingleColumnRestriction extends AbstractRestriction
      */
     protected abstract boolean isSupportedBy(Index index);
 
-    public static final class EQRestriction extends SingleColumnRestriction
+    public static class EQRestriction extends SingleColumnRestriction
     {
-        private final Term value;
+        public final Term value;
 
         public EQRestriction(ColumnDefinition columnDef, Term value)
         {
@@ -308,7 +308,7 @@ public abstract class SingleColumnRestriction extends AbstractRestriction
 
     public static class SliceRestriction extends SingleColumnRestriction
     {
-        private final TermSlice slice;
+        public final TermSlice slice;
 
         public SliceRestriction(ColumnDefinition columnDef, Bound bound, boolean inclusive, Term term)
         {
@@ -404,7 +404,7 @@ public abstract class SingleColumnRestriction extends AbstractRestriction
             return String.format("SLICE%s", slice);
         }
 
-        private SliceRestriction(ColumnDefinition columnDef, TermSlice slice)
+        SliceRestriction(ColumnDefinition columnDef, TermSlice slice)
         {
             super(columnDef);
             this.slice = slice;
@@ -646,4 +646,202 @@ public abstract class SingleColumnRestriction extends AbstractRestriction
             return index.supportsExpression(columnDef, Operator.IS_NOT);
         }
     }
+
+    /**
+     * Super Column Compatibiltiy
+     */
+
+    public static class SuperColumnMultiEQRestriction extends EQRestriction
+    {
+        public ByteBuffer firstValue;
+        public ByteBuffer secondValue;
+
+        public SuperColumnMultiEQRestriction(ColumnDefinition columnDef, Term value)
+        {
+            super(columnDef, value);
+        }
+
+        @Override
+        public MultiCBuilder appendTo(MultiCBuilder builder, QueryOptions options)
+        {
+            Term term = value.bind(options);
+
+            assert (term instanceof Tuples.Value);
+            firstValue = ((Tuples.Value)term).getElements().get(0);
+            secondValue = ((Tuples.Value)term).getElements().get(1);
+
+            builder.addElementToAll(firstValue);
+            checkFalse(builder.containsNull(), "Invalid null value in condition for column %s", columnDef.name);
+            checkFalse(builder.containsUnset(), "Invalid unset value for column %s", columnDef.name);
+            return builder;
+        }
+    }
+
+    public static class SuperColumnMultiSliceRestriction extends SliceRestriction
+    {
+        public ByteBuffer firstValue;
+        public ByteBuffer secondValue;
+
+        // These are here to avoid polluting SliceRestriction
+        public final Bound bound;
+        public final boolean trueInclusive;
+        public SuperColumnMultiSliceRestriction(ColumnDefinition columnDef, Bound bound, boolean inclusive, Term term)
+        {
+            super(columnDef, bound, true, term);
+            this.bound = bound;
+            this.trueInclusive = inclusive;
+
+        }
+
+        @Override
+        public MultiCBuilder appendBoundTo(MultiCBuilder builder, Bound bound, QueryOptions options)
+        {
+            Bound b = reverseBoundIfNeeded(getFirstColumn(), bound);
+
+            if (!hasBound(b))
+                return builder;
+
+            Term term = slice.bound(b);
+
+            assert (term instanceof Tuples.Value);
+            firstValue = ((Tuples.Value)term).getElements().get(0);
+            secondValue = ((Tuples.Value)term).getElements().get(1);
+
+            checkBindValueSet(firstValue, "Invalid unset value for column %s", columnDef.name);
+            checkBindValueSet(secondValue, "Invalid unset value for column %s", columnDef.name);
+            return builder.addElementToAll(firstValue);
+
+        }
+    }
+
+    public static final class SuperColumnKeyEQRestriction extends EQRestriction
+    {
+        public SuperColumnKeyEQRestriction(ColumnDefinition columnDef, Term value)
+        {
+            super(columnDef, value);
+        }
+
+        public ByteBuffer bindValue(QueryOptions options)
+        {
+            return value.bindAndGet(options);
+        }
+
+        @Override
+        public MultiCBuilder appendBoundTo(MultiCBuilder builder, Bound bound, QueryOptions options)
+        {
+            // no-op
+            return builder;
+        }
+
+        @Override
+        public void addRowFilterTo(RowFilter filter, SecondaryIndexManager indexManager, QueryOptions options) throws InvalidRequestException
+        {
+            // no-op
+        }
+    }
+
+    public static abstract class SuperColumnKeyINRestriction extends INRestriction
+    {
+        public SuperColumnKeyINRestriction(ColumnDefinition columnDef)
+        {
+            super(columnDef);
+        }
+
+        @Override
+        public MultiCBuilder appendTo(MultiCBuilder builder, QueryOptions options)
+        {
+            // no-op
+            return builder;
+        }
+
+        @Override
+        public void addRowFilterTo(RowFilter filter,
+                                   SecondaryIndexManager indexManager,
+                                   QueryOptions options) throws InvalidRequestException
+        {
+            // no-op
+        }
+
+        public void addFunctionsTo(List<Function> functions)
+        {
+            // no-op
+        }
+
+        MultiColumnRestriction toMultiColumnRestriction()
+        {
+            // no-op
+            return null;
+        }
+
+        public abstract List<ByteBuffer> getValues(QueryOptions options) throws InvalidRequestException;
+    }
+
+    public static class SuperColumnKeyINRestrictionWithMarkers extends SuperColumnKeyINRestriction
+    {
+        protected final AbstractMarker marker;
+
+        public SuperColumnKeyINRestrictionWithMarkers(ColumnDefinition columnDef, AbstractMarker marker)
+        {
+            super(columnDef);
+            this.marker = marker;
+        }
+
+        public List<ByteBuffer> getValues(QueryOptions options) throws InvalidRequestException
+        {
+            Terminal term = marker.bind(options);
+            checkNotNull(term, "Invalid null value for column %s", columnDef.name);
+            checkFalse(term == Constants.UNSET_VALUE, "Invalid unset value for column %s", columnDef.name);
+            Term.MultiItemTerminal lval = (Term.MultiItemTerminal) term;
+            return lval.getElements();
+        }
+    }
+
+    public static class SuperColumnKeyINRestrictionWithValues extends SuperColumnKeyINRestriction
+    {
+        private final List<Term> values;
+
+        public SuperColumnKeyINRestrictionWithValues(ColumnDefinition columnDef, List<Term> values)
+        {
+            super(columnDef);
+            this.values = values;
+        }
+
+        public List<ByteBuffer> getValues(QueryOptions options) throws InvalidRequestException
+        {
+            List<ByteBuffer> buffers = new ArrayList<>(values.size());
+            for (Term value : values)
+                buffers.add(value.bindAndGet(options));
+            return buffers;
+        }
+    }
+
+    public static class SuperColumnKeySliceRestriction extends SliceRestriction
+    {
+        // These are here to avoid polluting SliceRestriction
+        private Term term;
+
+        public SuperColumnKeySliceRestriction(ColumnDefinition columnDef, Bound bound, boolean inclusive, Term term)
+        {
+            super(columnDef, bound, inclusive, term);
+            this.term = term;
+        }
+
+        public ByteBuffer bindValue(QueryOptions options)
+        {
+            return term.bindAndGet(options);
+        }
+
+        @Override
+        public MultiCBuilder appendBoundTo(MultiCBuilder builder, Bound bound, QueryOptions options)
+        {
+            // no-op
+            return builder;
+        }
+
+        @Override
+        public void addRowFilterTo(RowFilter filter, SecondaryIndexManager indexManager, QueryOptions options) throws InvalidRequestException
+        {
+            // no-op
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
index d025d8a..84c6958 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
@@ -21,6 +21,7 @@ import java.nio.ByteBuffer;
 import java.util.*;
 
 import com.google.common.base.Joiner;
+import com.google.common.collect.Iterators;
 
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.config.ColumnDefinition;
@@ -160,7 +161,10 @@ public final class StatementRestrictions
             }
             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));
             }
         }
 
@@ -233,9 +237,16 @@ public final class StatementRestrictions
                                      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);
         }
@@ -847,4 +858,15 @@ public final class StatementRestrictions
                && (clusteringColumnsRestrictions.isEQ() || clusteringColumnsRestrictions.isIN());
     }
 
+
+    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(),
+                                                                                           nonPrimaryKeyRestrictions.iterator()));
+        return cached;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/cql3/restrictions/TermSlice.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/restrictions/TermSlice.java b/src/java/org/apache/cassandra/cql3/restrictions/TermSlice.java
index ac66b96..4b13877 100644
--- a/src/java/org/apache/cassandra/cql3/restrictions/TermSlice.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/TermSlice.java
@@ -26,7 +26,7 @@ import org.apache.cassandra.cql3.functions.Function;
 import org.apache.cassandra.cql3.statements.Bound;
 import org.apache.cassandra.index.Index;
 
-final class TermSlice
+public final class TermSlice
 {
     /**
      * The slice boundaries.

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/cql3/statements/CreateViewStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateViewStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateViewStatement.java
index 708d551..47304b6 100644
--- a/src/java/org/apache/cassandra/cql3/statements/CreateViewStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateViewStatement.java
@@ -137,6 +137,8 @@ public class CreateViewStatement extends SchemaAlteringStatement
 
         if (cfm.isCounter())
             throw new InvalidRequestException("Materialized views are not supported on counter tables");
+        if (cfm.isSuper())
+            throw new InvalidRequestException("Materialized views are not supported on SuperColumn tables");
         if (cfm.isView())
             throw new InvalidRequestException("Materialized views cannot be created against other materialized views");
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
index 4888b43..a0919d7 100644
--- a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
@@ -116,7 +116,7 @@ public class DeleteStatement extends ModificationStatement
     public static class Parsed extends ModificationStatement.Parsed
     {
         private final List<Operation.RawDeletion> deletions;
-        private final WhereClause whereClause;
+        private WhereClause whereClause;
 
         public Parsed(CFName name,
                       Attributes.Raw attrs,
@@ -139,17 +139,25 @@ public class DeleteStatement extends ModificationStatement
         {
             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);
-                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);
+                    op.collectMarkerSpecification(boundNames);
+                    operations.add(op);
+                }
             }
 
             StatementRestrictions restrictions = newRestrictions(cfm,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
index 0afd34d..28fc90f 100644
--- a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
@@ -544,10 +544,19 @@ public abstract class ModificationStatement implements CQLStatement
                 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);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
index 3882a23..2e090fa 100644
--- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
@@ -18,7 +18,16 @@
 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;
@@ -29,13 +38,40 @@ import org.slf4j.LoggerFactory;
 import org.apache.cassandra.auth.Permission;
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.config.ColumnDefinition;
-import org.apache.cassandra.cql3.*;
+import org.apache.cassandra.cql3.CFName;
+import org.apache.cassandra.cql3.CQLStatement;
+import org.apache.cassandra.cql3.ColumnIdentifier;
+import org.apache.cassandra.cql3.ColumnSpecification;
+import org.apache.cassandra.cql3.QueryOptions;
+import org.apache.cassandra.cql3.QueryProcessor;
+import org.apache.cassandra.cql3.ResultSet;
+import org.apache.cassandra.cql3.SuperColumnCompatibility;
+import org.apache.cassandra.cql3.Term;
+import org.apache.cassandra.cql3.VariableSpecifications;
+import org.apache.cassandra.cql3.WhereClause;
 import org.apache.cassandra.cql3.functions.Function;
 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.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;
@@ -45,7 +81,11 @@ 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;
@@ -479,7 +519,8 @@ public class SelectStatement implements CQLStatement
         {
             QueryProcessor.validateKey(key);
             DecoratedKey dk = cfm.decorateKey(ByteBufferUtil.clone(key));
-            commands.add(SinglePartitionReadCommand.create(cfm, nowInSec, queriedColumns, rowFilter, limit, dk, filter));
+            ColumnFilter cf = (cfm.isSuper() && cfm.isDense()) ? SuperColumnCompatibility.getColumnFilter(cfm, options, restrictions.getSuperColumnRestrictions()) : queriedColumns;
+            commands.add(SinglePartitionReadCommand.create(cfm, nowInSec, cf, rowFilter, limit, dk, filter));
         }
 
         return new SinglePartitionReadCommand.Group(commands, limit);
@@ -730,6 +771,12 @@ public class SelectStatement implements CQLStatement
     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();
 
         ByteBuffer[] keyComponents = getComponents(cfm, partition.partitionKey());

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java b/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
index 6f872d4..641b6bb 100644
--- a/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
@@ -17,7 +17,6 @@
  */
 package org.apache.cassandra.cql3.statements;
 
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -32,6 +31,7 @@ import org.apache.cassandra.db.partitions.PartitionUpdate;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.Pair;
 
+import static com.google.common.collect.Lists.newArrayList;
 import static org.apache.cassandra.cql3.statements.RequestValidations.checkContainsNoDuplicates;
 import static org.apache.cassandra.cql3.statements.RequestValidations.checkFalse;
 import static org.apache.cassandra.cql3.statements.RequestValidations.checkTrue;
@@ -81,7 +81,7 @@ public class UpdateStatement extends ModificationStatement
             // For a dense layout, when we translate it to thrift, we don't have a row marker. So we don't accept an insert/update
             // that only sets the PK unless the is no declared non-PK columns (which we recognize because in that case the compact
             // value is of type "EmptyType").
-            if (cfm.isCompactTable() && updates.isEmpty())
+            if ((cfm.isCompactTable() && !cfm.isSuper()) && updates.isEmpty())
             {
                 checkTrue(CompactTables.hasEmptyCompactValue(cfm),
                           "Column %s is mandatory for this COMPACT STORAGE table",
@@ -155,24 +155,33 @@ public class UpdateStatement extends ModificationStatement
             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(keyspace(), 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.collectMarkerSpecification(boundNames);
+                        operations.add(operation);
+                    }
                 }
             }
 
@@ -218,30 +227,36 @@ public class UpdateStatement extends ModificationStatement
         {
             checkFalse(cfm.isCounter(), "INSERT statements are not allowed on counter tables, use UPDATE instead");
 
-            Collection<ColumnDefinition> defs = cfm.allColumns();
+            List<ColumnDefinition> defs = newArrayList(cfm.allColumnsInSelectOrder());
             Json.Prepared prepared = jsonValue.prepareAndCollectMarkers(cfm, defs, boundNames);
 
             WhereClause.Builder whereClause = new WhereClause.Builder();
             Operations operations = new Operations(type);
             boolean hasClusteringColumnsSet = false;
 
-            for (ColumnDefinition def : defs)
+            if (cfm.isSuper() && cfm.isDense())
             {
-                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
+                hasClusteringColumnsSet = true;
+                SuperColumnCompatibility.prepareInsertJSONOperations(cfm, defs, boundNames, prepared, whereClause, operations);
+            }
+            else
+            {
+                for (ColumnDefinition def : defs)
                 {
-                    Operation operation = new Operation.SetValue(raw).prepare(keyspace(), def);
-                    operation.collectMarkerSpecification(boundNames);
-                    operations.add(operation);
+                    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);
+                    }
                 }
             }
 
@@ -270,7 +285,7 @@ public class UpdateStatement extends ModificationStatement
     {
         // Provided for an UPDATE
         private final List<Pair<ColumnIdentifier.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 @@ public class UpdateStatement extends ModificationStatement
         {
             Operations operations = new Operations(type);
 
-            for (Pair<ColumnIdentifier.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)
+                {
+                    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(keyspace(), def);
-                operation.collectMarkerSpecification(boundNames);
-                operations.add(operation);
+                    Operation operation = entry.right.prepare(cfm.ksName, def);
+                    operation.collectMarkerSpecification(boundNames);
+                    operations.add(operation);
+                }
             }
-
+            
             StatementRestrictions restrictions = newRestrictions(cfm,
                                                                  boundNames,
                                                                  operations,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/db/Columns.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/Columns.java b/src/java/org/apache/cassandra/db/Columns.java
index cad295c..eb4f761 100644
--- a/src/java/org/apache/cassandra/db/Columns.java
+++ b/src/java/org/apache/cassandra/db/Columns.java
@@ -422,6 +422,7 @@ public class Columns extends AbstractCollection<ColumnDefinition> implements Col
             {
                 ByteBuffer name = ByteBufferUtil.readWithVIntLength(in);
                 ColumnDefinition column = metadata.getColumnDefinition(name);
+
                 if (column == null)
                 {
                     // If we don't find the definition, it could be we have data for a dropped column, and we shouldn't

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/db/CompactTables.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/CompactTables.java b/src/java/org/apache/cassandra/db/CompactTables.java
index e31fda3..9da4d94 100644
--- a/src/java/org/apache/cassandra/db/CompactTables.java
+++ b/src/java/org/apache/cassandra/db/CompactTables.java
@@ -17,13 +17,15 @@
  */
 package org.apache.cassandra.db;
 
-import java.nio.ByteBuffer;
-import java.util.*;
+import java.util.HashSet;
+import java.util.Set;
 
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.config.ColumnDefinition;
-import org.apache.cassandra.db.marshal.*;
-import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.cql3.SuperColumnCompatibility;
+import org.apache.cassandra.db.marshal.AbstractType;
+import org.apache.cassandra.db.marshal.EmptyType;
+import org.apache.cassandra.db.marshal.UTF8Type;
 
 /**
  * Small utility methods pertaining to the encoding of COMPACT STORAGE tables.
@@ -54,39 +56,14 @@ import org.apache.cassandra.utils.ByteBufferUtil;
  * On variation is that if the table comparator is a CompositeType, then the underlying table will have one clustering column by
  * element of the CompositeType, but the rest of the layout is as above.
  *
- * As far as thrift is concerned, one exception to this is super column families, which have a different layout. Namely, a super
- * column families is encoded with:
- *   CREATE TABLE super (
- *      key [key_validation_class],
- *      super_column_name [comparator],
- *      [column_metadata_1] [type1],
- *      ...,
- *      [column_metadata_n] [type1],
- *      "" map<[sub_comparator], [default_validation_class]>
- *      PRIMARY KEY (key, super_column_name)
- *   )
- * In other words, every super column is encoded by a row. That row has one column for each defined "column_metadata", but it also
- * has a special map column (whose name is the empty string as this is guaranteed to never conflict with a user-defined
- * "column_metadata") which stores the super column "dynamic" sub-columns.
+ * SuperColumn families handling and detailed format description can be found in {@code SuperColumnCompatibility}.
  */
 public abstract class CompactTables
 {
-    // We use an empty value for the 1) this can't conflict with a user-defined column and 2) this actually
-    // validate with any comparator which makes it convenient for columnDefinitionComparator().
-    public static final ByteBuffer SUPER_COLUMN_MAP_COLUMN = ByteBufferUtil.EMPTY_BYTE_BUFFER;
-    public static final String SUPER_COLUMN_MAP_COLUMN_STR = UTF8Type.instance.compose(SUPER_COLUMN_MAP_COLUMN);
-
     private CompactTables() {}
 
-    public static ColumnDefinition getCompactValueColumn(PartitionColumns columns, boolean isSuper)
+    public static ColumnDefinition getCompactValueColumn(PartitionColumns columns)
     {
-        if (isSuper)
-        {
-            for (ColumnDefinition column : columns.regulars)
-                if (column.name.bytes.equals(SUPER_COLUMN_MAP_COLUMN))
-                    return column;
-            throw new AssertionError("Invalid super column table definition, no 'dynamic' map column");
-        }
         assert columns.regulars.simpleColumnCount() == 1 && columns.regulars.complexColumnCount() == 0;
         return columns.regulars.getSimple(0);
     }
@@ -104,11 +81,6 @@ public abstract class CompactTables
         return metadata.compactValueColumn().type instanceof EmptyType;
     }
 
-    public static boolean isSuperColumnMapColumn(ColumnDefinition column)
-    {
-        return column.kind == ColumnDefinition.Kind.REGULAR && column.name.bytes.equals(SUPER_COLUMN_MAP_COLUMN);
-    }
-
     public static DefaultNames defaultNameGenerator(Set<String> usedNames)
     {
         return new DefaultNames(new HashSet<String>(usedNames));

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/db/LegacyLayout.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/LegacyLayout.java b/src/java/org/apache/cassandra/db/LegacyLayout.java
index 4f7bc22..40b9fd3 100644
--- a/src/java/org/apache/cassandra/db/LegacyLayout.java
+++ b/src/java/org/apache/cassandra/db/LegacyLayout.java
@@ -24,6 +24,7 @@ import java.nio.ByteBuffer;
 import java.security.MessageDigest;
 import java.util.*;
 
+import org.apache.cassandra.cql3.SuperColumnCompatibility;
 import org.apache.cassandra.utils.AbstractIterator;
 import com.google.common.collect.Iterators;
 import com.google.common.collect.Lists;
@@ -298,7 +299,7 @@ public abstract class LegacyLayout
             // What it is depends if this a cell for a declared "static" column or a "dynamic" column part of the
             // super-column internal map.
             assert columnName != null; // This should never be null for supercolumns, see decodeForSuperColumn() above
-            values[clusteringSize] = columnName.equals(CompactTables.SUPER_COLUMN_MAP_COLUMN)
+            values[clusteringSize] = columnName.equals(SuperColumnCompatibility.SUPER_COLUMN_MAP_COLUMN)
                                    ? collectionElement
                                    : columnName;
         }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/db/SerializationHeader.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/SerializationHeader.java b/src/java/org/apache/cassandra/db/SerializationHeader.java
index 494c2a3..b2ed26e 100644
--- a/src/java/org/apache/cassandra/db/SerializationHeader.java
+++ b/src/java/org/apache/cassandra/db/SerializationHeader.java
@@ -332,6 +332,7 @@ public class SerializationHeader
             for (ByteBuffer name : typeMap.keySet())
             {
                 ColumnDefinition column = metadata.getColumnDefinition(name);
+
                 if (column == null)
                 {
                     // TODO: this imply we don't read data for a column we don't yet know about, which imply this is theoretically

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java b/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
index ac9cfd9..01c5e3e 100644
--- a/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
+++ b/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
@@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
 import org.apache.cassandra.config.*;
 import org.apache.cassandra.cql3.ColumnIdentifier;
 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;
@@ -271,10 +272,11 @@ public final class LegacySchemaMigrator
                                       SystemKeyspace.LEGACY_TRIGGERS);
         UntypedResultSet triggerRows = query(triggersQuery, keyspaceName, tableName);
 
-        return decodeTableMetadata(tableRow, columnRows, triggerRows);
+        return decodeTableMetadata(tableName, tableRow, columnRows, triggerRows);
     }
 
-    private static CFMetaData decodeTableMetadata(UntypedResultSet.Row tableRow,
+    private static CFMetaData decodeTableMetadata(String tableName,
+                                                  UntypedResultSet.Row tableRow,
                                                   UntypedResultSet columnRows,
                                                   UntypedResultSet triggerRows)
     {
@@ -297,7 +299,7 @@ public final class LegacySchemaMigrator
         if (rawIsDense != null && !rawIsDense)
             isDense = false;
         else
-            isDense = calculateIsDense(rawComparator, columnRows);
+            isDense = calculateIsDense(rawComparator, columnRows, isSuper);
 
         // now, if switched to sparse, remove redundant compact_value column and the last clustering column,
         // directly copying CASSANDRA-11502 logic. See CASSANDRA-11315.
@@ -389,7 +391,7 @@ public final class LegacySchemaMigrator
      * information for table just created through thrift, nor for table prior to CASSANDRA-7744, so this
      * method does its best to infer whether the table is dense or not based on other elements.
      */
-    private static boolean calculateIsDense(AbstractType<?> comparator, UntypedResultSet columnRows)
+    private static boolean calculateIsDense(AbstractType<?> comparator, UntypedResultSet columnRows, boolean isSuper)
     {
         /*
          * As said above, this method is only here because we need to deal with thrift upgrades.
@@ -411,8 +413,15 @@ public final class LegacySchemaMigrator
          * in the latter case only if the comparator is exactly CompositeType(UTF8Type).
          */
         for (UntypedResultSet.Row columnRow : columnRows)
+        {
             if ("regular".equals(columnRow.getString("type")))
                 return false;
+        }
+
+        // If we've checked the columns for supercf and found no regulars, it's dense. Relying on the emptiness
+        // of the value column is not enough due to index calculation.
+        if (isSuper)
+            return true;
 
         int maxClusteringIdx = -1;
         for (UntypedResultSet.Row columnRow : columnRows)
@@ -431,18 +440,11 @@ public final class LegacySchemaMigrator
         {
             String kind = columnRow.getString("type");
 
-            if ("compact_value".equals(kind))
+            if (!isSuper && "compact_value".equals(kind))
                 continue;
 
-            if ("clustering_key".equals(kind))
-            {
-                int position = columnRow.has("component_index") ? columnRow.getInt("component_index") : 0;
-                if (isSuper && position != 0)
-                    continue;
-
-                if (!isSuper && !isCompound)
-                    continue;
-            }
+            if ("clustering_key".equals(kind) && !isSuper && !isCompound)
+                continue;
 
             filteredRows.add(columnRow);
         }
@@ -569,14 +571,9 @@ public final class LegacySchemaMigrator
     // Should only be called on compact tables
     private static boolean checkNeedsUpgrade(Iterable<UntypedResultSet.Row> defs, boolean isSuper, boolean isStaticCompactTable)
     {
+        // For SuperColumn tables, re-create a compact value column
         if (isSuper)
-        {
-            // Check if we've added the "supercolumn map" column yet or not
-            for (UntypedResultSet.Row row : defs)
-                if (row.getString("column_name").isEmpty())
-                    return false;
             return true;
-        }
 
         // For static compact tables, we need to upgrade if the regular definitions haven't been converted to static yet,
         // i.e. if we don't have a static definition yet.
@@ -626,7 +623,7 @@ public final class LegacySchemaMigrator
 
         if (isSuper)
         {
-            defs.add(ColumnDefinition.regularDef(ksName, cfName, CompactTables.SUPER_COLUMN_MAP_COLUMN_STR, MapType.getInstance(subComparator, defaultValidator, true)));
+            defs.add(ColumnDefinition.regularDef(ksName, cfName, SuperColumnCompatibility.SUPER_COLUMN_MAP_COLUMN_STR, MapType.getInstance(subComparator, defaultValidator, true)));
         }
         else if (isStaticCompactTable)
         {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/thrift/CassandraServer.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/thrift/CassandraServer.java b/src/java/org/apache/cassandra/thrift/CassandraServer.java
index cb74b15..256f651 100644
--- a/src/java/org/apache/cassandra/thrift/CassandraServer.java
+++ b/src/java/org/apache/cassandra/thrift/CassandraServer.java
@@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory;
 import org.apache.cassandra.auth.Permission;
 import org.apache.cassandra.config.*;
 import org.apache.cassandra.cql3.QueryOptions;
+import org.apache.cassandra.cql3.SuperColumnCompatibility;
 import org.apache.cassandra.cql3.statements.ParsedStatement;
 import org.apache.cassandra.db.*;
 import org.apache.cassandra.db.context.CounterContext;
@@ -432,11 +433,15 @@ public class CassandraServer implements Cassandra.Iface
             ByteBuffer finish = range.reversed ? range.start : range.finish;
             builder.slice(def, start.hasRemaining() ? CellPath.create(start) : CellPath.BOTTOM, finish.hasRemaining() ? CellPath.create(finish) : CellPath.TOP);
 
+            if (metadata.isDense())
+                return builder.build();
+
             // We also want to add any staticly defined column if it's within the range
             AbstractType<?> cmp = metadata.thriftColumnNameType();
+
             for (ColumnDefinition column : metadata.partitionColumns())
             {
-                if (CompactTables.isSuperColumnMapColumn(column))
+                if (SuperColumnCompatibility.isSuperColumnMapColumn(column))
                     continue;
 
                 ByteBuffer name = column.name.bytes;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/src/java/org/apache/cassandra/thrift/ThriftConversion.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/thrift/ThriftConversion.java b/src/java/org/apache/cassandra/thrift/ThriftConversion.java
index bccfd8a..e8256a8 100644
--- a/src/java/org/apache/cassandra/thrift/ThriftConversion.java
+++ b/src/java/org/apache/cassandra/thrift/ThriftConversion.java
@@ -18,7 +18,6 @@
 package org.apache.cassandra.thrift;
 
 import java.util.*;
-import java.util.regex.Matcher;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Strings;
@@ -27,6 +26,7 @@ import com.google.common.collect.Maps;
 import org.apache.cassandra.config.*;
 import org.apache.cassandra.cql3.ColumnIdentifier;
 import org.apache.cassandra.cql3.Operator;
+import org.apache.cassandra.cql3.SuperColumnCompatibility;
 import org.apache.cassandra.cql3.statements.IndexTarget;
 import org.apache.cassandra.db.CompactTables;
 import org.apache.cassandra.db.LegacyLayout;
@@ -273,7 +273,8 @@ public class ThriftConversion
                                       hasKeyAlias ? null : keyValidator,
                                       rawComparator,
                                       subComparator,
-                                      defaultValidator);
+                                      defaultValidator,
+                                      isDense);
             }
 
             // We do not allow Thrift views, so we always set it to false
@@ -368,7 +369,8 @@ public class ThriftConversion
                                               AbstractType<?> keyValidator,
                                               AbstractType<?> comparator,
                                               AbstractType<?> subComparator,
-                                              AbstractType<?> defaultValidator)
+                                              AbstractType<?> defaultValidator,
+                                              boolean isDense)
     {
         CompactTables.DefaultNames names = CompactTables.defaultNameGenerator(defs);
         if (keyValidator != null)
@@ -389,7 +391,12 @@ public class ThriftConversion
         {
             // SuperColumn tables: we use a special map to hold dynamic values within a given super column
             defs.add(ColumnDefinition.clusteringDef(ks, cf, names.defaultClusteringName(), comparator, 0));
-            defs.add(ColumnDefinition.regularDef(ks, cf, CompactTables.SUPER_COLUMN_MAP_COLUMN_STR, MapType.getInstance(subComparator, defaultValidator, true)));
+            defs.add(ColumnDefinition.regularDef(ks, cf, SuperColumnCompatibility.SUPER_COLUMN_MAP_COLUMN_STR, MapType.getInstance(subComparator, defaultValidator, true)));
+            if (isDense)
+            {
+                defs.add(ColumnDefinition.clusteringDef(ks, cf, names.defaultClusteringName(), subComparator, 1));
+                defs.add(ColumnDefinition.regularDef(ks, cf, names.defaultCompactValueName(), defaultValidator));
+            }
         }
         else
         {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/test/unit/org/apache/cassandra/SchemaLoader.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/SchemaLoader.java b/test/unit/org/apache/cassandra/SchemaLoader.java
index 87e8e1e..1686973 100644
--- a/test/unit/org/apache/cassandra/SchemaLoader.java
+++ b/test/unit/org/apache/cassandra/SchemaLoader.java
@@ -387,25 +387,18 @@ public class SchemaLoader
             .compression(getCompressionParameters());
     }
 
-    // TODO: Fix superCFMD failing on legacy table creation. Seems to be applying composite comparator to partition key
     public static CFMetaData superCFMD(String ksName, String cfName, AbstractType subcc)
     {
         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

http://git-wip-us.apache.org/repos/asf/cassandra/blob/ce8c9b55/test/unit/org/apache/cassandra/cql3/ViewTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/ViewTest.java b/test/unit/org/apache/cassandra/cql3/ViewTest.java
index 1107a64..4a4fe1a 100644
--- a/test/unit/org/apache/cassandra/cql3/ViewTest.java
+++ b/test/unit/org/apache/cassandra/cql3/ViewTest.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.*;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.UUID;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import com.google.common.util.concurrent.Uninterruptibles;
@@ -36,6 +37,7 @@ import org.junit.Test;
 import com.datastax.driver.core.ResultSet;
 import com.datastax.driver.core.Row;
 import com.datastax.driver.core.exceptions.InvalidQueryException;
+import org.apache.cassandra.SchemaLoader;
 import org.apache.cassandra.concurrent.SEPExecutor;
 import org.apache.cassandra.concurrent.Stage;
 import org.apache.cassandra.concurrent.StageManager;
@@ -45,8 +47,12 @@ import org.apache.cassandra.db.ColumnFamilyStore;
 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.utils.FBUtilities;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 public class ViewTest extends CQLTester
 {
@@ -389,7 +395,30 @@ public class ViewTest extends CQLTester
     }
 
     @Test
-    public void testCreateMvWithTTL() throws Throwable
+    public void testSuperCoumn() throws Throwable
+    {
+        String keyspace = createKeyspaceName();
+        String table = createTableName();
+        SchemaLoader.createKeyspace(keyspace,
+                                    KeyspaceParams.simple(1),
+                                    SchemaLoader.superCFMD(keyspace, table, AsciiType.instance, AsciiType.instance));
+
+        execute("USE " + keyspace);
+        executeNet(protocolVersion, "USE " + keyspace);
+
+        try
+        {
+            createView("mv_super_column", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM " + keyspace + "." + table + " WHERE key IS NOT NULL AND column1 IS NOT NULL PRIMARY KEY (key,column1)");
+            Assert.fail("MV on SuperColumn table should fail");
+        }
+        catch (InvalidQueryException e)
+        {
+            assertEquals("Materialized views are not supported on SuperColumn tables", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testDurationsTable() throws Throwable
     {
         createTable("CREATE TABLE %s (" +
                     "k int PRIMARY KEY, " +


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


Mime
View raw message