Repository: cassandra
Updated Branches:
  refs/heads/trunk a604b14bf -> 65a7088e7


http://git-wip-us.apache.org/repos/asf/cassandra/blob/65a7088e/src/java/org/apache/cassandra/cql3/statements/SingleColumnRestriction.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/SingleColumnRestriction.java 
b/src/java/org/apache/cassandra/cql3/statements/SingleColumnRestriction.java
deleted file mode 100644
index b6ca640..0000000
--- a/src/java/org/apache/cassandra/cql3/statements/SingleColumnRestriction.java
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.cassandra.cql3.statements;
-
-import org.apache.cassandra.cql3.*;
-import org.apache.cassandra.exceptions.InvalidRequestException;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public abstract class SingleColumnRestriction implements Restriction
-{
-    public boolean isMultiColumn()
-    {
-        return false;
-    }
-
-    public static class EQ extends SingleColumnRestriction implements 
Restriction.EQ
-    {
-        protected final Term value;
-        private final boolean onToken;
-
-        public EQ(Term value, boolean onToken)
-        {
-            this.value = value;
-            this.onToken = onToken;
-        }
-
-        public boolean usesFunction(String ksName, String functionName)
-        {
-            return value != null && value.usesFunction(ksName, functionName);
-        }
-
-        public List<ByteBuffer> values(QueryOptions options) throws 
InvalidRequestException
-        {
-            return Collections.singletonList(value.bindAndGet(options));
-        }
-
-        public boolean isSlice()
-        {
-            return false;
-        }
-
-        public boolean isEQ()
-        {
-            return true;
-        }
-
-        public boolean isIN()
-        {
-            return false;
-        }
-
-        public boolean isContains()
-        {
-            return false;
-        }
-
-        public boolean isOnToken()
-        {
-            return onToken;
-        }
-
-        public boolean canEvaluateWithSlices()
-        {
-            return true;
-        }
-
-        @Override
-        public String toString()
-        {
-            return String.format("EQ(%s)%s", value, onToken ? "*" : "");
-        }
-    }
-
-    public static class InWithValues extends SingleColumnRestriction 
implements Restriction.IN
-    {
-        protected final List<Term> values;
-
-        public InWithValues(List<Term> values)
-        {
-            this.values = values;
-        }
-
-        public boolean usesFunction(String ksName, String functionName)
-        {
-            if (values != null)
-                for (Term value : values)
-                    if (value != null && value.usesFunction(ksName, 
functionName))
-                        return true;
-            return false;
-        }
-
-        public List<ByteBuffer> values(QueryOptions options) throws 
InvalidRequestException
-        {
-            List<ByteBuffer> buffers = new ArrayList<>(values.size());
-            for (Term value : values)
-                buffers.add(value.bindAndGet(options));
-            return buffers;
-        }
-
-        public boolean canHaveOnlyOneValue()
-        {
-            return values.size() == 1;
-        }
-
-        public boolean isSlice()
-        {
-            return false;
-        }
-
-        public boolean isEQ()
-        {
-            return false;
-        }
-
-        public boolean isIN()
-        {
-            return true;
-        }
-
-        public boolean isContains()
-        {
-            return false;
-        }
-
-        public boolean isOnToken()
-        {
-            return false;
-        }
-
-        public boolean canEvaluateWithSlices()
-        {
-            return true;
-        }
-
-        @Override
-        public String toString()
-        {
-            return String.format("IN(%s)", values);
-        }
-    }
-
-    public static class InWithMarker extends SingleColumnRestriction 
implements Restriction.IN
-    {
-        protected final AbstractMarker marker;
-
-        public InWithMarker(AbstractMarker marker)
-        {
-            this.marker = marker;
-        }
-
-        public boolean usesFunction(String ksName, String functionName)
-        {
-            return false;
-        }
-
-        public List<ByteBuffer> values(QueryOptions options) throws 
InvalidRequestException
-        {
-            Term.MultiItemTerminal lval = 
(Term.MultiItemTerminal)marker.bind(options);
-            if (lval == null)
-                throw new InvalidRequestException("Invalid null value for IN 
restriction");
-            return lval.getElements();
-        }
-
-        public boolean canHaveOnlyOneValue()
-        {
-            return false;
-        }
-
-        public boolean isSlice()
-        {
-            return false;
-        }
-
-        public boolean isEQ()
-        {
-            return false;
-        }
-
-        public boolean isIN()
-        {
-            return true;
-        }
-
-        public boolean isContains()
-        {
-            return false;
-        }
-
-        public boolean isOnToken()
-        {
-            return false;
-        }
-
-        public boolean canEvaluateWithSlices()
-        {
-            return true;
-        }
-
-        @Override
-        public String toString()
-        {
-            return "IN ?";
-        }
-    }
-
-    public static class Slice extends SingleColumnRestriction implements 
Restriction.Slice
-    {
-        protected final Term[] bounds;
-        protected final boolean[] boundInclusive;
-        protected final boolean onToken;
-
-        public Slice(boolean onToken)
-        {
-            this.bounds = new Term[2];
-            this.boundInclusive = new boolean[2];
-            this.onToken = onToken;
-        }
-
-        public boolean usesFunction(String ksName, String functionName)
-        {
-            for (Term value : bounds)
-                if (value != null && value.usesFunction(ksName, functionName))
-                    return true;
-            return false;
-        }
-
-        public boolean isSlice()
-        {
-            return true;
-        }
-
-        public boolean isEQ()
-        {
-            return false;
-        }
-
-        public boolean isIN()
-        {
-            return false;
-        }
-
-        public boolean isContains()
-        {
-            return false;
-        }
-
-        public List<ByteBuffer> values(QueryOptions options) throws 
InvalidRequestException
-        {
-            throw new UnsupportedOperationException();
-        }
-
-        public boolean isOnToken()
-        {
-            return onToken;
-        }
-
-        public boolean canEvaluateWithSlices()
-        {
-            return true;
-        }
-
-        /** Returns true if the start or end bound (depending on the argument) 
is set, false otherwise */
-        public boolean hasBound(Bound b)
-        {
-            return bounds[b.idx] != null;
-        }
-
-        public ByteBuffer bound(Bound b, QueryOptions options) throws 
InvalidRequestException
-        {
-            return bounds[b.idx].bindAndGet(options);
-        }
-
-        /** Returns true if the start or end bound (depending on the argument) 
is inclusive, false otherwise */
-        public boolean isInclusive(Bound b)
-        {
-            return bounds[b.idx] == null || boundInclusive[b.idx];
-        }
-
-        public Operator getRelation(Bound eocBound, Bound inclusiveBound)
-        {
-            switch (eocBound)
-            {
-                case START:
-                    return boundInclusive[inclusiveBound.idx] ? Operator.GTE : 
Operator.GT;
-                case END:
-                    return boundInclusive[inclusiveBound.idx] ? Operator.LTE : 
Operator.LT;
-            }
-            throw new AssertionError();
-        }
-
-        public Operator getIndexOperator(Bound b)
-        {
-            switch (b)
-            {
-                case START:
-                    return boundInclusive[b.idx] ? Operator.GTE : Operator.GT;
-                case END:
-                    return boundInclusive[b.idx] ? Operator.LTE : Operator.LT;
-            }
-            throw new AssertionError();
-        }
-
-        public void setBound(ColumnIdentifier name, Operator operator, Term t) 
throws InvalidRequestException
-        {
-            Bound b;
-            boolean inclusive;
-            switch (operator)
-            {
-                case GT:
-                    b = Bound.START;
-                    inclusive = false;
-                    break;
-                case GTE:
-                    b = Bound.START;
-                    inclusive = true;
-                    break;
-                case LT:
-                    b = Bound.END;
-                    inclusive = false;
-                    break;
-                case LTE:
-                    b = Bound.END;
-                    inclusive = true;
-                    break;
-                default:
-                    throw new AssertionError();
-            }
-
-            if (bounds[b.idx] != null)
-                throw new InvalidRequestException(String.format(
-                        "More than one restriction was found for the %s bound 
on %s", b.name().toLowerCase(), name));
-
-            bounds[b.idx] = t;
-            boundInclusive[b.idx] = inclusive;
-        }
-
-        @Override
-        public String toString()
-        {
-            return String.format("SLICE(%s %s, %s %s)%s", boundInclusive[0] ? 
">=" : ">",
-                                 bounds[0],
-                                 boundInclusive[1] ? "<=" : "<",
-                                 bounds[1],
-                                 onToken ? "*" : "");
-        }
-    }
-
-    // This holds both CONTAINS and CONTAINS_KEY restriction because we might 
want to have both of them.
-    public static class Contains extends SingleColumnRestriction
-    {
-        private List<Term> values; // for CONTAINS
-        private List<Term> keys;   // for CONTAINS_KEY
-
-        public boolean usesFunction(String ksName, String functionName)
-        {
-            if (values != null)
-                for (Term value : values)
-                    if (value != null && value.usesFunction(ksName, 
functionName))
-                        return true;
-            if (keys != null)
-                for (Term key : keys)
-                    if (key != null && key.usesFunction(ksName, functionName))
-                        return true;
-            return false;
-        }
-
-        public boolean hasContains()
-        {
-            return values != null;
-        }
-
-        public boolean hasContainsKey()
-        {
-            return keys != null;
-        }
-
-        public int numberOfValues()
-        {
-            return values == null ? 0 : values.size();
-        }
-
-        public int numberOfKeys()
-        {
-            return keys == null ? 0 : keys.size();
-        }
-
-        public void add(Term t, boolean isKey)
-        {
-            if (isKey)
-                addKey(t);
-            else
-                addValue(t);
-        }
-
-        public void addValue(Term t)
-        {
-            if (values == null)
-                values = new ArrayList<>();
-            values.add(t);
-        }
-
-        public void addKey(Term t)
-        {
-            if (keys == null)
-                keys = new ArrayList<>();
-            keys.add(t);
-        }
-
-        public List<ByteBuffer> values(QueryOptions options) throws 
InvalidRequestException
-        {
-            if (values == null)
-                return Collections.emptyList();
-
-            List<ByteBuffer> buffers = new 
ArrayList<ByteBuffer>(values.size());
-            for (Term value : values)
-                buffers.add(value.bindAndGet(options));
-            return buffers;
-        }
-
-        public List<ByteBuffer> keys(QueryOptions options) throws 
InvalidRequestException
-        {
-            if (keys == null)
-                return Collections.emptyList();
-
-            List<ByteBuffer> buffers = new ArrayList<ByteBuffer>(keys.size());
-            for (Term value : keys)
-                buffers.add(value.bindAndGet(options));
-            return buffers;
-        }
-
-        public boolean isSlice()
-        {
-            return false;
-        }
-
-        public boolean isEQ()
-        {
-            return false;
-        }
-
-        public boolean isIN()
-        {
-            return false;
-        }
-
-        public boolean isContains()
-        {
-            return true;
-        }
-
-        public boolean isOnToken()
-        {
-            return false;
-        }
-
-        public boolean canEvaluateWithSlices()
-        {
-            return false;
-        }
-
-        @Override
-        public String toString()
-        {
-            return String.format("CONTAINS(values=%s, keys=%s)", values, keys);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/65a7088e/src/java/org/apache/cassandra/db/composites/Composites.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/Composites.java 
b/src/java/org/apache/cassandra/db/composites/Composites.java
index f6626e0..fa0df48 100644
--- a/src/java/org/apache/cassandra/db/composites/Composites.java
+++ b/src/java/org/apache/cassandra/db/composites/Composites.java
@@ -22,8 +22,11 @@ import java.util.List;
 
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.db.filter.ColumnSlice;
-import org.apache.cassandra.utils.memory.AbstractAllocator;
 import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.memory.AbstractAllocator;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
 
 public abstract class Composites
 {
@@ -31,6 +34,23 @@ public abstract class Composites
 
     public static final Composite EMPTY = new EmptyComposite();
 
+    /**
+     * Converts the specified <code>Composites</code> into 
<code>ByteBuffer</code>s.
+     *
+     * @param composites the composites to convert.
+     * @return the <code>ByteBuffer</code>s corresponding to the specified 
<code>Composites</code>.
+     */
+    public static List<ByteBuffer> toByteBuffers(List<Composite> composites)
+    {
+        return Lists.transform(composites, new Function<Composite, 
ByteBuffer>()
+        {
+            public ByteBuffer apply(Composite composite)
+            {
+                return composite.toByteBuffer();
+            }
+        });
+    }
+
     static final CBuilder EMPTY_BUILDER = new CBuilder()
     {
         public int remainingCount() { return 0; }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/65a7088e/src/java/org/apache/cassandra/db/composites/CompositesBuilder.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/composites/CompositesBuilder.java 
b/src/java/org/apache/cassandra/db/composites/CompositesBuilder.java
index 4542ac5..9a32dcc 100644
--- a/src/java/org/apache/cassandra/db/composites/CompositesBuilder.java
+++ b/src/java/org/apache/cassandra/db/composites/CompositesBuilder.java
@@ -20,6 +20,7 @@ package org.apache.cassandra.db.composites;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Comparator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
@@ -240,8 +241,8 @@ public final class CompositesBuilder
         if (elementsList.isEmpty())
             return singletonList(builder.build().withEOC(eoc));
 
-        // Use a TreeSet to sort and eliminate duplicates
-        Set<Composite> set = new TreeSet<Composite>(comparator);
+        // Use a Set to sort if needed and eliminate duplicates
+        Set<Composite> set = newSet();
 
         for (int i = 0, m = elementsList.size(); i < m; i++)
         {
@@ -252,6 +253,16 @@ public final class CompositesBuilder
         return new ArrayList<>(set);
     }
 
+    /**
+     * Returns a new <code>Set</code> instance that will be used to eliminate 
duplicates and sort the results.
+     *
+     * @return a new <code>Set</code> instance.
+     */
+    private Set<Composite> newSet()
+    {
+        return comparator == null ? new LinkedHashSet<Composite>() : new 
TreeSet<Composite>(comparator);
+    }
+
     private void checkUpdateable()
     {
         if (!hasRemaining() || built)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/65a7088e/src/java/org/apache/cassandra/db/marshal/CollectionType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/CollectionType.java 
b/src/java/org/apache/cassandra/db/marshal/CollectionType.java
index 24ad533..3121899 100644
--- a/src/java/org/apache/cassandra/db/marshal/CollectionType.java
+++ b/src/java/org/apache/cassandra/db/marshal/CollectionType.java
@@ -26,6 +26,11 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.cassandra.cql3.CQL3Type;
+import org.apache.cassandra.cql3.ColumnSpecification;
+import org.apache.cassandra.cql3.Lists;
+import org.apache.cassandra.cql3.Maps;
+import org.apache.cassandra.cql3.Sets;
+
 import org.apache.cassandra.serializers.CollectionSerializer;
 import org.apache.cassandra.serializers.MarshalException;
 import org.apache.cassandra.utils.ByteBufferUtil;
@@ -43,7 +48,29 @@ public abstract class CollectionType<T> extends 
AbstractType<T>
 
     public enum Kind
     {
-        MAP, SET, LIST
+        MAP
+        {
+            public ColumnSpecification 
makeCollectionReceiver(ColumnSpecification collection, boolean isKey)
+            {
+                return isKey ? Maps.keySpecOf(collection) : 
Maps.valueSpecOf(collection);
+            }
+        },
+        SET
+        {
+            public ColumnSpecification 
makeCollectionReceiver(ColumnSpecification collection, boolean isKey)
+            {
+                return Sets.valueSpecOf(collection);
+            }
+        },
+        LIST
+        {
+            public ColumnSpecification 
makeCollectionReceiver(ColumnSpecification collection, boolean isKey)
+            {
+                return Lists.valueSpecOf(collection);
+            }
+        };
+
+        public abstract ColumnSpecification 
makeCollectionReceiver(ColumnSpecification collection, boolean isKey);
     }
 
     public final Kind kind;
@@ -59,6 +86,11 @@ public abstract class CollectionType<T> extends 
AbstractType<T>
     @Override
     public abstract CollectionSerializer<T> getSerializer();
 
+    public ColumnSpecification makeCollectionReceiver(ColumnSpecification 
collection, boolean isKey)
+    {
+        return kind.makeCollectionReceiver(collection, isKey);
+    }
+
     public String getString(ByteBuffer bytes)
     {
         return BytesType.instance.getString(bytes);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/65a7088e/src/java/org/apache/cassandra/exceptions/UnrecognizedEntityException.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/exceptions/UnrecognizedEntityException.java 
b/src/java/org/apache/cassandra/exceptions/UnrecognizedEntityException.java
new file mode 100644
index 0000000..e8392e9
--- /dev/null
+++ b/src/java/org/apache/cassandra/exceptions/UnrecognizedEntityException.java
@@ -0,0 +1,49 @@
+/*
+ * 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.exceptions;
+
+import org.apache.cassandra.cql3.ColumnIdentifier;
+import org.apache.cassandra.cql3.Relation;
+
+/**
+ * Exception thrown when an entity is not recognized within a relation.
+ */
+public final class UnrecognizedEntityException extends InvalidRequestException
+{
+    /**
+     * The unrecognized entity.
+     */
+    public final ColumnIdentifier entity;
+
+    /**
+     * The entity relation.
+     */
+    public final Relation relation;
+
+    /**
+     * Creates a new <code>UnrecognizedEntityException</code>.
+     * @param entity the unrecognized entity
+     * @param relation the entity relation
+     */
+    public UnrecognizedEntityException(ColumnIdentifier entity, Relation 
relation)
+    {
+        super(String.format("Undefined name %s in where clause ('%s')", 
entity, relation));
+        this.entity = entity;
+        this.relation = relation;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/65a7088e/test/unit/org/apache/cassandra/cql3/AliasTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/AliasTest.java 
b/test/unit/org/apache/cassandra/cql3/AliasTest.java
new file mode 100644
index 0000000..132aa04
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/AliasTest.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cassandra.cql3;
+
+import org.junit.Test;
+
+public class AliasTest extends CQLTester
+{
+    @Test
+    public void testAlias() throws Throwable
+    {
+        createTable("CREATE TABLE %s (id int PRIMARY KEY, name text)");
+
+        for (int i = 0; i < 5; i++)
+            execute("INSERT INTO %s (id, name) VALUES (?, ?) USING TTL 10 AND 
TIMESTAMP 0", i, Integer.toString(i));
+
+        assertInvalidMessage("Aliases aren't allowed in the where clause" ,
+                             "SELECT id AS user_id, name AS user_name FROM %s 
WHERE user_id = 0");
+
+        // test that select throws a meaningful exception for aliases in order 
by clause
+        assertInvalidMessage("Aliases are not allowed in order by clause",
+                             "SELECT id AS user_id, name AS user_name FROM %s 
WHERE id IN (0) ORDER BY user_name");
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/65a7088e/test/unit/org/apache/cassandra/cql3/ContainsRelationTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/ContainsRelationTest.java 
b/test/unit/org/apache/cassandra/cql3/ContainsRelationTest.java
index 12d65fa..8f78553 100644
--- a/test/unit/org/apache/cassandra/cql3/ContainsRelationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/ContainsRelationTest.java
@@ -26,7 +26,11 @@ public class ContainsRelationTest extends CQLTester
                    row("test", 5, set("lmn"))
         );
 
-        assertInvalid("SELECT * FROM %s WHERE account = ? AND categories 
CONTAINS ? AND categories CONTAINS ?", "xyz", "lmn", "notPresent");
+        assertInvalidMessage("Unsupported null value for indexed column 
categories",
+                             "SELECT * FROM %s WHERE account = ? AND id = ? 
AND categories CONTAINS ?", "test", 5, null);
+
+        assertInvalidMessage("Cannot execute this query as it might involve 
data filtering and thus may have unpredictable performance. If you want to 
execute this query despite the performance unpredictability, use ALLOW 
FILTERING",
+                             "SELECT * FROM %s WHERE account = ? AND 
categories CONTAINS ? AND categories CONTAINS ?", "xyz", "lmn", "notPresent");
         assertEmpty(execute("SELECT * FROM %s WHERE account = ? AND categories 
CONTAINS ? AND categories CONTAINS ? ALLOW FILTERING", "xyz", "lmn", 
"notPresent"));
     }
 
@@ -52,8 +56,12 @@ public class ContainsRelationTest extends CQLTester
                    row("test", 5, list("lmn"))
         );
 
-        assertInvalid("SELECT * FROM %s WHERE account = ? AND id = ? AND 
categories CONTAINS ? AND categories CONTAINS ?",
-                      "test", 5, "lmn", "notPresent");
+        assertInvalidMessage("Unsupported null value for indexed column 
categories",
+                             "SELECT * FROM %s WHERE account = ? AND id = ? 
AND categories CONTAINS ?", "test", 5, null);
+
+        assertInvalidMessage("Cannot execute this query as it might involve 
data filtering and thus may have unpredictable performance. If you want to 
execute this query despite the performance unpredictability, use ALLOW 
FILTERING",
+                             "SELECT * FROM %s WHERE account = ? AND id = ? 
AND categories CONTAINS ? AND categories CONTAINS ?",
+                             "test", 5, "lmn", "notPresent");
         assertEmpty(execute("SELECT * FROM %s WHERE account = ? AND id = ? AND 
categories CONTAINS ? AND categories CONTAINS ? ALLOW FILTERING",
                             "test", 5, "lmn", "notPresent"));
     }
@@ -79,13 +87,18 @@ public class ContainsRelationTest extends CQLTester
                    row("test", 5, map("lmn", "foo"))
         );
 
-        assertInvalid("SELECT * FROM %s WHERE account = ? AND id = ? AND 
categories CONTAINS KEY ? AND categories CONTAINS KEY ?",
-                      "test", 5, "lmn", "notPresent");
+        assertInvalidMessage("Unsupported null value for indexed column 
categories",
+                             "SELECT * FROM %s WHERE account = ? AND id = ? 
AND categories CONTAINS KEY ?", "test", 5, null);
+
+        assertInvalidMessage("Cannot execute this query as it might involve 
data filtering and thus may have unpredictable performance. If you want to 
execute this query despite the performance unpredictability, use ALLOW 
FILTERING",
+                             "SELECT * FROM %s WHERE account = ? AND id = ? 
AND categories CONTAINS KEY ? AND categories CONTAINS KEY ?",
+                             "test", 5, "lmn", "notPresent");
         assertEmpty(execute("SELECT * FROM %s WHERE account = ? AND id = ? AND 
categories CONTAINS KEY ? AND categories CONTAINS KEY ? ALLOW FILTERING",
                             "test", 5, "lmn", "notPresent"));
 
-        assertInvalid("SELECT * FROM %s WHERE account = ? AND id = ? AND 
categories CONTAINS KEY ? AND categories CONTAINS ?",
-                      "test", 5, "lmn", "foo");
+        assertInvalidMessage("Cannot execute this query as it might involve 
data filtering and thus may have unpredictable performance. If you want to 
execute this query despite the performance unpredictability, use ALLOW 
FILTERING",
+                             "SELECT * FROM %s WHERE account = ? AND id = ? 
AND categories CONTAINS KEY ? AND categories CONTAINS ?",
+                             "test", 5, "lmn", "foo");
     }
 
     @Test
@@ -110,7 +123,11 @@ public class ContainsRelationTest extends CQLTester
                    row("test", 5, map("lmn", "foo"))
         );
 
-        assertInvalid("SELECT * FROM %s WHERE account = ? AND id = ? AND 
categories CONTAINS ? AND categories CONTAINS ?"
+        assertInvalidMessage("Unsupported null value for indexed column 
categories",
+                             "SELECT * FROM %s WHERE account = ? AND id = ? 
AND categories CONTAINS ?", "test", 5, null);
+
+        assertInvalidMessage("Cannot execute this query as it might involve 
data filtering and thus may have unpredictable performance. If you want to 
execute this query despite the performance unpredictability, use ALLOW 
FILTERING",
+                             "SELECT * FROM %s WHERE account = ? AND id = ? 
AND categories CONTAINS ? AND categories CONTAINS ?"
                            , "test", 5, "foo", "notPresent");
 
         assertEmpty(execute("SELECT * FROM %s WHERE account = ? AND id = ? AND 
categories CONTAINS ? AND categories CONTAINS ? ALLOW FILTERING"
@@ -197,7 +214,8 @@ public class ContainsRelationTest extends CQLTester
         execute("INSERT INTO %s (account, id , categories) VALUES (?, ?, ?)", 
"test", 5, map("lmn", "foo"));
         execute("INSERT INTO %s (account, id , categories) VALUES (?, ?, ?)", 
"test", 6, map("lmn", "foo2"));
 
-        assertInvalid("SELECT * FROM %s WHERE account = ? AND categories 
CONTAINS ?", "test", "foo");
+        assertInvalidMessage("No secondary indexes on the restricted columns 
support the provided operators: 'categories CONTAINS <value>'",
+                             "SELECT * FROM %s WHERE account = ? AND 
categories CONTAINS ?", "test", "foo");
 
         assertRows(execute("SELECT * FROM %s WHERE account = ? AND categories 
CONTAINS KEY ?", "test", "lmn"),
                    row("test", 5, map("lmn", "foo")),
@@ -219,7 +237,8 @@ public class ContainsRelationTest extends CQLTester
         execute("INSERT INTO %s (account, id , categories) VALUES (?, ?, ?)", 
"test", 5, map("lmn", "foo"));
         execute("INSERT INTO %s (account, id , categories) VALUES (?, ?, ?)", 
"test", 6, map("lmn2", "foo"));
 
-        assertInvalid("SELECT * FROM %s WHERE account = ? AND categories 
CONTAINS KEY ?", "test", "lmn");
+        assertInvalidMessage("No secondary indexes on the restricted columns 
support the provided operators: 'categories CONTAINS KEY <value>'",
+                             "SELECT * FROM %s WHERE account = ? AND 
categories CONTAINS KEY ?", "test", "lmn");
 
         assertRows(execute("SELECT * FROM %s WHERE account = ? AND categories 
CONTAINS ?", "test", "foo"),
                    row("test", 5, map("lmn", "foo")),

http://git-wip-us.apache.org/repos/asf/cassandra/blob/65a7088e/test/unit/org/apache/cassandra/cql3/FrozenCollectionsTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/FrozenCollectionsTest.java 
b/test/unit/org/apache/cassandra/cql3/FrozenCollectionsTest.java
index bf7ccfd..896bc5f 100644
--- a/test/unit/org/apache/cassandra/cql3/FrozenCollectionsTest.java
+++ b/test/unit/org/apache/cassandra/cql3/FrozenCollectionsTest.java
@@ -75,8 +75,8 @@ public class FrozenCollectionsTest extends CQLTester
         );
 
         assertRows(execute("SELECT * FROM %s WHERE k IN ?", list(set(4, 5, 6), 
set())),
-                row(set(4, 5, 6), 0),
-                row(set(), 0)
+                   row(set(), 0),
+                   row(set(4, 5, 6), 0)
         );
 
         assertRows(execute("SELECT * FROM %s WHERE token(k) >= token(?)", 
set(4, 5, 6)),
@@ -144,9 +144,9 @@ public class FrozenCollectionsTest extends CQLTester
         );
 
         assertRows(execute("SELECT * FROM %s WHERE k IN ?", list(map(set(4, 5, 
6), list(1, 2, 3)), map(), map(set(), list(1, 2, 3)))),
-            row(map(set(4, 5, 6), list(1, 2, 3)), 0),
-            row(map(), 0),
-            row(map(set(), list(1, 2, 3)), 0)
+                   row(map(), 0),
+                   row(map(set(), list(1, 2, 3)), 0),
+                   row(map(set(4, 5, 6), list(1, 2, 3)), 0)
         );
 
         assertRows(execute("SELECT * FROM %s WHERE token(k) >= token(?)", 
map(set(4, 5, 6), list(1, 2, 3))),
@@ -615,10 +615,10 @@ public class FrozenCollectionsTest extends CQLTester
                              "SELECT * FROM %s WHERE c CONTAINS KEY ?", 1);
 
         // normal indexes on frozen collections don't support CONTAINS or 
CONTAINS KEY
-        assertInvalidMessage("Cannot restrict column \"b\" by a CONTAINS 
relation without a secondary index",
+        assertInvalidMessage("Cannot restrict clustering columns by a CONTAINS 
relation without a secondary index",
                              "SELECT * FROM %s WHERE b CONTAINS ?", 1);
 
-        assertInvalidMessage("Cannot restrict column \"b\" by a CONTAINS 
relation without a secondary index",
+        assertInvalidMessage("Cannot restrict clustering columns by a CONTAINS 
relation without a secondary index",
                              "SELECT * FROM %s WHERE b CONTAINS ? ALLOW 
FILTERING", 1);
 
         assertInvalidMessage("No secondary indexes on the restricted columns 
support the provided operator",
@@ -627,7 +627,7 @@ public class FrozenCollectionsTest extends CQLTester
         assertInvalidMessage("No secondary indexes on the restricted columns 
support the provided operator",
                              "SELECT * FROM %s WHERE d CONTAINS KEY ? ALLOW 
FILTERING", 1);
 
-        assertInvalidMessage("Cannot restrict column \"b\" by a CONTAINS 
relation without a secondary index",
+        assertInvalidMessage("Cannot restrict clustering columns by a CONTAINS 
relation without a secondary index",
                              "SELECT * FROM %s WHERE b CONTAINS ? AND d 
CONTAINS KEY ? ALLOW FILTERING", 1, 1);
 
         // index lookup on b

http://git-wip-us.apache.org/repos/asf/cassandra/blob/65a7088e/test/unit/org/apache/cassandra/cql3/MultiColumnRelationTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/MultiColumnRelationTest.java 
b/test/unit/org/apache/cassandra/cql3/MultiColumnRelationTest.java
index 4c3ba2a..291afd8 100644
--- a/test/unit/org/apache/cassandra/cql3/MultiColumnRelationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/MultiColumnRelationTest.java
@@ -24,56 +24,77 @@ public class MultiColumnRelationTest extends CQLTester
     @Test
     public void testSingleClusteringInvalidQueries() throws Throwable
     {
-        for (String compactOption : new String[]{"", " WITH COMPACT STORAGE"})
+        for (String compactOption : new String[] { "", " WITH COMPACT STORAGE" 
})
         {
             createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))" + compactOption);
 
             assertInvalidSyntax("SELECT * FROM %s WHERE () = (?, ?)", 1, 2);
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND (b) = (?) AND (b) 
> (?)", 0, 0);
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND (b) > (?) AND (b) 
> (?)", 0, 1);
-            assertInvalid("SELECT * FROM %s WHERE (a, b) = (?, ?)", 0, 0);
+            assertInvalidMessage("b cannot be restricted by more than one 
relation if it includes an Equal",
+                                 "SELECT * FROM %s WHERE a = 0 AND (b) = (?) 
AND (b) > (?)", 0, 0);
+            assertInvalidMessage("More than one restriction was found for the 
start bound on b",
+                                 "SELECT * FROM %s WHERE a = 0 AND (b) > (?) 
AND (b) > (?)", 0, 1);
+            assertInvalidMessage("Multi-column relations can only be applied 
to clustering columns but was applied to: a",
+                                 "SELECT * FROM %s WHERE (a, b) = (?, ?)", 0, 
0);
         }
     }
 
     @Test
     public void testMultiClusteringInvalidQueries() throws Throwable
     {
-        for (String compactOption : new String[]{"", " WITH COMPACT STORAGE"})
+        for (String compactOption : new String[] { "", " WITH COMPACT STORAGE" 
})
         {
             createTable("CREATE TABLE %s (a int, b int, c int, d int, PRIMARY 
KEY (a, b, c, d))" + compactOption);
 
             assertInvalidSyntax("SELECT * FROM %s WHERE a = 0 AND (b, c) > 
()");
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND (b, c) > (?, ?, 
?)", 1, 2, 3);
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND (b, c) > (?, ?)", 
1, null);
+            assertInvalidMessage("Expected 2 elements in value tuple, but got 
3: (?, ?, ?)",
+                                 "SELECT * FROM %s WHERE a = 0 AND (b, c) > 
(?, ?, ?)", 1, 2, 3);
+            assertInvalidMessage("Invalid null value in condition for column 
c",
+                                 "SELECT * FROM %s WHERE a = 0 AND (b, c) > 
(?, ?)", 1, null);
 
             // Wrong order of columns
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND (d, c, b) = (?, ?, 
?)", 0, 0, 0);
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND (d, c, b) > (?, ?, 
?)", 0, 0, 0);
+            assertInvalidMessage("Clustering columns may not be skipped in 
multi-column relations. They should appear in the PRIMARY KEY order. Got (d, c, 
b) = (?, ?, ?)",
+                                 "SELECT * FROM %s WHERE a = 0 AND (d, c, b) = 
(?, ?, ?)", 0, 0, 0);
+            assertInvalidMessage("Clustering columns may not be skipped in 
multi-column relations. They should appear in the PRIMARY KEY order. Got (d, c, 
b) > (?, ?, ?)",
+                                 "SELECT * FROM %s WHERE a = 0 AND (d, c, b) > 
(?, ?, ?)", 0, 0, 0);
 
             // Wrong number of values
-            assertInvalid("SELECT * FROM %s WHERE a=0 AND (b, c, d) IN ((?, 
?))", 0, 1);
-            assertInvalid("SELECT * FROM %s WHERE a=0 AND (b, c, d) IN ((?, ?, 
?, ?, ?))", 0, 1, 2, 3, 4);
+            assertInvalidMessage("Expected 3 elements in value tuple, but got 
2: (?, ?)",
+                                 "SELECT * FROM %s WHERE a=0 AND (b, c, d) IN 
((?, ?))", 0, 1);
+            assertInvalidMessage("Expected 3 elements in value tuple, but got 
5: (?, ?, ?, ?, ?)",
+                                 "SELECT * FROM %s WHERE a=0 AND (b, c, d) IN 
((?, ?, ?, ?, ?))", 0, 1, 2, 3, 4);
 
             // Missing first clustering column
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND (c, d) = (?, ?)", 
0, 0);
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND (c, d) > (?, ?)", 
0, 0);
+            assertInvalidMessage("Clustering columns may not be skipped in 
multi-column relations. They should appear in the PRIMARY KEY order. Got (c, d) 
= (?, ?)",
+                                 "SELECT * FROM %s WHERE a = 0 AND (c, d) = 
(?, ?)", 0, 0);
+            assertInvalidMessage("Clustering columns may not be skipped in 
multi-column relations. They should appear in the PRIMARY KEY order. Got (c, d) 
> (?, ?)",
+                                 "SELECT * FROM %s WHERE a = 0 AND (c, d) > 
(?, ?)", 0, 0);
 
             // Nulls
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND (b, c, d) IN ((?, 
?, ?))", 1, 2, null);
+            assertInvalidMessage("Invalid null value in condition for column 
d",
+                                 "SELECT * FROM %s WHERE a = 0 AND (b, c, d) 
IN ((?, ?, ?))", 1, 2, null);
 
             // Wrong type for 'd'
             assertInvalid("SELECT * FROM %s WHERE a = 0 AND (b, c, d) = (?, ?, 
?)", 1, 2, "foobar");
-
             assertInvalid("SELECT * FROM %s WHERE a = 0 AND b = (?, ?, ?)", 1, 
2, 3);
 
             // Mix single and tuple inequalities
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND (b, c, d) > (?, ?, 
?) AND b < ?", 0, 1, 0, 1);
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND (b, c, d) > (?, ?, 
?) AND c < ?", 0, 1, 0, 1);
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND b > ? AND (b, c, 
d) < (?, ?, ?)", 1, 1, 1, 0);
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND c > ? AND (b, c, 
d) < (?, ?, ?)", 1, 1, 1, 0);
-
-            assertInvalid("SELECT * FROM %s WHERE (a, b, c, d) IN ((?, ?, ?, 
?))", 0, 1, 2, 3);
-            assertInvalid("SELECT * FROM %s WHERE (c, d) IN ((?, ?))", 0, 1);
+            assertInvalidMessage("Mixing single column relations and multi 
column relations on clustering columns is not allowed",
+                                 "SELECT * FROM %s WHERE a = 0 AND (b, c, d) > 
(?, ?, ?) AND b < ?", 0, 1, 0, 1);
+            assertInvalidMessage("Mixing single column relations and multi 
column relations on clustering columns is not allowed",
+                                 "SELECT * FROM %s WHERE a = 0 AND (b, c, d) > 
(?, ?, ?) AND c < ?", 0, 1, 0, 1);
+            assertInvalidMessage("Mixing single column relations and multi 
column relations on clustering columns is not allowed",
+                                 "SELECT * FROM %s WHERE a = 0 AND b > ? AND 
(b, c, d) < (?, ?, ?)", 1, 1, 1, 0);
+            assertInvalidMessage("Mixing single column relations and multi 
column relations on clustering columns is not allowed",
+                                 "SELECT * FROM %s WHERE a = 0 AND c > ? AND 
(b, c, d) < (?, ?, ?)", 1, 1, 1, 0);
+
+            assertInvalidMessage("Multi-column relations can only be applied 
to clustering columns but was applied to: a",
+                                 "SELECT * FROM %s WHERE (a, b, c, d) IN ((?, 
?, ?, ?))", 0, 1, 2, 3);
+            assertInvalidMessage("Clustering columns may not be skipped in 
multi-column relations. They should appear in the PRIMARY KEY order. Got (c, d) 
IN ((?, ?))",
+                                 "SELECT * FROM %s WHERE (c, d) IN ((?, ?))", 
0, 1);
+
+            assertInvalidMessage("Mixing single column relations and multi 
column relations on clustering columns is not allowed",
+                                 "SELECT * FROM %s WHERE a = ? AND (b, c) in 
((?, ?), (?, ?)) AND d > ?",
+                                 0, 0, 0, 0, 0, 0);
 
             assertInvalid("SELECT * FROM %s WHERE a = ? AND (b, c) in ((?, ?), 
(?, ?)) AND d > ?", 0, 0, 0, 0, 0, 0);
         }
@@ -85,10 +106,12 @@ public class MultiColumnRelationTest extends CQLTester
         for (String compactOption : new String[]{"", " WITH COMPACT STORAGE"})
         {
             createTable("CREATE TABLE %s (a int PRIMARY KEY, b int)" + 
compactOption);
-
-            assertInvalid("SELECT * FROM %s WHERE (a) > (?)", 0);
-            assertInvalid("SELECT * FROM %s WHERE (a) = (?)", 0);
-            assertInvalid("SELECT * FROM %s WHERE (b) = (?)", 0);
+            assertInvalidMessage("Multi-column relations can only be applied 
to clustering columns but was applied to: a",
+                                 "SELECT * FROM %s WHERE (a) > (?)", 0);
+            assertInvalidMessage("Multi-column relations can only be applied 
to clustering columns but was applied to: a",
+                                 "SELECT * FROM %s WHERE (a) = (?)", 0);
+            assertInvalidMessage("Multi-column relations can only be applied 
to clustering columns but was applied to: b",
+                                 "SELECT * FROM %s WHERE (b) = (?)", 0);
         }
     }
 
@@ -150,7 +173,8 @@ public class MultiColumnRelationTest extends CQLTester
         for (String compactOption : new String[]{"", " WITH COMPACT STORAGE"})
         {
             createTable("CREATE TABLE %s (a int PRIMARY KEY, b int)" + 
compactOption);
-            assertInvalid("SELECT * FROM %s WHERE a = 0 AND (b) != (0)");
+            assertInvalidMessage("Unsupported \"!=\" relation: (b) != (0)",
+                    "SELECT * FROM %s WHERE a = 0 AND (b) != (0)");
         }
     }
 
@@ -444,10 +468,10 @@ public class MultiColumnRelationTest extends CQLTester
 
             // same query, but reversed order for the IN values
             assertRows(execute("SELECT * FROM %s WHERE a IN (?, ?) AND (b, c, 
d) IN (?, ?)", 1, 0, tuple(0, 1, 1), tuple(0, 1, 0)),
-                    row(1, 0, 1, 0),
-                    row(1, 0, 1, 1),
                     row(0, 0, 1, 0),
-                    row(0, 0, 1, 1)
+                    row(0, 0, 1, 1),
+                    row(1, 0, 1, 0),
+                    row(1, 0, 1, 1)
             );
 
             assertRows(execute("SELECT * FROM %s WHERE a IN (?, ?) and (b, c) 
IN ((?, ?))", 0, 1, 0, 1),
@@ -555,4 +579,81 @@ public class MultiColumnRelationTest extends CQLTester
             assertEmpty(execute("SELECT * FROM %s WHERE a = ? AND (b, c) > (?, 
?)", 0, 1, 0));
         }
     }
+
+    @Test
+    public void testMultipleClusteringWithIndex() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, 
PRIMARY KEY (a, b, c, d))");
+        createIndex("CREATE INDEX ON %s (b)");
+        createIndex("CREATE INDEX ON %s (e)");
+
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 0, 
0, 0, 0);
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 0, 
1, 0, 1);
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 0, 
1, 1, 2);
+
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 1, 
0, 0, 0);
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 1, 
1, 0, 1);
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 1, 
1, 1, 2);
+
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 2, 
0, 0, 0);
+
+        assertRows(execute("SELECT * FROM %s WHERE (b) = (?)", 1),
+                   row(0, 1, 0, 0, 0),
+                   row(0, 1, 1, 0, 1),
+                   row(0, 1, 1, 1, 2));
+
+        assertRows(execute("SELECT * FROM %s WHERE (b, c) = (?, ?) ALLOW 
FILTERING", 1, 1),
+                   row(0, 1, 1, 0, 1),
+                   row(0, 1, 1, 1, 2));
+
+        assertRows(execute("SELECT * FROM %s WHERE (b, c) = (?, ?) AND e = ? 
ALLOW FILTERING", 1, 1, 2),
+                   row(0, 1, 1, 1, 2));
+
+        assertRows(execute("SELECT * FROM %s WHERE (b) IN ((?)) AND e = ? 
ALLOW FILTERING", 1, 2),
+                   row(0, 1, 1, 1, 2));
+
+        assertInvalidMessage("IN restrictions are not supported on indexed 
columns",
+                             "SELECT * FROM %s WHERE (b) IN ((?), (?)) AND e = 
? ALLOW FILTERING", 0, 1, 2);
+
+        assertInvalidMessage("IN restrictions are not supported on indexed 
columns",
+                             "SELECT * FROM %s WHERE (b, c) IN ((?, ?)) AND e 
= ? ALLOW FILTERING", 0, 1, 2);
+
+        assertInvalidMessage("IN restrictions are not supported on indexed 
columns",
+                             "SELECT * FROM %s WHERE (b, c) IN ((?, ?), (?, 
?)) AND e = ? ALLOW FILTERING", 0, 1, 1, 1, 2);
+
+        assertInvalidMessage("Slice restrictions are not supported on indexed 
columns which are part of a multi column relation",
+                             "SELECT * FROM %s WHERE (b) >= (?) AND e = ? 
ALLOW FILTERING", 1, 2);
+    }
+
+    @Test
+    public void testMultiplePartitionKeyAndMultiClusteringWithIndex() throws 
Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, 
PRIMARY KEY ((a, b), c, d, e))");
+        createIndex("CREATE INDEX ON %s (c)");
+
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 0, 
0, 0, 0);
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 0, 
0, 1, 0);
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 0, 
0, 1, 1);
+
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 0, 
1, 0, 0);
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 0, 
1, 1, 0);
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 0, 
1, 1, 1);
+
+        execute("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?)", 0, 0, 
2, 0, 0);
+
+        assertRows(execute("SELECT * FROM %s WHERE a = ? AND (c) = (?) ALLOW 
FILTERING", 0, 1),
+                   row(0, 0, 1, 0, 0),
+                   row(0, 0, 1, 1, 0),
+                   row(0, 0, 1, 1, 1));
+
+        assertRows(execute("SELECT * FROM %s WHERE a = ? AND (c, d) = (?, ?) 
ALLOW FILTERING", 0, 1, 1),
+                   row(0, 0, 1, 1, 0),
+                   row(0, 0, 1, 1, 1));
+
+        assertInvalidMessage("Partition key parts: b must be restricted as 
other parts are",
+                             "SELECT * FROM %s WHERE a = ? AND (c, d) IN ((?, 
?)) ALLOW FILTERING", 0, 1, 1);
+
+        assertInvalidMessage("Partition key parts: b must be restricted as 
other parts are",
+                             "SELECT * FROM %s WHERE a = ? AND (c, d) >= (?, 
?) ALLOW FILTERING", 0, 1, 1);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/65a7088e/test/unit/org/apache/cassandra/cql3/SelectWithTokenFunctionTest.java
----------------------------------------------------------------------
diff --git 
a/test/unit/org/apache/cassandra/cql3/SelectWithTokenFunctionTest.java 
b/test/unit/org/apache/cassandra/cql3/SelectWithTokenFunctionTest.java
index 6f9f5e2..39b62e3 100644
--- a/test/unit/org/apache/cassandra/cql3/SelectWithTokenFunctionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/SelectWithTokenFunctionTest.java
@@ -30,17 +30,34 @@ public class SelectWithTokenFunctionTest extends CQLTester
         assertRows(execute("SELECT * FROM %s WHERE token(a) >= token(?)", 0), 
row(0, "a"));
         assertRows(execute("SELECT * FROM %s WHERE token(a) >= token(?) and 
token(a) < token(?)", 0, 1), row(0, "a"));
         assertInvalid("SELECT * FROM %s WHERE token(a) > token(?)", "a");
-        assertInvalid("SELECT * FROM %s WHERE token(a, b) >= token(?, ?)", 
"b", 0);
-        assertInvalid("SELECT * FROM %s WHERE token(a) >= token(?) and 
token(a) >= token(?)", 0, 1);
-        assertInvalid("SELECT * FROM %s WHERE token(a) >= token(?) and 
token(a) = token(?)", 0, 1);
+        assertInvalidMessage("Columns \"a\" cannot be restricted by both a 
normal relation and a token relation",
+                             "SELECT * FROM %s WHERE token(a) > token(?) AND a 
= ?", 1, 1);
+        assertInvalidMessage("Columns \"a\" cannot be restricted by both a 
normal relation and a token relation",
+                             "SELECT * FROM %s WHERE a = ? and token(a) > 
token(?)", 1, 1);
+        assertInvalidMessage("The token() function must contains only 
partition key components",
+                             "SELECT * FROM %s WHERE token(a, b) >= token(?, 
?)", "b", 0);
+        assertInvalidMessage("More than one restriction was found for the 
start bound on a",
+                             "SELECT * FROM %s WHERE token(a) >= token(?) and 
token(a) >= token(?)", 0, 1);
+        assertInvalidMessage("Columns \"a\" cannot be restricted by both an 
equality and an inequality relation",
+                             "SELECT * FROM %s WHERE token(a) >= token(?) and 
token(a) = token(?)", 0, 1);
         assertInvalidSyntax("SELECT * FROM %s WHERE token(a) = token(?) and 
token(a) IN (token(?))", 0, 1);
+
+        assertInvalidMessage("More than one restriction was found for the 
start bound on a",
+                             "SELECT * FROM %s WHERE token(a) > token(?) AND 
token(a) > token(?)", 1, 2);
+        assertInvalidMessage("More than one restriction was found for the end 
bound on a",
+                             "SELECT * FROM %s WHERE token(a) <= token(?) AND 
token(a) < token(?)", 1, 2);
+        assertInvalidMessage("Columns \"a\" cannot be restricted by both an 
equality and an inequality relation",
+                             "SELECT * FROM %s WHERE token(a) > token(?) AND 
token(a) = token(?)", 1, 2);
+        assertInvalidMessage("a cannot be restricted by more than one relation 
if it includes an Equal",
+                             "SELECT * FROM %s WHERE  token(a) = token(?) AND 
token(a) > token(?)", 1, 2);
     }
 
     @Test
     public void testTokenFunctionWithPartitionKeyAndClusteringKeyArguments() 
throws Throwable
     {
         createTable("CREATE TABLE IF NOT EXISTS %s (a int, b text, PRIMARY KEY 
(a, b))");
-        assertInvalid("SELECT * FROM %s WHERE token(a, b) > token(0, 'c')");
+        assertInvalidMessage("The token() function must contains only 
partition key components",
+                             "SELECT * FROM %s WHERE token(a, b) > token(0, 
'c')");
     }
 
     @Test
@@ -59,8 +76,16 @@ public class SelectWithTokenFunctionTest extends CQLTester
                            0, "d"),
                    row(0, "b"),
                    row(0, "c"));
-        assertInvalid("SELECT * FROM %s WHERE token(a) > token(?) and token(b) 
> token(?)", 0, "a");
-        assertInvalid("SELECT * FROM %s WHERE token(a) > token(?, ?) and 
token(a) < token(?, ?) and token(b) > token(?, ?) ", 0, "a", 0, "d", 0, "a");
-        assertInvalid("SELECT * FROM %s WHERE token(b, a) > token(0, 'c')");
+        assertInvalidMessage("The token() function must be applied to all 
partition key components or none of them",
+                             "SELECT * FROM %s WHERE token(a) > token(?) and 
token(b) > token(?)", 0, "a");
+        assertInvalidMessage("The token() function must be applied to all 
partition key components or none of them",
+                             "SELECT * FROM %s WHERE token(a) > token(?, ?) 
and token(a) < token(?, ?) and token(b) > token(?, ?) ",
+                             0, "a", 0, "d", 0, "a");
+        assertInvalidMessage("The token function arguments must be in the 
partition key order: a, b",
+                             "SELECT * FROM %s WHERE token(b, a) > token(0, 
'c')");
+        assertInvalidMessage("The token() function must be applied to all 
partition key components or none of them",
+                             "SELECT * FROM %s WHERE token(a, b) > token(?, ?) 
and token(b) < token(?, ?)", 0, "a", 0, "a");
+        assertInvalidMessage("The token() function must be applied to all 
partition key components or none of them",
+                             "SELECT * FROM %s WHERE token(a) > token(?, ?) 
and token(b) > token(?, ?)", 0, "a", 0, "a");
     }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/65a7088e/test/unit/org/apache/cassandra/cql3/SingleColumnRelationTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/SingleColumnRelationTest.java 
b/test/unit/org/apache/cassandra/cql3/SingleColumnRelationTest.java
index c93147b..112da06 100644
--- a/test/unit/org/apache/cassandra/cql3/SingleColumnRelationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/SingleColumnRelationTest.java
@@ -31,9 +31,12 @@ public class SingleColumnRelationTest extends CQLTester
         createIndex("CREATE INDEX ON %s (c)");
         createIndex("CREATE INDEX ON %s (d)");
 
-        assertInvalid("SELECT * FROM %s WHERE a = 0 AND b=?", set(0));
-        assertInvalid("SELECT * FROM %s WHERE a = 0 AND c=?", list(0));
-        assertInvalid("SELECT * FROM %s WHERE a = 0 AND d=?", map(0, 0));
+        assertInvalidMessage("Collection column 'b' (set<int>) cannot be 
restricted by a '=' relation",
+                             "SELECT * FROM %s WHERE a = 0 AND b=?", set(0));
+        assertInvalidMessage("Collection column 'c' (list<int>) cannot be 
restricted by a '=' relation",
+                             "SELECT * FROM %s WHERE a = 0 AND c=?", list(0));
+        assertInvalidMessage("Collection column 'd' (map<int, int>) cannot be 
restricted by a '=' relation",
+                             "SELECT * FROM %s WHERE a = 0 AND d=?", map(0, 
0));
     }
 
     @Test
@@ -44,11 +47,16 @@ public class SingleColumnRelationTest extends CQLTester
         execute("INSERT INTO %s (a, b, c) VALUES (0, {0}, 0)");
 
         // non-EQ operators
-        assertInvalid("SELECT * FROM %s WHERE c = 0 AND b > ?", set(0));
-        assertInvalid("SELECT * FROM %s WHERE c = 0 AND b >= ?", set(0));
-        assertInvalid("SELECT * FROM %s WHERE c = 0 AND b < ?", set(0));
-        assertInvalid("SELECT * FROM %s WHERE c = 0 AND b <= ?", set(0));
-        assertInvalid("SELECT * FROM %s WHERE c = 0 AND b IN (?)", set(0));
+        assertInvalidMessage("Collection column 'b' (set<int>) cannot be 
restricted by a '>' relation",
+                             "SELECT * FROM %s WHERE c = 0 AND b > ?", set(0));
+        assertInvalidMessage("Collection column 'b' (set<int>) cannot be 
restricted by a '>=' relation",
+                             "SELECT * FROM %s WHERE c = 0 AND b >= ?", 
set(0));
+        assertInvalidMessage("Collection column 'b' (set<int>) cannot be 
restricted by a '<' relation",
+                             "SELECT * FROM %s WHERE c = 0 AND b < ?", set(0));
+        assertInvalidMessage("Collection column 'b' (set<int>) cannot be 
restricted by a '<=' relation",
+                             "SELECT * FROM %s WHERE c = 0 AND b <= ?", 
set(0));
+        assertInvalidMessage("Collection column 'b' (set<int>) cannot be 
restricted by a 'IN' relation",
+                             "SELECT * FROM %s WHERE c = 0 AND b IN (?)", 
set(0));
     }
 
     @Test
@@ -114,7 +122,8 @@ public class SingleColumnRelationTest extends CQLTester
                    row("first", 2, 6, 2),
                    row("first", 3, 7, 3));
 
-        assertInvalid("select * from %s where a = ? and b in ? and c in ?", 
"first", null, Arrays.asList(7, 6));
+        assertInvalidMessage("Invalid null value for IN restriction",
+                             "select * from %s where a = ? and b in ? and c in 
?", "first", null, Arrays.asList(7, 6));
 
         assertRows(execute("select * from %s where a = ? and c >= ? and b in 
(?, ?)", "first", 6, 3, 2),
                    row("first", 2, 6, 2),
@@ -128,11 +137,32 @@ public class SingleColumnRelationTest extends CQLTester
 
         assertRows(execute("select * from %s where a = ? and c < ? and b in 
(?, ?)", "first", 7, 3, 2),
                    row("first", 2, 6, 2));
+//---
+        assertRows(execute("select * from %s where a = ? and c >= ? and c <= ? 
and b in (?, ?)", "first", 6, 7, 3, 2),
+                   row("first", 2, 6, 2),
+                   row("first", 3, 7, 3));
+
+        assertRows(execute("select * from %s where a = ? and c > ? and c <= ? 
and b in (?, ?)", "first", 6, 7, 3, 2),
+                   row("first", 3, 7, 3));
+
+        assertEmpty(execute("select * from %s where a = ? and c > ? and c < ? 
and b in (?, ?)", "first", 6, 7, 3, 2));
+
+        assertInvalidMessage("Column \"c\" cannot be restricted by both an 
equality and an inequality relation",
+                             "select * from %s where a = ? and c > ? and c = ? 
and b in (?, ?)", "first", 6, 7, 3, 2);
+
+        assertInvalidMessage("c cannot be restricted by more than one relation 
if it includes an Equal",
+                             "select * from %s where a = ? and c = ? and c > ? 
 and b in (?, ?)", "first", 6, 7, 3, 2);
 
         assertRows(execute("select * from %s where a = ? and c in (?, ?) and b 
in (?, ?) order by b DESC",
                            "first", 7, 6, 3, 2),
                    row("first", 3, 7, 3),
                    row("first", 2, 6, 2));
+
+        assertInvalidMessage("More than one restriction was found for the 
start bound on b",
+                             "select * from %s where a = ? and b > ? and b > 
?", "first", 6, 3, 2);
+
+        assertInvalidMessage("More than one restriction was found for the end 
bound on b",
+                             "select * from %s where a = ? and b < ? and b <= 
?", "first", 6, 3, 2);
     }
 
     @Test
@@ -144,8 +174,16 @@ public class SingleColumnRelationTest extends CQLTester
         execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "first", 3, 
3, 3);
         execute("insert into %s (a, b, c, d) values (?, ?, ?, ?)", "second", 
4, 4, 4);
 
-        assertInvalid("select * from %s where a in (?, ?)", "first", "second");
-        assertInvalid("select * from %s where a in (?, ?) and b in (?, ?)", 
"first", "second", 2, 3);
+        assertInvalidMessage("Partition KEY part a cannot be restricted by IN 
relation (only the last part of the partition key can)",
+                             "select * from %s where a in (?, ?)", "first", 
"second");
+        assertInvalidMessage("Partition KEY part a cannot be restricted by IN 
relation (only the last part of the partition key can)",
+                             "select * from %s where a in (?, ?) and b in (?, 
?)", "first", "second", 2, 3);
+        assertInvalidMessage("Partition key parts: b must be restricted as 
other parts are",
+                             "select * from %s where a = ?", "first");
+        assertInvalidMessage("b cannot be restricted by more than one relation 
if it includes a IN",
+                             "select * from %s where a = ? AND b IN (?, ?) AND 
b = ?", "first", 2, 2, 3);
+        assertInvalidMessage("b cannot be restricted by more than one relation 
if it includes an Equal",
+                             "select * from %s where a = ? AND b = ? AND b IN 
(?, ?)", "first", 2, 2, 3);
     }
 
     @Test
@@ -167,4 +205,162 @@ public class SingleColumnRelationTest extends CQLTester
                    row("first", 2, 6, 2),
                    row("first", 3, 7, 3));
     }
+
+    @Test
+    public void testAllowFilteringWithClusteringColumn() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int, c int, v int, PRIMARY KEY (k, 
c))");
+
+        execute("INSERT INTO %s (k, c, v) VALUES(?, ?, ?)", 1, 2, 1);
+        execute("INSERT INTO %s (k, c, v) VALUES(?, ?, ?)", 1, 3, 2);
+        execute("INSERT INTO %s (k, c, v) VALUES(?, ?, ?)", 2, 2, 3);
+
+        // Don't require filtering, always allowed
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 1),
+                   row(1, 2, 1),
+                   row(1, 3, 2));
+
+        assertRows(execute("SELECT * FROM %s WHERE k = ? AND c > ?", 1, 2), 
row(1, 3, 2));
+
+        assertRows(execute("SELECT * FROM %s WHERE k = ? AND c = ?", 1, 2), 
row(1, 2, 1));
+
+        assertRows(execute("SELECT * FROM %s WHERE k = ? ALLOW FILTERING", 1),
+                   row(1, 2, 1),
+                   row(1, 3, 2));
+
+        assertRows(execute("SELECT * FROM %s WHERE k = ? AND c > ? ALLOW 
FILTERING", 1, 2), row(1, 3, 2));
+
+        assertRows(execute("SELECT * FROM %s WHERE k = ? AND c = ? ALLOW 
FILTERING", 1, 2), row(1, 2, 1));
+
+        // Require filtering, allowed only with ALLOW FILTERING
+        assertInvalidMessage("Cannot execute this query as it might involve 
data filtering",
+                             "SELECT * FROM %s WHERE c = ?", 2);
+        assertInvalidMessage("Cannot execute this query as it might involve 
data filtering",
+                             "SELECT * FROM %s WHERE c > ? AND c <= ?", 2, 4);
+
+        assertRows(execute("SELECT * FROM %s WHERE c = ? ALLOW FILTERING", 2),
+                   row(1, 2, 1),
+                   row(2, 2, 3));
+
+        assertRows(execute("SELECT * FROM %s WHERE c > ? AND c <= ? ALLOW 
FILTERING", 2, 4), row(1, 3, 2));
+    }
+
+    @Test
+    public void testAllowFilteringWithIndexedColumn() throws Throwable
+    {
+        createTable("CREATE TABLE %s (k int PRIMARY KEY, a int, b int)");
+        createIndex("CREATE INDEX ON %s(a)");
+
+        execute("INSERT INTO %s(k, a, b) VALUES(?, ?, ?)", 1, 10, 100);
+        execute("INSERT INTO %s(k, a, b) VALUES(?, ?, ?)", 2, 20, 200);
+        execute("INSERT INTO %s(k, a, b) VALUES(?, ?, ?)", 3, 30, 300);
+        execute("INSERT INTO %s(k, a, b) VALUES(?, ?, ?)", 4, 40, 400);
+
+        // Don't require filtering, always allowed
+        assertRows(execute("SELECT * FROM %s WHERE k = ?", 1), row(1, 10, 
100));
+        assertRows(execute("SELECT * FROM %s WHERE a = ?", 20), row(2, 20, 
200));
+        assertRows(execute("SELECT * FROM %s WHERE k = ? ALLOW FILTERING", 1), 
row(1, 10, 100));
+        assertRows(execute("SELECT * FROM %s WHERE a = ? ALLOW FILTERING", 
20), row(2, 20, 200));
+
+        assertInvalid("SELECT * FROM %s WHERE a = ? AND b = ?");
+        assertRows(execute("SELECT * FROM %s WHERE a = ? AND b = ? ALLOW 
FILTERING", 20, 200), row(2, 20, 200));
+    }
+
+    @Test
+    public void testIndexQueriesOnComplexPrimaryKey() throws Throwable
+    {
+        createTable("CREATE TABLE %s (pk0 int, pk1 int, ck0 int, ck1 int, ck2 
int, value int, PRIMARY KEY ((pk0, pk1), ck0, ck1, ck2))");
+
+        createIndex("CREATE INDEX ON %s (ck1)");
+        createIndex("CREATE INDEX ON %s (ck2)");
+        createIndex("CREATE INDEX ON %s (pk0)");
+        createIndex("CREATE INDEX ON %s (ck0)");
+
+        execute("INSERT INTO %s (pk0, pk1, ck0, ck1, ck2, value) VALUES (?, ?, 
?, ?, ?, ?)", 0, 1, 2, 3, 4, 5);
+        execute("INSERT INTO %s (pk0, pk1, ck0, ck1, ck2, value) VALUES (?, ?, 
?, ?, ?, ?)", 1, 2, 3, 4, 5, 0);
+        execute("INSERT INTO %s (pk0, pk1, ck0, ck1, ck2, value) VALUES (?, ?, 
?, ?, ?, ?)", 2, 3, 4, 5, 0, 1);
+        execute("INSERT INTO %s (pk0, pk1, ck0, ck1, ck2, value) VALUES (?, ?, 
?, ?, ?, ?)", 3, 4, 5, 0, 1, 2);
+        execute("INSERT INTO %s (pk0, pk1, ck0, ck1, ck2, value) VALUES (?, ?, 
?, ?, ?, ?)", 4, 5, 0, 1, 2, 3);
+        execute("INSERT INTO %s (pk0, pk1, ck0, ck1, ck2, value) VALUES (?, ?, 
?, ?, ?, ?)", 5, 0, 1, 2, 3, 4);
+
+        assertRows(execute("SELECT value FROM %s WHERE pk0 = 2"), row(1));
+        assertRows(execute("SELECT value FROM %s WHERE ck0 = 0"), row(3));
+        assertRows(execute("SELECT value FROM %s WHERE pk0 = 3 AND pk1 = 4 AND 
ck1 = 0"), row(2));
+        assertRows(execute("SELECT value FROM %s WHERE pk0 = 5 AND pk1 = 0 AND 
ck0 = 1 AND ck2 = 3 ALLOW FILTERING"), row(4));
+    }
+
+    @Test
+    public void testIndexOnClusteringColumns() throws Throwable
+    {
+        createTable("CREATE TABLE %s (id1 int, id2 int, author text, time 
bigint, v1 text, v2 text, PRIMARY KEY ((id1, id2), author, time))");
+        createIndex("CREATE INDEX ON %s(time)");
+        createIndex("CREATE INDEX ON %s(id2)");
+
+        execute("INSERT INTO %s(id1, id2, author, time, v1, v2) VALUES(0, 0, 
'bob', 0, 'A', 'A')");
+        execute("INSERT INTO %s(id1, id2, author, time, v1, v2) VALUES(0, 0, 
'bob', 1, 'B', 'B')");
+        execute("INSERT INTO %s(id1, id2, author, time, v1, v2) VALUES(0, 1, 
'bob', 2, 'C', 'C')");
+        execute("INSERT INTO %s(id1, id2, author, time, v1, v2) VALUES(0, 0, 
'tom', 0, 'D', 'D')");
+        execute("INSERT INTO %s(id1, id2, author, time, v1, v2) VALUES(0, 1, 
'tom', 1, 'E', 'E')");
+
+        assertRows(execute("SELECT v1 FROM %s WHERE time = 1"), row("B"), 
row("E"));
+
+        assertRows(execute("SELECT v1 FROM %s WHERE id2 = 1"), row("C"), 
row("E"));
+
+        assertRows(execute("SELECT v1 FROM %s WHERE id1 = 0 AND id2 = 0 AND 
author = 'bob' AND time = 0"), row("A"));
+
+        // Test for CASSANDRA-8206
+        execute("UPDATE %s SET v2 = null WHERE id1 = 0 AND id2 = 0 AND author 
= 'bob' AND time = 1");
+
+        assertRows(execute("SELECT v1 FROM %s WHERE id2 = 0"), row("A"), 
row("B"), row("D"));
+
+        assertRows(execute("SELECT v1 FROM %s WHERE time = 1"), row("B"), 
row("E"));
+
+        assertInvalidMessage("IN restrictions are not supported on indexed 
columns",
+                             "SELECT v1 FROM %s WHERE id2 = 0 and time IN (1, 
2) ALLOW FILTERING");
+    }
+
+    @Test
+    public void testCompositeIndexWithPrimaryKey() throws Throwable
+    {
+        createTable("CREATE TABLE %s (blog_id int, time1 int, time2 int, 
author text, content text, PRIMARY KEY (blog_id, time1, time2))");
+
+        createIndex("CREATE INDEX ON %s(author)");
+
+        String req = "INSERT INTO %s (blog_id, time1, time2, author, content) 
VALUES (?, ?, ?, ?, ?)";
+        execute(req, 1, 0, 0, "foo", "bar1");
+        execute(req, 1, 0, 1, "foo", "bar2");
+        execute(req, 2, 1, 0, "foo", "baz");
+        execute(req, 3, 0, 1, "gux", "qux");
+
+        assertRows(execute("SELECT blog_id, content FROM %s WHERE 
author='foo'"),
+                   row(1, "bar1"),
+                   row(1, "bar2"),
+                   row(2, "baz"));
+        assertRows(execute("SELECT blog_id, content FROM %s WHERE time1 > 0 
AND author='foo' ALLOW FILTERING"), row(2, "baz"));
+        assertRows(execute("SELECT blog_id, content FROM %s WHERE time1 = 1 
AND author='foo' ALLOW FILTERING"), row(2, "baz"));
+        assertRows(execute("SELECT blog_id, content FROM %s WHERE time1 = 1 
AND time2 = 0 AND author='foo' ALLOW FILTERING"),
+                   row(2, "baz"));
+        assertEmpty(execute("SELECT content FROM %s WHERE time1 = 1 AND time2 
= 1 AND author='foo' ALLOW FILTERING"));
+        assertEmpty(execute("SELECT content FROM %s WHERE time1 = 1 AND time2 
> 0 AND author='foo' ALLOW FILTERING"));
+
+        assertInvalidMessage("Cannot execute this query as it might involve 
data filtering",
+                             "SELECT content FROM %s WHERE time2 >= 0 AND 
author='foo'");
+    }
+
+    @Test
+    public void testRangeQueryOnIndex() throws Throwable
+    {
+        createTable("CREATE TABLE %s (id int primary key, row int, setid 
int);");
+        createIndex("CREATE INDEX ON %s (setid)");
+
+        String q = "INSERT INTO %s (id, row, setid) VALUES (?, ?, ?);";
+        execute(q, 0, 0, 0);
+        execute(q, 1, 1, 0);
+        execute(q, 2, 2, 0);
+        execute(q, 3, 3, 0);
+
+        assertInvalidMessage("Cannot execute this query as it might involve 
data filtering",
+                             "SELECT * FROM %s WHERE setid = 0 AND row < 1;");
+        assertRows(execute("SELECT * FROM %s WHERE setid = 0 AND row < 1 ALLOW 
FILTERING;"), row(0, 0, 0));
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/65a7088e/test/unit/org/apache/cassandra/cql3/ThriftCompatibilityTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/ThriftCompatibilityTest.java 
b/test/unit/org/apache/cassandra/cql3/ThriftCompatibilityTest.java
index deb3082..88ee688 100644
--- a/test/unit/org/apache/cassandra/cql3/ThriftCompatibilityTest.java
+++ b/test/unit/org/apache/cassandra/cql3/ThriftCompatibilityTest.java
@@ -33,7 +33,7 @@ public class ThriftCompatibilityTest extends SchemaLoader
     @BeforeClass
     public static void defineSchema() throws Exception
     {
-        SchemaLoader.prepareServer();
+        // The before class annotation of SchemaLoader will prepare the 
service so no need to do it here
         SchemaLoader.createKeyspace("thriftcompat",
                                     SimpleStrategy.class,
                                     KSMetaData.optsWithRF(1),

Reply via email to