http://git-wip-us.apache.org/repos/asf/cassandra/blob/71778eec/test/unit/org/apache/cassandra/cql3/MultiColumnRelationTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/MultiColumnRelationTest.java
index 51625da,a4ee5d7..8bd4e97
--- a/test/unit/org/apache/cassandra/cql3/MultiColumnRelationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/MultiColumnRelationTest.java
@@@ -64,39 -64,174 +64,225 @@@ public class MultiColumnRelationTest ex
                                   "SELECT * FROM %s WHERE a=0 AND (b, c, d) IN 
((?, ?, ?, ?, ?))", 0, 1, 2, 3, 4);
  
              // Missing first clustering column
-             assertInvalidMessage("Clustering columns may not be skipped in 
multi-column relations. They should appear in the PRIMARY KEY order. Got (c, d) 
= (?, ?)",
 -            assertInvalidMessage("PRIMARY KEY column \"c\" cannot be 
restricted (preceding column \"b\" is not restricted)",
++            assertInvalidMessage("PRIMARY KEY column \"c\" cannot be 
restricted as preceding column \"b\" is not restricted",
                                   "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) 
> (?, ?)",
 -            assertInvalidMessage("PRIMARY KEY column \"c\" cannot be 
restricted (preceding column \"b\" is not restricted)",
++            assertInvalidMessage("PRIMARY KEY column \"c\" cannot be 
restricted as preceding column \"b\" is not restricted",
                                   "SELECT * FROM %s WHERE a = 0 AND (c, d) > 
(?, ?)", 0, 0);
  
              // Nulls
--            assertInvalidMessage("Invalid null value in condition for column 
d",
++            assertInvalidMessage("Invalid null value in condition for 
columns: [b, c, d]",
                                   "SELECT * FROM %s WHERE a = 0 AND (b, c, d) 
IN ((?, ?, ?))", 1, 2, null);
  
              // Wrong type for 'd'
 -            assertInvalidMessage("Expected 4 or 0 byte int (6)",
 -                                 "SELECT * FROM %s WHERE a = 0 AND (b, c, d) 
= (?, ?, ?)", 1, 2, "foobar");
 -
 -            assertInvalidMessage("Invalid tuple type literal for b of type 
int",
 -                                 "SELECT * FROM %s WHERE a = 0 AND b = (?, ?, 
?)", 1, 2, 3);
 +            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
 -            assertInvalidMessage("Column \"b\" cannot be restricted by both a 
tuple notation inequality and a single column inequality (b < ?)",
 +            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("Column \"c\" cannot be restricted by both a 
tuple notation inequality and a single column inequality (c < ?)",
 +            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("Column \"b\" cannot have both 
tuple-notation inequalities and single-column inequalities: (b, c, d) < (?, ?, 
?)",
 +            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("Column \"c\" cannot have both 
tuple-notation inequalities and single-column inequalities: (b, c, d) < (?, ?, 
?)",
 +            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: a",
 +            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 ((?, ?))",
 -            assertInvalidMessage("PRIMARY KEY column \"c\" cannot be 
restricted (preceding column \"b\" is not restricted)",
++            assertInvalidMessage("PRIMARY KEY column \"c\" cannot be 
restricted as preceding column \"b\" is not restricted",
                                   "SELECT * FROM %s WHERE (c, d) IN ((?, ?))", 
0, 1);
 -            assertInvalidMessage("PRIMARY KEY column \"c\" cannot be 
restricted (preceding column \"b\" is restricted by a non-EQ relation)",
 +
-             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);
++            assertInvalidMessage("Clustering column \"c\" cannot be 
restricted (preceding column \"b\" is restricted by a non-EQ relation)",
+                                  "SELECT * FROM %s WHERE a = ? AND b > ?  AND 
(c, d) IN ((?, ?))", 0, 0, 0, 0);
+ 
 -            assertInvalidMessage("PRIMARY KEY column \"c\" cannot be 
restricted (preceding column \"b\" is restricted by a non-EQ relation)",
++            assertInvalidMessage("Clustering column \"c\" cannot be 
restricted (preceding column \"b\" is restricted by a non-EQ relation)",
+                                  "SELECT * FROM %s WHERE a = ? AND b > ?  AND 
(c, d) > (?, ?)", 0, 0, 0, 0);
+             assertInvalidMessage("PRIMARY KEY column \"c\" cannot be 
restricted (preceding column \"b\" is restricted by a non-EQ relation)",
+                                  "SELECT * FROM %s WHERE a = ? AND (c, d) > 
(?, ?) AND b > ?  ", 0, 0, 0, 0);
 -            assertInvalidMessage("Column \"c\" cannot be restricted by two 
tuple-notation inequalities not starting with the same column: (c) < (?)",
++            assertInvalidMessage("Column \"c\" cannot be restricted by two 
tuple-notation inequalities not starting with the same column",
+                                  "SELECT * FROM %s WHERE a = ? AND (b, c) > 
(?, ?) AND (b) < (?) AND (c) < (?)", 0, 0, 0, 0, 0);
 -            assertInvalidMessage("Column \"c\" cannot be restricted by two 
tuple-notation inequalities not starting with the same column: (b, c) > (?, ?)",
++            assertInvalidMessage("Column \"c\" cannot be restricted by two 
tuple-notation inequalities not starting with the same column",
+                                  "SELECT * FROM %s WHERE a = ? AND (c) < (?) 
AND (b, c) > (?, ?) AND (b) < (?)", 0, 0, 0, 0, 0);
 -            assertInvalidMessage("Column \"c\" cannot be restricted by two 
tuple-notation inequalities not starting with the same column: (b, c) > (?, ?)",
++            assertInvalidMessage("Clustering column \"c\" cannot be 
restricted (preceding column \"b\" is restricted by a non-EQ relation)",
+                                  "SELECT * FROM %s WHERE a = ? AND (b) < (?) 
AND (c) < (?) AND (b, c) > (?, ?)", 0, 0, 0, 0, 0);
+ 
 -            assertInvalidMessage("Column \"c\" cannot be restricted by two 
tuple-notation inequalities not starting with the same column: (c) < (?)",
++            assertInvalidMessage("Column \"c\" cannot be restricted by two 
tuple-notation inequalities not starting with the same column",
+                                  "SELECT * FROM %s WHERE a = ? AND (b, c) > 
(?, ?) AND (c) < (?)", 0, 0, 0, 0);
 -
 -            assertInvalidMessage("PRIMARY KEY column \"d\" cannot be 
restricted (preceding column \"c\" is restricted by an IN tuple notation)",
 -                                 "SELECT * FROM %s WHERE a = ? AND (b, c) in 
((?, ?), (?, ?)) AND d > ?", 0, 0, 0, 0, 0, 0);
+         }
+     }
+ 
+     @Test
+     public void testMultiAndSingleColumnRelationMix() throws Throwable
+     {
+         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);
+ 
+             execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, 
0, 0);
+             execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, 
1, 0);
+             execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, 
1, 1);
+ 
+             execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 1, 
0, 0);
+             execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 1, 
1, 0);
+             execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 1, 
1, 1);
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and b = ? and 
(c, d) = (?, ?)", 0, 1, 0, 0),
+                        row(0, 1, 0, 0));
+ 
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and b IN (?, ?) 
and (c, d) = (?, ?)", 0, 0, 1, 0, 0),
++                       row(0, 0, 0, 0),
++                       row(0, 1, 0, 0));
++
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and b = ? and 
(c) IN ((?))", 0, 1, 0),
+                        row(0, 1, 0, 0));
+ 
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and b IN (?, ?) 
and (c) IN ((?))", 0, 0, 1, 0),
++                       row(0, 0, 0, 0),
++                       row(0, 1, 0, 0));
++
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and b = ? and 
(c) IN ((?), (?))", 0, 1, 0, 1),
+                        row(0, 1, 0, 0),
+                        row(0, 1, 1, 0),
+                        row(0, 1, 1, 1));
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and b = ? and 
(c, d) IN ((?, ?))", 0, 1, 0, 0),
+                        row(0, 1, 0, 0));
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and b = ? and 
(c, d) IN ((?, ?), (?, ?))", 0, 1, 0, 0, 1, 1),
+                        row(0, 1, 0, 0),
+                        row(0, 1, 1, 1));
+ 
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and b IN (?, ?) 
and (c, d) IN ((?, ?), (?, ?))", 0, 0, 1, 0, 0, 1, 1),
++                       row(0, 0, 0, 0),
++                       row(0, 0, 1, 1),
++                       row(0, 1, 0, 0),
++                       row(0, 1, 1, 1));
++
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and b = ? and 
(c, d) > (?, ?)", 0, 1, 0, 0),
+                        row(0, 1, 1, 0),
+                        row(0, 1, 1, 1));
+ 
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and b IN (?, ?) 
and (c, d) > (?, ?)", 0, 0, 1, 0, 0),
++                       row(0, 0, 1, 0),
++                       row(0, 0, 1, 1),
++                       row(0, 1, 1, 0),
++                       row(0, 1, 1, 1));
++
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and b = ? and 
(c, d) > (?, ?) and (c) <= (?) ", 0, 1, 0, 0, 1),
+                        row(0, 1, 1, 0),
+                        row(0, 1, 1, 1));
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and b = ? and 
(c, d) >= (?, ?) and (c, d) < (?, ?)", 0, 1, 0, 0, 1, 1),
+                        row(0, 1, 0, 0),
+                        row(0, 1, 1, 0));
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and (b, c) = (?, 
?) and d = ?", 0, 0, 1, 0),
+                        row(0, 0, 1, 0));
+ 
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and (b, c) IN 
((?, ?), (?, ?)) and d = ?", 0, 0, 1, 0, 0, 0),
++                       row(0, 0, 0, 0),
++                       row(0, 0, 1, 0));
++
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and b = ? and 
(c) = (?) and d = ?", 0, 0, 1, 0),
+                        row(0, 0, 1, 0));
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and (b, c) = (?, 
?) and d IN (?, ?)", 0, 0, 1, 0, 2),
+                        row(0, 0, 1, 0));
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and b = ? and 
(c) = (?) and d IN (?, ?)", 0, 0, 1, 0, 2),
+                        row(0, 0, 1, 0));
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and (b, c) = (?, 
?) and d >= ?", 0, 0, 1, 0),
+                        row(0, 0, 1, 0),
+                        row(0, 0, 1, 1));
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and d < 1 and 
(b, c) = (?, ?) and d >= ?", 0, 0, 1, 0),
+                        row(0, 0, 1, 0));
++
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and d < 1 and 
(b, c) IN ((?, ?), (?, ?)) and d >= ?", 0, 0, 1, 0, 0, 0),
++                       row(0, 0, 0, 0),
++                       row(0, 0, 1, 0));
+         }
+     }
+ 
+     @Test
 -    public void testMultipleMultiColumnRelation() throws Throwable
++    public void testSeveralMultiColumnRelation() throws Throwable
+     {
+         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);
+ 
+             execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, 
0, 0);
+             execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, 
1, 0);
+             execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, 
1, 1);
+ 
+             execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 1, 
0, 0);
+             execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 1, 
1, 0);
+             execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 1, 
1, 1);
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) = (?) 
and (c, d) = (?, ?)", 0, 1, 0, 0),
+                        row(0, 1, 0, 0));
+ 
 -            assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) = (?) 
