cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From slebre...@apache.org
Subject git commit: Fix error when doing reverse queries with static columns
Date Wed, 09 Jul 2014 16:22:15 GMT
Repository: cassandra
Updated Branches:
  refs/heads/cassandra-2.0 a14211fbd -> 6893130e8


Fix error when doing reverse queries with static columns

patch by graham sanderson; reviewed by slebresne for CASSANDRA-7490


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/6893130e
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/6893130e
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/6893130e

Branch: refs/heads/cassandra-2.0
Commit: 6893130e899f1c9968e49eb58bf8d81212fc3157
Parents: a14211f
Author: Sylvain Lebresne <sylvain@datastax.com>
Authored: Wed Jul 9 15:50:17 2014 +0200
Committer: Sylvain Lebresne <sylvain@datastax.com>
Committed: Wed Jul 9 15:50:17 2014 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../cql3/statements/SelectStatement.java        |  17 +-
 ...QueryFilterWithStaticColumnsPresentTest.java | 357 +++++++++++++++++++
 3 files changed, 370 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/6893130e/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 23be338..3553e4a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -10,6 +10,7 @@
    (CASSANDRA-7455)
  * Add inter_dc_stream_throughput_outbound_megabits_per_sec (CASSANDRA-6596)
  * Add option to disable STCS in L0 (CASSANDRA-6621)
+ * Fix error when doing reversed queries with static columns (CASSANDRA-7490)
 Merged from 1.2:
 
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/6893130e/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
index 98bd99a..523302f 100644
--- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
@@ -472,10 +472,17 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
                 if (slice.isAlwaysEmpty(cfDef.cfm.comparator, isReversed))
                     return staticSlice == null ? null : sliceFilter(staticSlice, limit, toGroup);
 
-                return staticSlice == null
-                     ? sliceFilter(slice, limit, toGroup)
-                     : (slice.includes(cfDef.cfm.comparator, staticSlice.finish) ? sliceFilter(new
ColumnSlice(staticSlice.start, slice.finish), limit, toGroup)
-                                                                                 : sliceFilter(new
ColumnSlice[]{ staticSlice, slice }, limit, toGroup));
+                if (staticSlice == null)
+                    return sliceFilter(slice, limit, toGroup);
+
+                if (isReversed)
+                    return slice.includes(cfDef.cfm.comparator.reverseComparator, staticSlice.start)
+                            ? sliceFilter(new ColumnSlice(slice.start, staticSlice.finish),
limit, toGroup)
+                            : sliceFilter(new ColumnSlice[]{ slice, staticSlice }, limit,
toGroup);
+                else
+                    return slice.includes(cfDef.cfm.comparator, staticSlice.finish)
+                            ? sliceFilter(new ColumnSlice(staticSlice.start, slice.finish),
limit, toGroup)
+                            : sliceFilter(new ColumnSlice[]{ staticSlice, slice }, limit,
toGroup);
             }
 
             List<ColumnSlice> l = new ArrayList<ColumnSlice>(startBounds.size());
