Fix the problem with duplicated rows when using paging with SASI

Patch by Alex Petrov; reviewed by Andrés de la Peña for CASSANDRA-13302


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

Branch: refs/heads/trunk
Commit: 9723db27171c014911a8a3f2b0db9454a91dd936
Parents: f0319c8
Author: Alex Petrov <[email protected]>
Authored: Tue Apr 4 11:41:06 2017 +0200
Committer: Alex Petrov <[email protected]>
Committed: Fri May 12 09:47:16 2017 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../cassandra/index/sasi/plan/QueryPlan.java    |  3 +
 .../cassandra/index/sasi/SASICQLTest.java       | 81 ++++++++++++++++++++
 3 files changed, 85 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/9723db27/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index b13b777..3a99e6a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.11.0
+ * Fix the problem with duplicated rows when using paging with SASI 
(CASSANDRA-13302)
  * Allow CONTAINS statements filtering on the partition key and it’s parts 
(CASSANDRA-13275)
  * Fall back to even ranges calculation in clusters with vnodes when tokens 
are distributed unevenly (CASSANDRA-13229)
  * Fix duration type validation to prevent overflow (CASSANDRA-13218)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9723db27/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java 
b/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java
index 4410756..326ea0d 100644
--- a/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java
+++ b/src/java/org/apache/cassandra/index/sasi/plan/QueryPlan.java
@@ -110,6 +110,9 @@ public class QueryPlan
                     if (!keyRange.right.isMinimum() && 
keyRange.right.compareTo(key) < 0)
                         return endOfData();
 
+                    if (!keyRange.inclusiveLeft() && 
key.compareTo(keyRange.left) == 0)
+                        continue;
+
                     try (UnfilteredRowIterator partition = 
controller.getPartition(key, executionController))
                     {
                         Row staticRow = partition.staticRow();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9723db27/test/unit/org/apache/cassandra/index/sasi/SASICQLTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/index/sasi/SASICQLTest.java 
b/test/unit/org/apache/cassandra/index/sasi/SASICQLTest.java
new file mode 100644
index 0000000..efef880
--- /dev/null
+++ b/test/unit/org/apache/cassandra/index/sasi/SASICQLTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.index.sasi;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.google.common.collect.Sets;
+import org.junit.Test;
+
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.SimpleStatement;
+import junit.framework.Assert;
+import org.apache.cassandra.cql3.CQLTester;
+
+public class SASICQLTest extends CQLTester
+{
+    @Test
+    public void testPaging() throws Throwable
+    {
+        for (boolean forceFlush : new boolean[]{ false, true })
+        {
+            createTable("CREATE TABLE %s (pk int primary key, v int);");
+            createIndex("CREATE CUSTOM INDEX ON %s (v) USING 
'org.apache.cassandra.index.sasi.SASIIndex';");
+
+            for (int i = 0; i < 10; i++)
+                execute("INSERT INTO %s (pk, v) VALUES (?, ?);", i, 1);
+
+            flush(forceFlush);
+
+            Session session = sessionNet();
+            SimpleStatement stmt = new SimpleStatement("SELECT * FROM " + 
KEYSPACE + '.' + currentTable() + " WHERE v = 1");
+            stmt.setFetchSize(5);
+            List<Row> rs = session.execute(stmt).all();
+            Assert.assertEquals(10, rs.size());
+            Assert.assertEquals(Sets.newHashSet(0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
+                                rs.stream().map((i) -> 
i.getInt("pk")).collect(Collectors.toSet()));
+        }
+    }
+
+    @Test
+    public void testPagingWithClustering() throws Throwable
+    {
+        for (boolean forceFlush : new boolean[]{ false, true })
+        {
+            createTable("CREATE TABLE %s (pk int, ck int, v int, PRIMARY KEY 
(pk, ck));");
+            createIndex("CREATE CUSTOM INDEX ON %s (v) USING 
'org.apache.cassandra.index.sasi.SASIIndex';");
+
+            for (int i = 0; i < 10; i++)
+            {
+                execute("INSERT INTO %s (pk, ck, v) VALUES (?, ?, ?);", i, 1, 
1);
+                execute("INSERT INTO %s (pk, ck, v) VALUES (?, ?, ?);", i, 2, 
1);
+            }
+
+            flush(forceFlush);
+
+            Session session = sessionNet();
+            SimpleStatement stmt = new SimpleStatement("SELECT * FROM " + 
KEYSPACE + '.' + currentTable() + " WHERE v = 1");
+            stmt.setFetchSize(5);
+            List<Row> rs = session.execute(stmt).all();
+            Assert.assertEquals(20, rs.size());
+        }
+    }
+}


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

Reply via email to