and (c) = (?) and (d) = (?)", 0, 1, 0, 0),
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) IN ((?), 
(?)) and (c, d) = (?, ?)", 0, 0, 1, 0, 0),
++                       row(0, 0, 0, 0),
+                        row(0, 1, 0, 0));
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) = (?) 
and (c) IN ((?))", 0, 1, 0),
+                        row(0, 1, 0, 0));
+ 
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) IN 
((?),(?)) and (c) IN ((?))", 0, 0, 1, 0),
++                       row(0, 0, 0, 0),
++                       row(0, 1, 0, 0));
++
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) = (?) 
and (c) IN ((?), (?))", 0, 1, 0, 1),
+                        row(0, 1, 0, 0),
+                        row(0, 1, 1, 0),
+                        row(0, 1, 1, 1));
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) = (?) 
and (c, d) IN ((?, ?))", 0, 1, 0, 0),
+                        row(0, 1, 0, 0));
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) = (?) 
and (c, d) IN ((?, ?), (?, ?))", 0, 1, 0, 0, 1, 1),
+                        row(0, 1, 0, 0),
+                        row(0, 1, 1, 1));
+ 
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) IN ((?), 
(?)) and (c, d) IN ((?, ?), (?, ?))", 0, 0, 1, 0, 0, 1, 1),
++                       row(0, 0, 0, 0),
++                       row(0, 0, 1, 1),
++                       row(0, 1, 0, 0),
++                       row(0, 1, 1, 1));
++
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) = (?) 
and (c, d) > (?, ?)", 0, 1, 0, 0),
+                        row(0, 1, 1, 0),
+                        row(0, 1, 1, 1));
+ 
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) IN 
((?),(?)) and (c, d) > (?, ?)", 0, 0, 1, 0, 0),
++                       row(0, 0, 1, 0),
++                       row(0, 0, 1, 1),
++                       row(0, 1, 1, 0),
++                       row(0, 1, 1, 1));
++
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) = (?) 
and (c, d) > (?, ?) and (c) <= (?) ", 0, 1, 0, 0, 1),
+                        row(0, 1, 1, 0),
+                        row(0, 1, 1, 1));
+ 
+             assertRows(execute("SELECT * FROM %s WHERE a = ? and (b) = (?) 
and (c, d) >= (?, ?) and (c, d) < (?, ?)", 0, 1, 0, 0, 1, 1),
+                        row(0, 1, 0, 0),
+                        row(0, 1, 1, 0));
+ 
 -            assertRows(execute("SELECT * FROM %s WHERE a = ? and (b, c) = (?, 
?) and (d) = (?)", 0, 0, 1, 0),
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and (b, c) = (?, 
?) and d = ?", 0, 0, 1, 0),
++                       row(0, 0, 1, 0));
++
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and (b, c) IN 
((?, ?), (?, ?)) and d = ?", 0, 0, 1, 0, 0, 0),
++                       row(0, 0, 0, 0),
++                       row(0, 0, 1, 0));
++
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and (d) < (1) 
and (b, c) = (?, ?) and (d) >= (?)", 0, 0, 1, 0),
++                       row(0, 0, 1, 0));
 +