@@ -497,7 +504,7 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
             ColumnSlice[] slices;
             if (isReversed)
             {
-                if (l.get(l.size() - 1).includes(cfDef.cfm.comparator, staticSlice.start))
+                if (l.get(l.size() - 1).includes(cfDef.cfm.comparator.reverseComparator,
staticSlice.start))
                 {
                     slices = l.toArray(new ColumnSlice[l.size()]);
                     slices[slices.length-1] = new ColumnSlice(slices[slices.length-1].start,
ByteBufferUtil.EMPTY_BYTE_BUFFER);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/6893130e/test/unit/org/apache/cassandra/cql3/SliceQueryFilterWithStaticColumnsPresentTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/SliceQueryFilterWithStaticColumnsPresentTest.java
b/test/unit/org/apache/cassandra/cql3/SliceQueryFilterWithStaticColumnsPresentTest.java
new file mode 100644
index 0000000..a21ebdc
--- /dev/null
+++ b/test/unit/org/apache/cassandra/cql3/SliceQueryFilterWithStaticColumnsPresentTest.java
@@ -0,0 +1,357 @@
+package org.apache.cassandra.cql3;
+
+import org.apache.cassandra.SchemaLoader;
+import org.apache.cassandra.db.ConsistencyLevel;
+import org.apache.cassandra.db.marshal.*;
+import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.exceptions.RequestExecutionException;
+import org.apache.cassandra.exceptions.RequestValidationException;
+import org.apache.cassandra.exceptions.SyntaxException;
+import org.apache.cassandra.gms.Gossiper;
+import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.service.QueryState;
+import org.apache.cassandra.transport.messages.ResultMessage;
+import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.MD5Digest;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.ByteBuffer;
+import java.util.*;
+
+import static org.apache.cassandra.cql3.QueryProcessor.process;
+import static org.apache.cassandra.cql3.QueryProcessor.processInternal;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static com.google.common.collect.Lists.newArrayList;
+import static org.junit.Assert.fail;
+
+/**
+ * Test column ranges and ordering with static column in table
+ */
+public class SliceQueryFilterWithStaticColumnsPresentTest
+{
+    static ClientState clientState;
+    static String keyspace = "static_column_slice_test";
+
+    @BeforeClass
+    public static void setUpClass() throws Throwable
+    {
+        SchemaLoader.loadSchema();
+        executeSchemaChange("CREATE KEYSPACE IF NOT EXISTS %s WITH replication = {'class':
'SimpleStrategy', 'replication_factor': '1'}");
+        executeSchemaChange("CREATE TABLE IF NOT EXISTS %s.single_clustering (p text, c text,
v text, s text static, PRIMARY KEY (p, c));");
+        executeSchemaChange("CREATE TABLE IF NOT EXISTS %s.single_clustering_reversed (p
text, c text, v text, s text static, PRIMARY KEY (p, c)) WITH CLUSTERING ORDER BY (c DESC);");
+        execute("INSERT INTO %s.single_clustering (p, c, v, s) values ('p1', 'k1', 'v1',
'sv1')");
+        execute("INSERT INTO %s.single_clustering (p, c, v) values ('p1', 'k2', 'v2')");
+        execute("INSERT INTO %s.single_clustering (p, s) values ('p2', 'sv2')");
+        execute("INSERT INTO %s.single_clustering_reversed (p, c, v, s) values ('p1', 'k1',
'v1', 'sv1')");
+        execute("INSERT INTO %s.single_clustering_reversed (p, c, v) values ('p1', 'k2',
'v2')");
+        execute("INSERT INTO %s.single_clustering_reversed (p, s) values ('p2', 'sv2')");
+        clientState = ClientState.forInternalCalls();
+    }
+
+    @AfterClass
+    public static void stopGossiper()
+    {
+        Gossiper.instance.stop();
+    }
+
+    private static void executeSchemaChange(String query) throws Throwable
+    {
+        try
+        {
+            process(String.format(query, keyspace), ConsistencyLevel.ONE);
+        } catch (RuntimeException exc)
+        {
+            throw exc.getCause();
+        }
+    }
+
+    private static UntypedResultSet execute(String query) throws Throwable
+    {
+        try
+        {
+            return processInternal(String.format(query, keyspace));
+        } catch (RuntimeException exc)
+        {
+            if (exc.getCause() != null)
+                throw exc.getCause();
+            throw exc;
+        }
+    }
+
+    @Test
+    public void testNoClusteringColumnDefaultOrdering() throws Throwable
+    {
+        UntypedResultSet results = execute("SELECT * FROM %s.single_clustering WHERE p='p1'");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+        checkRow(1, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p2'");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p2", null, "sv2", null);
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1'");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+        checkRow(1, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p2'");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p2", null, "sv2", null);
+    }
+
+    @Test
+    public void testNoClusteringColumnAscending() throws Throwable
+    {
+        UntypedResultSet results = execute("SELECT * FROM %s.single_clustering WHERE p='p1'
ORDER BY c ASC");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+        checkRow(1, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p2' ORDER BY c ASC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p2", null, "sv2", null);
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' ORDER
BY c ASC");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+        checkRow(1, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p2' ORDER
BY c ASC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p2", null, "sv2", null);
+    }
+
+    @Test
+    public void testNoClusteringColumnDescending() throws Throwable
+    {
+        UntypedResultSet results = execute("SELECT * FROM %s.single_clustering WHERE p='p1'
ORDER BY c DESC");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+        checkRow(1, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p2' ORDER BY c DESC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p2", null, "sv2", null);
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' ORDER
BY c DESC");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+        checkRow(1, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p2' ORDER
BY c DESC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p2", null, "sv2", null);
+    }
+
+    @Test
+    public void testSingleRelationDefaultOrdering() throws Throwable
+    {
+        UntypedResultSet results = execute("SELECT * FROM %s.single_clustering WHERE p='p1'
AND c>='k1'");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+        checkRow(1, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c>='k2'");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c>='k3'");
+        assertEquals(0, results.size());
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c ='k1'");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c<='k1'");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c<='k0'");
+        assertEquals(0, results.size());
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c>='k1'");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+        checkRow(1, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c>='k2'");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c>='k3'");
+        assertEquals(0, results.size());
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c='k1'");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c<='k1'");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c<='k0'");
+        assertEquals(0, results.size());
+    }
+
+    @Test
+    public void testSingleRelationAscending() throws Throwable
+    {
+        UntypedResultSet results = execute("SELECT * FROM %s.single_clustering WHERE p='p1'
AND c>='k1' ORDER BY c ASC");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+        checkRow(1, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c>='k2'
ORDER BY c ASC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c>='k3'
ORDER BY c ASC");
+        assertEquals(0, results.size());
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c ='k1' ORDER
BY c ASC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c<='k1'
ORDER BY c ASC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c<='k0'
ORDER BY c ASC");
+        assertEquals(0, results.size());
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c>='k1'
ORDER BY c ASC");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+        checkRow(1, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c>='k2'
ORDER BY c ASC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c>='k3'
ORDER BY c ASC");
+        assertEquals(0, results.size());
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c='k1'
ORDER BY c ASC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c<='k1'
ORDER BY c ASC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c<='k0'
ORDER BY c ASC");
+        assertEquals(0, results.size());
+    }
+
+    @Test
+    public void testSingleRelationDescending() throws Throwable
+    {
+        UntypedResultSet results = execute("SELECT * FROM %s.single_clustering WHERE p='p1'
AND c>='k1' ORDER BY c DESC");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+        checkRow(1, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c>='k2'
ORDER BY c DESC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c>='k3'
ORDER BY c DESC");
+        assertEquals(0, results.size());
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c ='k1' ORDER
BY c DESC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c<='k1'
ORDER BY c DESC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering WHERE p='p1' AND c<='k0'
ORDER BY c DESC");
+        assertEquals(0, results.size());
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c>='k1'
ORDER BY c DESC");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+        checkRow(1, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c>='k2'
ORDER BY c DESC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c>='k3'
ORDER BY c DESC");
+        assertEquals(0, results.size());
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c='k1'
ORDER BY c DESC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c<='k1'
ORDER BY c DESC");
+        assertEquals(1, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c<='k0'
ORDER BY c DESC");
+        assertEquals(0, results.size());
+    }
+
+    @Test
+    public void testInDefaultOrdering() throws Throwable
+    {
+        UntypedResultSet results = execute("SELECT * FROM %s.single_clustering WHERE p='p1'
AND c IN ('k1', 'k2')");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+        checkRow(1, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c
IN ('k1', 'k2')");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+        checkRow(1, results, "p1", "k1", "sv1", "v1");
+    }
+
+    @Test
+    public void testInAscending() throws Throwable
+    {
+        UntypedResultSet results = execute("SELECT * FROM %s.single_clustering WHERE p='p1'
AND c IN ('k1', 'k2') ORDER BY c ASC");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+        checkRow(1, results, "p1", "k2", "sv1", "v2");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c
IN ('k1', 'k2') ORDER BY c ASC");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k1", "sv1", "v1");
+        checkRow(1, results, "p1", "k2", "sv1", "v2");
+    }
+
+    @Test
+    public void testInDescending() throws Throwable
+    {
+        UntypedResultSet results = execute("SELECT * FROM %s.single_clustering WHERE p='p1'
AND c IN ('k1', 'k2') ORDER BY c DESC");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+        checkRow(1, results, "p1", "k1", "sv1", "v1");
+
+        results = execute("SELECT * FROM %s.single_clustering_reversed WHERE p='p1' AND c
IN ('k1', 'k2') ORDER BY c DESC");
+        assertEquals(2, results.size());
+        checkRow(0, results, "p1", "k2", "sv1", "v2");
+        checkRow(1, results, "p1", "k1", "sv1", "v1");
+    }
+
+    private static void checkRow(int rowIndex, UntypedResultSet results, String... expectedValues)
+    {
+        List<UntypedResultSet.Row> rows = newArrayList(results.iterator());
+        UntypedResultSet.Row row = rows.get(rowIndex);
+        Iterator<ColumnSpecification> columns = row.getColumns().iterator();
+        for (String expected : expectedValues)
+        {
+            String columnName = columns.next().name.toString();
+            String actual = row.has(columnName) ? row.getString(columnName) : null;
+            assertEquals(String.format("Expected value %s for column %s in row %d, but got
%s", actual, columnName, rowIndex, expected),
+                    expected, actual);
+        }
+    }
+}


Mime
View raw message