-             assertInvalid("SELECT * FROM %s WHERE a = ? AND (b, c) in ((?, 
?), (?, ?)) AND d > ?", 0, 0, 0, 0, 0, 0);
++            assertRows(execute("SELECT * FROM %s WHERE a = ? and (d) < (1) 
and (b, c) IN ((?, ?), (?, ?)) and (d) >= (?)", 0, 0, 1, 0, 0, 0),
++                       row(0, 0, 0, 0),
+                        row(0, 0, 1, 0));
          }
      }
  

http://git-wip-us.apache.org/repos/asf/cassandra/blob/71778eec/test/unit/org/apache/cassandra/cql3/restrictions/PrimaryKeyRestrictionSetTest.java
----------------------------------------------------------------------
diff --cc 
test/unit/org/apache/cassandra/cql3/restrictions/PrimaryKeyRestrictionSetTest.java
index 0000000,0000000..05d6e98
new file mode 100644
--- /dev/null
+++ 
b/test/unit/org/apache/cassandra/cql3/restrictions/PrimaryKeyRestrictionSetTest.java
@@@ -1,0 -1,0 +1,1120 @@@
++/*
++ * 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.restrictions;
++
++import java.nio.ByteBuffer;
++import java.util.ArrayList;
++import java.util.List;
++
++import org.junit.Test;
++
++import org.apache.cassandra.config.CFMetaData;
++import org.apache.cassandra.config.ColumnDefinition;
++import org.apache.cassandra.cql3.*;
++import org.apache.cassandra.cql3.Term.MultiItemTerminal;
++import org.apache.cassandra.cql3.statements.Bound;
++import org.apache.cassandra.db.ColumnFamilyType;
++import org.apache.cassandra.db.composites.Composite;
++import org.apache.cassandra.db.composites.Composite.EOC;
++import org.apache.cassandra.db.composites.Composites;
++import org.apache.cassandra.db.composites.CompoundSparseCellNameType;
++import org.apache.cassandra.db.marshal.AbstractType;
++import org.apache.cassandra.db.marshal.Int32Type;
++import org.apache.cassandra.exceptions.InvalidRequestException;
++import org.apache.cassandra.utils.ByteBufferUtil;
++
++import static java.util.Arrays.asList;
++import static org.junit.Assert.assertEquals;
++import static org.junit.Assert.assertTrue;
++
++public class PrimaryKeyRestrictionSetTest
++{
++    @Test
++    public void testBoundsAsCompositesWithNoRestrictions() throws 
InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(1);
++
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++    }
++
++    /**
++     * Test 'clustering_0 = 1' with only one clustering column
++     */
++    @Test
++    public void 
testBoundsAsCompositesWithOneEqRestrictionsAndOneClusteringColumn() throws 
InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(1);
++
++        ByteBuffer clustering_0 = ByteBufferUtil.bytes(1);
++        Restriction eq = newSingleEq(cfMetaData, 0, clustering_0);
++
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(eq);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), clustering_0, EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), clustering_0, EOC.END);
++    }
++
++    /**
++     * Test 'clustering_1 = 1' with 2 clustering columns
++     */
++    @Test
++    public void 
testBoundsAsCompositesWithOneEqRestrictionsAndTwoClusteringColumns() throws 
InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(2);
++
++        ByteBuffer clustering_0 = ByteBufferUtil.bytes(1);
++        Restriction eq = newSingleEq(cfMetaData, 0, clustering_0);
++
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(eq);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), clustering_0, EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), clustering_0, EOC.END);
++    }
++
++    /**
++     * Test 'clustering_0 IN (1, 2, 3)' with only one clustering column
++     */
++    @Test
++    public void 
testBoundsAsCompositesWithOneInRestrictionsAndOneClusteringColumn() throws 
InvalidRequestException
++    {
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++        ByteBuffer value3 = ByteBufferUtil.bytes(3);
++
++        CFMetaData cfMetaData = newCFMetaData(2);
++
++        Restriction in = newSingleIN(cfMetaData, 0, value1, value2, value3);
++
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(in);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(3, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.START);
++        assertComposite(bounds.get(1), value2, EOC.START);
++        assertComposite(bounds.get(2), value3, EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(3, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.END);
++        assertComposite(bounds.get(1), value2, EOC.END);
++        assertComposite(bounds.get(2), value3, EOC.END);
++    }
++
++    /**
++     * Test slice restriction (e.g 'clustering_0 > 1') with only one 
clustering column
++     */
++    @Test
++    public void 
testBoundsAsCompositesWithSliceRestrictionsAndOneClusteringColumn() throws 
InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(1);
++
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++
++        Restriction slice = newSingleSlice(cfMetaData, 0, Bound.START, false, 
value1);
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.END);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        slice = newSingleSlice(cfMetaData, 0, Bound.START, true, value1);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.NONE);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        slice = newSingleSlice(cfMetaData, 0, Bound.END, true, value1);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.END);
++
++        slice = newSingleSlice(cfMetaData, 0, Bound.END, false, value1);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.START);
++
++        slice = newSingleSlice(cfMetaData, 0, Bound.START, false, value1);
++        Restriction slice2 = newSingleSlice(cfMetaData, 0, Bound.END, false, 
value2);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice).mergeWith(slice2);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.END);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value2, EOC.START);
++
++        slice = newSingleSlice(cfMetaData, 0, Bound.START, true, value1);
++        slice2 = newSingleSlice(cfMetaData, 0, Bound.END, true, value2);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice).mergeWith(slice2);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.NONE);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value2, EOC.END);
++    }
++
++    /**
++     * Test 'clustering_0 = 1 AND clustering_1 IN (1, 2, 3)'
++     */
++    @Test
++    public void testBoundsAsCompositesWithEqAndInRestrictions() throws 
InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(2);
++
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++        ByteBuffer value3 = ByteBufferUtil.bytes(3);
++        Restriction eq = newSingleEq(cfMetaData, 0, value1);
++        Restriction in = newSingleIN(cfMetaData, 1, value1, value2, value3);
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(eq).mergeWith(in);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(3, bounds.size());
++        assertComposite(bounds.get(0), value1, value1, EOC.START);
++        assertComposite(bounds.get(1), value1, value2, EOC.START);
++        assertComposite(bounds.get(2), value1, value3, EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(3, bounds.size());
++        assertComposite(bounds.get(0), value1, value1, EOC.END);
++        assertComposite(bounds.get(1), value1, value2, EOC.END);
++        assertComposite(bounds.get(2), value1, value3, EOC.END);
++    }
++
++    /**
++     * Test equal and slice restrictions (e.g 'clustering_0 = 0 clustering_1 
> 1')
++     */
++    @Test
++    public void testBoundsAsCompositesWithEqAndSliceRestrictions() throws 
InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(2);
++
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++        ByteBuffer value3 = ByteBufferUtil.bytes(3);
++
++        Restriction eq = newSingleEq(cfMetaData, 0, value3);
++
++        Restriction slice = newSingleSlice(cfMetaData, 1, Bound.START, false, 
value1);
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(eq).mergeWith(slice);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value3, value1, EOC.END);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value3, EOC.END);
++
++        slice = newSingleSlice(cfMetaData, 1, Bound.START, true, value1);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(eq).mergeWith(slice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value3, value1, EOC.NONE);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value3, EOC.END);
++
++        slice = newSingleSlice(cfMetaData, 1, Bound.END, true, value1);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(eq).mergeWith(slice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value3, EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value3, value1, EOC.END);
++
++        slice = newSingleSlice(cfMetaData, 1, Bound.END, false, value1);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(eq).mergeWith(slice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value3, EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value3, value1, EOC.START);
++
++        slice = newSingleSlice(cfMetaData, 1, Bound.START, false, value1);
++        Restriction slice2 = newSingleSlice(cfMetaData, 1, Bound.END, false, 
value2);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = 
restrictions.mergeWith(eq).mergeWith(slice).mergeWith(slice2);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value3, value1, EOC.END);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value3, value2, EOC.START);
++
++        slice = newSingleSlice(cfMetaData, 1, Bound.START, true, value1);
++        slice2 = newSingleSlice(cfMetaData, 1, Bound.END, true, value2);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = 
restrictions.mergeWith(eq).mergeWith(slice).mergeWith(slice2);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value3, value1, EOC.NONE);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value3, value2, EOC.END);
++    }
++
++    /**
++     * Test '(clustering_0, clustering_1) = (1, 2)' with two clustering column
++     */
++    @Test
++    public void testBoundsAsCompositesWithMultiEqRestrictions() throws 
InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(2);
++
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++        Restriction eq = newMultiEq(cfMetaData, 0, value1, value2);
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(eq);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, EOC.END);
++    }
++
++    /**
++     * Test '(clustering_0, clustering_1) IN ((1, 2), (2, 3))' with two 
clustering column
++     */
++    @Test
++    public void testBoundsAsCompositesWithMultiInRestrictions() throws 
InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(2);
++
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++        ByteBuffer value3 = ByteBufferUtil.bytes(3);
++        Restriction in = newMultiIN(cfMetaData, 0, asList(value1, value2), 
asList(value2, value3));
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(in);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(2, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, EOC.START);
++        assertComposite(bounds.get(1), value2, value3, EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(2, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, EOC.END);
++        assertComposite(bounds.get(1), value2, value3, EOC.END);
++    }
++
++    /**
++     * Test multi-column slice restrictions (e.g '(clustering_0) > (1)') with 
only one clustering column
++     */
++    @Test
++    public void 
testBoundsAsCompositesWithMultiSliceRestrictionsWithOneClusteringColumn() 
throws InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(1);
++
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++
++        Restriction slice = newMultiSlice(cfMetaData, 0, Bound.START, false, 
value1);
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.END);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        slice = newMultiSlice(cfMetaData, 0, Bound.START, true, value1);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.NONE);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        slice = newMultiSlice(cfMetaData, 0, Bound.END, true, value1);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.END);
++
++        slice = newMultiSlice(cfMetaData, 0, Bound.END, false, value1);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.START);
++
++        slice = newMultiSlice(cfMetaData, 0, Bound.START, false, value1);
++        Restriction slice2 = newMultiSlice(cfMetaData, 0, Bound.END, false, 
value2);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice).mergeWith(slice2);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.END);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value2, EOC.START);
++
++        slice = newMultiSlice(cfMetaData, 0, Bound.START, true, value1);
++        slice2 = newMultiSlice(cfMetaData, 0, Bound.END, true, value2);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice).mergeWith(slice2);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.NONE);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value2, EOC.END);
++    }
++
++    /**
++     * Test multi-column slice restrictions (e.g '(clustering_0, 
clustering_1) > (1, 2)')
++     */
++    @Test
++    public void 
testBoundsAsCompositesWithMultiSliceRestrictionsWithTwoClusteringColumn() 
throws InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(2);
++
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++
++        // (clustering_0, clustering1) > (1, 2)
++        Restriction slice = newMultiSlice(cfMetaData, 0, Bound.START, false, 
value1, value2);
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, EOC.END);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        // (clustering_0, clustering1) >= (1, 2)
++        slice = newMultiSlice(cfMetaData, 0, Bound.START, true, value1, 
value2);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, EOC.NONE);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        // (clustering_0, clustering1) <= (1, 2)
++        slice = newMultiSlice(cfMetaData, 0, Bound.END, true, value1, value2);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, EOC.END);
++
++        // (clustering_0, clustering1) < (1, 2)
++        slice = newMultiSlice(cfMetaData, 0, Bound.END, false, value1, 
value2);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertEmptyComposite(bounds.get(0));
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, EOC.START);
++
++        // (clustering_0, clustering1) > (1, 2) AND (clustering_0) < (2)
++        slice = newMultiSlice(cfMetaData, 0, Bound.START, false, value1, 
value2);
++        Restriction slice2 = newMultiSlice(cfMetaData, 0, Bound.END, false, 
value2);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice).mergeWith(slice2);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, EOC.END);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value2, EOC.START);
++
++        // (clustering_0, clustering1) >= (1, 2) AND (clustering_0, 
clustering1) <= (2, 1)
++        slice = newMultiSlice(cfMetaData, 0, Bound.START, true, value1, 
value2);
++        slice2 = newMultiSlice(cfMetaData, 0, Bound.END, true, value2, 
value1);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(slice).mergeWith(slice2);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, EOC.NONE);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value2, value1, EOC.END);
++    }
++
++    /**
++     * Test mixing single and multi equals restrictions (e.g. clustering_0 = 
1 AND (clustering_1, clustering_2) = (2, 3))
++     */
++    @Test
++    public void testBoundsAsCompositesWithSingleEqAndMultiEqRestrictions() 
throws InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(4);
++
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++        ByteBuffer value3 = ByteBufferUtil.bytes(3);
++        ByteBuffer value4 = ByteBufferUtil.bytes(4);
++
++        // clustering_0 = 1 AND (clustering_1, clustering_2) = (2, 3)
++        Restriction singleEq = newSingleEq(cfMetaData, 0, value1);
++        Restriction multiEq = newMultiEq(cfMetaData, 1, value2, value3);
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(singleEq).mergeWith(multiEq);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, EOC.END);
++
++        // clustering_0 = 1 AND clustering_1 = 2 AND (clustering_2, 
clustering_3) = (3, 4)
++        singleEq = newSingleEq(cfMetaData, 0, value1);
++        Restriction singleEq2 = newSingleEq(cfMetaData, 1, value2);
++        multiEq = newMultiEq(cfMetaData, 2, value3, value4);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = 
restrictions.mergeWith(singleEq).mergeWith(singleEq2).mergeWith(multiEq);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, value4, 
EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, value4, 
EOC.END);
++
++        // (clustering_0, clustering_1) = (1, 2) AND clustering_2 = 3
++        singleEq = newSingleEq(cfMetaData, 2, value3);
++        multiEq = newMultiEq(cfMetaData, 0, value1, value2);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(singleEq).mergeWith(multiEq);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, EOC.END);
++
++        // clustering_0 = 1 AND (clustering_1, clustering_2) = (2, 3) AND 
clustering_3 = 4
++        singleEq = newSingleEq(cfMetaData, 0, value1);
++        singleEq2 = newSingleEq(cfMetaData, 3, value4);
++        multiEq = newMultiEq(cfMetaData, 1, value2, value3);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = 
restrictions.mergeWith(singleEq).mergeWith(multiEq).mergeWith(singleEq2);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, value4, 
EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, value4, 
EOC.END);
++    }
++
++    /**
++     * Test clustering_0 = 1 AND (clustering_1, clustering_2) IN ((2, 3), (4, 
5))
++     */
++    @Test
++    public void testBoundsAsCompositesWithSingleEqAndMultiINRestrictions() 
throws InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(4);
++
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++        ByteBuffer value3 = ByteBufferUtil.bytes(3);
++        ByteBuffer value4 = ByteBufferUtil.bytes(4);
++        ByteBuffer value5 = ByteBufferUtil.bytes(5);
++
++        // clustering_0 = 1 AND (clustering_1, clustering_2) IN ((2, 3), (4, 
5))
++        Restriction singleEq = newSingleEq(cfMetaData, 0, value1);
++        Restriction multiIN = newMultiIN(cfMetaData, 1, asList(value2, 
value3), asList(value4, value5));
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(singleEq).mergeWith(multiIN);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(2, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, EOC.START);
++        assertComposite(bounds.get(1), value1, value4, value5, EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(2, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, EOC.END);
++        assertComposite(bounds.get(1), value1, value4, value5, EOC.END);
++
++        // clustering_0 = 1 AND (clustering_1, clustering_2) IN ((2, 3))
++        singleEq = newSingleEq(cfMetaData, 0, value1);
++        multiIN = newMultiIN(cfMetaData, 1, asList(value2, value3));
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(multiIN).mergeWith(singleEq);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, EOC.END);
++
++        // clustering_0 = 1 AND clustering_1 = 5 AND (clustering_2, 
clustering_3) IN ((2, 3), (4, 5))
++        singleEq = newSingleEq(cfMetaData, 0, value1);
++        Restriction singleEq2 = newSingleEq(cfMetaData, 1, value5);
++        multiIN = newMultiIN(cfMetaData, 2, asList(value2, value3), 
asList(value4, value5));
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = 
restrictions.mergeWith(singleEq).mergeWith(multiIN).mergeWith(singleEq2);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(2, bounds.size());
++        assertComposite(bounds.get(0), value1, value5, value2, value3, 
EOC.START);
++        assertComposite(bounds.get(1), value1, value5, value4, value5, 
EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(2, bounds.size());
++        assertComposite(bounds.get(0), value1, value5, value2, value3, 
EOC.END);
++        assertComposite(bounds.get(1), value1, value5, value4, value5, 
EOC.END);
++    }
++
++    /**
++     * Test mixing single equal restrictions with multi-column slice 
restrictions
++     * (e.g. clustering_0 = 1 AND (clustering_1, clustering_2) > (2, 3))
++     */
++    @Test
++    public void testBoundsAsCompositesWithSingleEqAndSliceRestrictions() 
throws InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(3);
++
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++        ByteBuffer value3 = ByteBufferUtil.bytes(3);
++        ByteBuffer value4 = ByteBufferUtil.bytes(4);
++        ByteBuffer value5 = ByteBufferUtil.bytes(5);
++
++        // clustering_0 = 1 AND (clustering_1, clustering_2) > (2, 3)
++        Restriction singleEq = newSingleEq(cfMetaData, 0, value1);
++        Restriction multiSlice = newMultiSlice(cfMetaData, 1, Bound.START, 
false, value2, value3);
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(singleEq).mergeWith(multiSlice);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, EOC.END);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, EOC.END);
++
++        // clustering_0 = 1 AND (clustering_1, clustering_2) > (2, 3) AND 
(clustering_1) < (4)
++        singleEq = newSingleEq(cfMetaData, 0, value1);
++        multiSlice = newMultiSlice(cfMetaData, 1, Bound.START, false, value2, 
value3);
++        Restriction multiSlice2 = newMultiSlice(cfMetaData, 1, Bound.END, 
false, value4);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = 
restrictions.mergeWith(multiSlice2).mergeWith(singleEq).mergeWith(multiSlice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, EOC.END);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value4, EOC.START);
++
++        // clustering_0 = 1 AND (clustering_1, clustering_2) => (2, 3) AND 
(clustering_1, clustering_2) <= (4, 5)
++        singleEq = newSingleEq(cfMetaData, 0, value1);
++        multiSlice = newMultiSlice(cfMetaData, 1, Bound.START, true, value2, 
value3);
++        multiSlice2 = newMultiSlice(cfMetaData, 1, Bound.END, true, value4, 
value5);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = 
restrictions.mergeWith(multiSlice2).mergeWith(singleEq).mergeWith(multiSlice);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, EOC.NONE);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value4, value5, EOC.END);
++    }
++
++    /**
++     * Test mixing multi equal restrictions with single-column slice 
restrictions
++     * (e.g. clustering_0 = 1 AND (clustering_1, clustering_2) > (2, 3))
++     */
++    @Test
++    public void testBoundsAsCompositesWithMultiEqAndSingleSliceRestrictions() 
throws InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(3);
++
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++        ByteBuffer value3 = ByteBufferUtil.bytes(3);
++
++        // (clustering_0, clustering_1) = (1, 2) AND clustering_2 > 3
++        Restriction multiEq = newMultiEq(cfMetaData, 0, value1, value2);
++        Restriction singleSlice = newSingleSlice(cfMetaData, 2, Bound.START, 
false, value3);
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(multiEq).mergeWith(singleSlice);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, EOC.END);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0),  value1, value2, EOC.END);
++    }
++
++    @Test
++    public void testBoundsAsCompositesWithSeveralMultiColumnRestrictions() 
throws InvalidRequestException
++    {
++        CFMetaData cfMetaData = newCFMetaData(4);
++
++        ByteBuffer value1 = ByteBufferUtil.bytes(1);
++        ByteBuffer value2 = ByteBufferUtil.bytes(2);
++        ByteBuffer value3 = ByteBufferUtil.bytes(3);
++        ByteBuffer value4 = ByteBufferUtil.bytes(4);
++        ByteBuffer value5 = ByteBufferUtil.bytes(5);
++
++        // (clustering_0, clustering_1) = (1, 2) AND (clustering_2, 
clustering_3) > (3, 4)
++        Restriction multiEq = newMultiEq(cfMetaData, 0, value1, value2);
++        Restriction multiSlice = newMultiSlice(cfMetaData, 2, Bound.START, 
false, value3, value4);
++        PrimaryKeyRestrictions restrictions = new 
PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(multiEq).mergeWith(multiSlice);
++
++        List<Composite> bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, value4, 
EOC.END);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0),  value1, value2, EOC.END);
++
++        // (clustering_0, clustering_1) = (1, 2) AND (clustering_2, 
clustering_3) IN ((3, 4), (4, 5))
++        multiEq = newMultiEq(cfMetaData, 0, value1, value2);
++        Restriction multiIN = newMultiIN(cfMetaData, 2, asList(value3, 
value4), asList(value4, value5));
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(multiEq).mergeWith(multiIN);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(2, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, value4, 
EOC.START);
++        assertComposite(bounds.get(1), value1, value2, value4, value5, 
EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(2, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, value4, 
EOC.END);
++        assertComposite(bounds.get(1), value1, value2, value4, value5, 
EOC.END);
++
++        // (clustering_0, clustering_1) = (1, 2) AND (clustering_2, 
clustering_3) = (3, 4)
++        multiEq = newMultiEq(cfMetaData, 0, value1, value2);
++        Restriction multiEq2 = newMultiEq(cfMetaData, 2, value3, value4);
++        restrictions = new PrimaryKeyRestrictionSet(cfMetaData.comparator);
++        restrictions = restrictions.mergeWith(multiEq).mergeWith(multiEq2);
++
++        bounds = restrictions.boundsAsComposites(Bound.START, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, value4, 
EOC.START);
++
++        bounds = restrictions.boundsAsComposites(Bound.END, 
QueryOptions.DEFAULT);
++        assertEquals(1, bounds.size());
++        assertComposite(bounds.get(0), value1, value2, value3, value4, 
EOC.END);
++    }
++
++    /**
++     * Asserts that the specified <code>Composite</code> is an empty one.
++     *
++     * @param composite the composite to check
++     */
++    private static void assertEmptyComposite(Composite composite)
++    {
++        assertEquals(Composites.EMPTY, composite);
++    }
++
++    /**
++     * Asserts that the specified <code>Composite</code> contains the 
specified element and the specified EOC.
++     *
++     * @param composite the composite to check
++     * @param element the expected element of the composite
++     * @param eoc the expected EOC of the composite
++     */
++    private static void assertComposite(Composite composite, ByteBuffer 
element, EOC eoc)
++    {
++        assertComposite(composite, eoc, element);
++    }
++
++    /**
++     * Asserts that the specified <code>Composite</code> contains the 2 
specified element and the specified EOC.
++     *
++     * @param composite the composite to check
++     * @param eoc the expected EOC of the composite
++     * @param elements the expected element of the composite
++     */
++    private static void assertComposite(Composite composite, ByteBuffer 
firstElement, ByteBuffer secondElement, EOC eoc)
++    {
++        assertComposite(composite, eoc, firstElement, secondElement);
++    }
++
++    /**
++     * Asserts that the specified <code>Composite</code> contains the 3 
specified element and the specified EOC.
++     *
++     * @param composite the composite to check
++     * @param firstElement the first expected element of the composite
++     * @param secondElement the second expected element of the composite
++     * @param thirdElement the third expected element of the composite
++     * @param eoc the expected EOC of the composite
++     * @param elements the expected element of the composite
++     */
++    private static void assertComposite(Composite composite,
++                                        ByteBuffer firstElement,
++                                        ByteBuffer secondElement,
++                                        ByteBuffer thirdElement,
++                                        EOC eoc)
++    {
++        assertComposite(composite, eoc, firstElement, secondElement, 
thirdElement);
++    }
++
++    /**
++     * Asserts that the specified <code>Composite</code> contains the 4 
specified element and the specified EOC.
++     *
++     * @param composite the composite to check
++     * @param firstElement the first expected element of the composite
++     * @param secondElement the second expected element of the composite
++     * @param thirdElement the third expected element of the composite
++     * @param fourthElement the fourth expected element of the composite
++     * @param eoc the expected EOC of the composite
++     * @param elements the expected element of the composite
++     */
++    private static void assertComposite(Composite composite,
++                                        ByteBuffer firstElement,
++                                        ByteBuffer secondElement,
++                                        ByteBuffer thirdElement,
++                                        ByteBuffer fourthElement,
++                                        EOC eoc)
++    {
++        assertComposite(composite, eoc, firstElement, secondElement, 
thirdElement, fourthElement);
++    }
++
++    /**
++     * Asserts that the specified <code>Composite</code> contains the 
specified elements and EOC.
++     *
++     * @param composite the composite to check
++     * @param eoc the expected EOC of the composite
++     * @param elements the expected elements of the composite
++     */
++    private static void assertComposite(Composite composite, EOC eoc, 
ByteBuffer... elements)
++    {
++        assertEquals("the composite size is not the expected one:", 
elements.length, composite.size());
++        for (int i = 0, m = elements.length; i < m; i++)
++        {
++            ByteBuffer element = elements[i];
++            assertTrue(String.format("the element %s of the composite is not 
the expected one: expected %s but was %s",
++                                     i,
++                                     ByteBufferUtil.toInt(element),
++                                     ByteBufferUtil.toInt(composite.get(i))),
++                       element.equals(composite.get(i)));
++        }
++        assertEquals("the EOC of the composite is not the expected one:", 
eoc, composite.eoc());
++    }
++
++    /**
++     * Creates a new <code>CFMetaData</code> instance.
++     *
++     * @param numberOfClusteringColumns the number of clustering column
++     * @return a new <code>CFMetaData</code> instance
++     */
++    private static CFMetaData newCFMetaData(int numberOfClusteringColumns)
++    {
++        List<AbstractType<?>> types = new ArrayList<>();
++
++        for (int i = 0; i < numberOfClusteringColumns; i++)
++            types.add(Int32Type.instance);
++
++        CompoundSparseCellNameType cType = new 
CompoundSparseCellNameType(types);
++        CFMetaData cfMetaData = new CFMetaData("keyspace", "test", 
ColumnFamilyType.Standard, cType);
++
++        for (int i = 0; i < numberOfClusteringColumns; i++)
++        {
++            ByteBuffer name = ByteBufferUtil.bytes("clustering_" + i);
++            ColumnDefinition columnDef = 
ColumnDefinition.clusteringKeyDef(cfMetaData, name, Int32Type.instance, i);
++            cfMetaData.addColumnDefinition(columnDef);
++        }
++        cfMetaData.rebuild();
++        return cfMetaData;
++    }
++
++    /**
++     * Creates a new <code>SingleColumnRestriction.EQ</code> instance for the 
specified clustering column.
++     *
++     * @param cfMetaData the column family meta data
++     * @param index the clustering column index
++     * @param value the equality value
++     * @return a new <code>SingleColumnRestriction.EQ</code> instance for the 
specified clustering column
++     */
++    private static Restriction newSingleEq(CFMetaData cfMetaData, int index, 
ByteBuffer value)
++    {
++        ColumnDefinition columnDef = 
getClusteringColumnDefinition(cfMetaData, index);
++        return new SingleColumnRestriction.EQ(columnDef, toTerm(value));
++    }
++
++    /**
++     * Creates a new <code>MultiColumnRestriction.EQ</code> instance for the 
specified clustering column.
++     *
++     * @param cfMetaData the column family meta data
++     * @param index the clustering column index
++     * @param value the equality value
++     * @return a new <code>MultiColumnRestriction.EQ</code> instance for the 
specified clustering column
++     */
++    private static Restriction newMultiEq(CFMetaData cfMetaData, int 
firstIndex, ByteBuffer... values)
++    {
++        List<ColumnDefinition> columnDefinitions = new ArrayList<>();
++        for (int i = 0; i < values.length; i++)
++        {
++            columnDefinitions.add(getClusteringColumnDefinition(cfMetaData, 
firstIndex + i));
++        }
++        return new MultiColumnRestriction.EQ(columnDefinitions, 
toMultiItemTerminal(values));
++    }
++
++    /**
++     * Creates a new <code>MultiColumnRestriction.IN</code> instance for the 
specified clustering column.
++     *
++     * @param cfMetaData the column family meta data
++     * @param firstIndex the index of the first clustering column
++     * @param values the in values
++     * @return a new <code>MultiColumnRestriction.IN</code> instance for the 
specified clustering column
++     */
++    @SafeVarargs
++    private static Restriction newMultiIN(CFMetaData cfMetaData, int 
firstIndex, List<ByteBuffer>... values)
++    {
++        List<ColumnDefinition> columnDefinitions = new ArrayList<>();
++        List<Term> terms = new ArrayList<>();
++        for (int i = 0; i < values.length; i++)
++        {
++            columnDefinitions.add(getClusteringColumnDefinition(cfMetaData, 
firstIndex + i));
++            terms.add(toMultiItemTerminal(values[i].toArray(new 
ByteBuffer[0])));
++        }
++        return new MultiColumnRestriction.InWithValues(columnDefinitions, 
terms);
++    }
++
++    /**
++     * Creates a new <code>SingleColumnRestriction.IN</code> instance for the 
specified clustering column.
++     *
++     * @param cfMetaData the column family meta data
++     * @param index the clustering column index
++     * @param values the in values
++     * @return a new <code>SingleColumnRestriction.IN</code> instance for the 
specified clustering column
++     */
++    private static Restriction newSingleIN(CFMetaData cfMetaData, int index, 
ByteBuffer... values)
++    {
++        ColumnDefinition columnDef = 
getClusteringColumnDefinition(cfMetaData, index);
++        return new SingleColumnRestriction.InWithValues(columnDef, 
toTerms(values));
++    }
++
++    /**
++     * Returns the clustering <code>ColumnDefinition</code> for the specified 
position.
++     *
++     * @param cfMetaData the column family meta data
++     * @param index the clustering column index
++     * @return the clustering <code>ColumnDefinition</code> for the specified 
position.
++     */
++    private static ColumnDefinition getClusteringColumnDefinition(CFMetaData 
cfMetaData, int index)
++    {
++        return cfMetaData.clusteringColumns().get(index);
++    }
++
++    /**
++     * Creates a new <code>SingleColumnRestriction.Slice</code> instance for 
the specified clustering column.
++     *
++     * @param cfMetaData the column family meta data
++     * @param index the clustering column index
++     * @param bound the slice bound
++     * @param inclusive <code>true</code> if the bound is inclusive
++     * @param value the bound value
++     * @return a new <code>SingleColumnRestriction.Slice</code> instance for 
the specified clustering column
++     */
++    private static Restriction newSingleSlice(CFMetaData cfMetaData, int 
index, Bound bound, boolean inclusive, ByteBuffer value)
++    {
++        ColumnDefinition columnDef = 
getClusteringColumnDefinition(cfMetaData, index);
++        return new SingleColumnRestriction.Slice(columnDef, bound, inclusive, 
toTerm(value));
++    }
++
++    /**
++     * Creates a new <code>SingleColumnRestriction.Slice</code> instance for 
the specified clustering column.
++     *
++     * @param cfMetaData the column family meta data
++     * @param index the clustering column index
++     * @param bound the slice bound
++     * @param inclusive <code>true</code> if the bound is inclusive
++     * @param value the bound value
++     * @return a new <code>SingleColumnRestriction.Slice</code> instance for 
the specified clustering column
++     */
++    private static Restriction newMultiSlice(CFMetaData cfMetaData, int 
firstIndex, Bound bound, boolean inclusive, ByteBuffer... values)
++    {
++        List<ColumnDefinition> columnDefinitions = new ArrayList<>();
++        for (int i = 0; i < values.length; i++)
++        {
++            columnDefinitions.add(getClusteringColumnDefinition(cfMetaData, i 
+ firstIndex));
++        }
++        return new MultiColumnRestriction.Slice(columnDefinitions, bound, 
inclusive, toMultiItemTerminal(values));
++    }
++
++    /**
++     * Converts the specified values into a <code>MultiItemTerminal</code>.
++     *
++     * @param values the values to convert.
++     * @return the term corresponding to the specified values.
++     */
++    private static MultiItemTerminal toMultiItemTerminal(ByteBuffer... values)
++    {
++        return new Tuples.Value(values);
++    }
++
++    /**
++     * Converts the specified value into a term.
++     *
++     * @param value the value to convert.
++     * @return the term corresponding to the specified value.
++     */
++    private static Term toTerm(ByteBuffer value)
++    {
++        return new Constants.Value(value);
++    }
++
++    /**
++     * Converts the specified values into a <code>List</code> of terms.
++     *
++     * @param values the values to convert.
++     * @return a <code>List</code> of terms corresponding to the specified 
values.
++     */
++    private static List<Term> toTerms(ByteBuffer... values)
++    {
++        List<Term> terms = new ArrayList<>();
++        for (ByteBuffer value : values)
++            terms.add(toTerm(value));
++        return terms;
++    }
++}

Reply via email to