You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pr@cassandra.apache.org by GitBox <gi...@apache.org> on 2020/08/14 16:39:28 UTC

[GitHub] [cassandra] adelapena commented on a change in pull request #708: CASSANDRA-15977 4.0 quality testing: Read Repair

adelapena commented on a change in pull request #708:
URL: https://github.com/apache/cassandra/pull/708#discussion_r470733819



##########
File path: test/distributed/org/apache/cassandra/distributed/test/ReadRepairQueryTypesTest.java
##########
@@ -0,0 +1,1200 @@
+/*
+ * 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.distributed.test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import org.apache.cassandra.distributed.Cluster;
+import org.apache.cassandra.distributed.api.ICoordinator;
+import org.apache.cassandra.service.reads.repair.ReadRepairStrategy;
+
+import static org.apache.cassandra.distributed.api.ConsistencyLevel.ALL;
+import static org.apache.cassandra.distributed.shared.AssertUtils.*;
+import static org.apache.cassandra.utils.ByteBufferUtil.EMPTY_BYTE_BUFFER;
+
+/**
+ * Tests basic read repair functionality with different types of query types and schemas.
+ * <p>
+ * Each test verifies that its tested query triggers read repair propagating mismatched rows/columns and row/column
+ * deletions. They also verify that the selected rows and columns are propagated through read repair on missmatch,
+ * and that unselected rows/columns are not repaired.
+ * <p>
+ * The tests are parameterized for:
+ * <ul>
+ *     <li><Both {@code NONE} and {@code BLOCKING} read repair stratregies/li>
+ *     <li>Data to be repaired residing on the query coordinator or a replica</li>
+ *     <li>Data to be repaired residing on memtables or flushed to sstables</li>
+ * </ul>
+ * <p>
+ * All the included tests have a similar behaviour:
+ * <ul>
+ *     <li>Create a keyspace with RF=2 and a table</li>
+ *     <li>Insert some data in only one of the nodes</li>
+ *     <li>Run the tested read query selecting a subset of the inserted columns with CL=ALL</li>
+ *     <li>Verify that the previous read has triggered read repair propagating only the queried columns</li>
+ *     <li>Run the tested read query again but this time selecting all the columns</li>
+ *     <li>Verify that the previous read has triggered read repair propagating the rest of the queried rows</li>
+ *     <li>Delete one of the involved columns in just one node</li>
+ *     <li>Run the tested read query again but this time selecting a column different to the deleted one</li>
+ *     <li>Verify that the previous read hasn't propagated the column deletion</li>
+ *     <li>Run the tested read query again selecting all the columns</li>
+ *     <li>Verify that the previous read has triggered read repair propagating the column deletion</li>
+ *     <li>Delete one of the involved rows in just one node</li>
+ *     <li>Run the tested read query again selecting all the columns</li>
+ *     <li>Verify that the previous read has triggered read repair propagating the row deletions</li>
+ *     <li>Verify the final status of each node and drop the table</li>
+ * </ul>
+ */
+@RunWith(Parameterized.class)
+public class ReadRepairQueryTypesTest extends TestBaseImpl
+{
+    private static final boolean[] BOOLEANS = new boolean[]{ false, true };
+
+    private static Cluster cluster;
+
+    @Parameterized.Parameter
+    public ReadRepairStrategy strategy;
+
+    @Parameterized.Parameter(1)
+    public boolean flush;
+
+    @Parameterized.Parameter(2)
+    public boolean localCoordinator;
+
+    @Parameterized.Parameters(name = "{index}: strategy={0} flush={1} localCoordinator={2}")
+    public static Collection<Object[]> data()
+    {
+        List<Object[]> result = new ArrayList<>();
+        for (ReadRepairStrategy strategy : ReadRepairStrategy.values())
+            for (boolean flush : BOOLEANS)
+                for (boolean localCoordinator : BOOLEANS)
+                    result.add(new Object[]{ strategy, flush, localCoordinator });
+        return result;
+    }
+
+    @BeforeClass
+    public static void setupCluster() throws IOException
+    {
+        cluster = init(Cluster.build(2).start());
+        cluster.schemaChange(withKeyspace("CREATE TYPE %s.udt (x int, y int)"));
+    }
+
+    @AfterClass
+    public static void teardownCluster()
+    {
+        if (cluster != null)
+            cluster.close();
+    }
+
+    /**
+     * Test queries without restrictions on a table without clustering columns.
+     */
+    @Test
+    public void testUnrestrictedQueryOnSkinnyTable()
+    {
+        tester().withQueryRestriction("")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a int, b int)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (1, 10, 100)",
+                              "INSERT INTO %s (k, a, b) VALUES (2, 20, 200)")
+                .queryColumns("a",
+                              rows(row(10), row(20)),
+                              rows(row(1, 10, 100), row(2, 20, 200)),
+                              rows(row(1, 10, null), row(2, 20, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=1",
+                              "b",
+                              rows(row(100), row(200)),
+                              rows(row(1, null, 100), row(2, 20, 200)),
+                              rows(row(1, 10, 100), row(2, 20, 200)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(row(2, 20, 200)),
+                            rows(row(1, null, 100), row(2, 20, 200)))
+                .tearDown(rows(rows(row(2, 20, 200))),
+                          rows(rows(row(2, 20, 200))));
+    }
+
+    /**
+     * Test queries without restrictions on a table with clustering columns.
+     */
+    @Test
+    public void testUnrestrictedQueryOnWideTable()
+    {
+        tester().withQueryRestriction("")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (1, 10, 100, 1000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (1, 20, 200, 2000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 30, 300, 3000)")
+                .queryColumns("a",
+                              rows(row(100), row(200), row(300)),
+                              rows(row(1, 10, 100, 1000), row(1, 20, 200, 2000), row(2, 30, 300, 3000)),
+                              rows(row(1, 10, 100, null), row(1, 20, 200, null), row(2, 30, 300, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=1 AND c=20",
+                              "b",
+                              rows(row(1000), row(2000), row(3000)),
+                              rows(row(1, 10, 100, 1000), row(1, 20, null, 2000), row(2, 30, 300, 3000)),
+                              rows(row(1, 10, 100, 1000), row(1, 20, 200, 2000), row(2, 30, 300, 3000)))
+                .deleteRows("DELETE FROM %s WHERE k=1 AND c=20",
+                            rows(row(1, 10, 100, 1000), row(2, 30, 300, 3000)),
+                            rows(row(1, 10, 100, 1000), row(1, 20, null, 2000), row(2, 30, 300, 3000)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(row(2, 30, 300, 3000)),
+                            rows(row(1, 10, 100, 1000), row(2, 30, 300, 3000)))
+                .tearDown(rows(row(2, 30, 300, 3000)),
+                          rows(row(2, 30, 300, 3000)));
+    }
+
+    /**
+     * Test range queries on a table with static columns.
+     */
+    @Test
+    public void testUnrestrictedQueryWithStaticColumns()
+    {
+        tester().withQueryRestriction("")
+                .createTable("CREATE TABLE %s (k int, s1 int static, s2 int static, c int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, s1, s2) VALUES (1, 10, 100)",
+                              "INSERT INTO %s (k, c) VALUES (1, 1)",
+                              "INSERT INTO %s (k, c) VALUES (1, 2)",
+                              "INSERT INTO %s (k, s1, s2) VALUES (2, 10, 100)")
+                .queryColumns("s1",
+                              rows(row(10), row(10), row(10)),
+                              rows(row(1, 1, 10, 100), row(1, 2, 10, 100), row(2, null, 10, 100)),
+                              rows(row(1, 1, 10, null), row(1, 2, 10, null), row(2, null, 10, null)))
+                .deleteColumn("DELETE s1 FROM %s WHERE k=1",
+                              "s2",
+                              rows(row(100), row(100), row(100)),
+                              rows(row(1, 1, null, 100), row(1, 2, null, 100), row(2, null, 10, 100)),
+                              rows(row(1, 1, 10, 100), row(1, 2, 10, 100), row(2, null, 10, 100)))
+                .deleteRows("DELETE FROM %s WHERE k=1 AND c=1",
+                            rows(row(1, 2, null, 100), row(2, null, 10, 100)),
+                            rows(row(1, 1, null, 100), row(1, 2, null, 100), row(2, null, 10, 100)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(row(2, null, 10, 100)),
+                            rows(row(1, 2, null, 100), row(2, null, 10, 100)))
+                .tearDown(rows(row(2, null, 10, 100)),
+                          rows(row(2, null, 10, 100)));
+    }
+
+    /**
+     * Test queries selecting a specific row from a table without clustering columns.
+     */
+    @Test
+    public void testPointQueryOnSkinnyTable()
+    {
+        tester().withQueryRestriction("WHERE k=1")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a int, b int)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (1, 2, 3)")
+                .queryColumns("a",
+                              rows(row(2)),
+                              rows(row(1, 2, 3)),
+                              rows(row(1, 2, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=1",
+                              "b",
+                              rows(row(3)),
+                              rows(row(1, null, 3)),
+                              rows(row(1, 2, 3)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(),
+                            rows(row(1, null, 3)))
+                .tearDown();
+    }
+
+    /**
+     * Test queries selecting a specific row from a table with clustering columns.
+     */
+    @Test
+    public void testPointQueryOnWideTable()
+    {
+        tester().withQueryRestriction("WHERE k=0 AND c=2")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (0, 1, 10, 100)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (0, 2, 20, 200)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (0, 3, 30, 300)")
+                .queryColumns("a",
+                              rows(row(20)),
+                              rows(row(0, 2, 20, 200)),
+                              rows(row(0, 2, 20, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=0 AND c=2",
+                              "b",
+                              rows(row(200)),
+                              rows(row(0, 2, null, 200)),
+                              rows(row(0, 2, 20, 200)))
+                .deleteRows("DELETE FROM %s WHERE k=0 AND c=2",
+                            rows(),
+                            rows(row(0, 2, null, 200)))
+                .tearDown(rows(row(0, 1, 10, 100), row(0, 3, 30, 300)),
+                          rows());
+    }
+
+    /**
+     * Test range queries on a table without clustering columns.
+     */
+    @Test
+    public void testRangeQueryOnSkinnyTable()
+    {
+        tester().withQueryRestriction("WHERE token(k) >= token(2)")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a int, b int)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (1, 10, 100)",
+                              "INSERT INTO %s (k, a, b) VALUES (2, 20, 200)",
+                              "INSERT INTO %s (k, a, b) VALUES (3, 30, 300)")
+                .queryColumns("a",
+                              rows(row(20), row(30)),
+                              rows(row(2, 20, 200), row(3, 30, 300)),
+                              rows(row(2, 20, null), row(3, 30, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=2",
+                              "b",
+                              rows(row(200), row(300)),
+                              rows(row(2, null, 200), row(3, 30, 300)),
+                              rows(row(2, 20, 200), row(3, 30, 300)))
+                .deleteRows("DELETE FROM %s WHERE k=3",
+                            rows(row(2, null, 200)),
+                            rows(row(2, null, 200), row(3, 30, 300)))
+                .tearDown(rows(row(1, 10, 100), row(2, null, 200)),
+                          rows(row(2, null, 200)));
+    }
+
+    /**
+     * Test range queries on a table with clustering columns.
+     */
+    @Test
+    public void testRangeQueryOnWideTable()
+    {
+        tester().withQueryRestriction("WHERE token(k) >= token(2)")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (1, 10, 100, 1000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 20, 200, 2000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 21, 201, 2001)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (3, 30, 300, 3000)")
+                .queryColumns("a",
+                              rows(row(200), row(201), row(300)),
+                              rows(row(2, 20, 200, 2000), row(2, 21, 201, 2001), row(3, 30, 300, 3000)),
+                              rows(row(2, 20, 200, null), row(2, 21, 201, null), row(3, 30, 300, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=2 AND c=21",
+                              "b",
+                              rows(row(2000), row(2001), row(3000)),
+                              rows(row(2, 20, 200, 2000), row(2, 21, null, 2001), row(3, 30, 300, 3000)),
+                              rows(row(2, 20, 200, 2000), row(2, 21, 201, 2001), row(3, 30, 300, 3000)))
+                .deleteRows("DELETE FROM %s WHERE k=2 AND c=21",
+                            rows(row(2, 20, 200, 2000), row(3, 30, 300, 3000)),
+                            rows(row(2, 20, 200, 2000), row(2, 21, null, 2001), row(3, 30, 300, 3000)))
+                .deleteRows("DELETE FROM %s WHERE k=2",
+                            rows(row(3, 30, 300, 3000)),
+                            rows(row(2, 20, 200, 2000), row(3, 30, 300, 3000)))
+                .tearDown(rows(row(1, 10, 100, 1000), row(3, 30, 300, 3000)),
+                          rows(row(3, 30, 300, 3000)));
+    }
+
+    /**
+     * Test range queries without restrictions but with a limit on a table without clustering columns.
+     */
+    @Test
+    public void testRangeQueryWithLimitOnSkinnyTable()
+    {
+        tester().withQueryRestriction("WHERE token(k) >= token(1) LIMIT 2")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a int, b int)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (1, 10, 100)",
+                              "INSERT INTO %s (k, a, b) VALUES (2, 20, 200)",
+                              "INSERT INTO %s (k, a, b) VALUES (3, 30, 300)")
+                .queryColumns("a",
+                              rows(row(10), row(20)),
+                              rows(row(1, 10, 100), row(2, 20, 200)),
+                              rows(row(1, 10, null), row(2, 20, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=2",
+                              "b",
+                              rows(row(100), row(200)),
+                              rows(row(1, 10, 100), row(2, null, 200)),
+                              rows(row(1, 10, 100), row(2, 20, 200)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(row(2, null, 200), row(3, 30, 300)),
+                            rows(row(1, 10, 100), row(2, null, 200)))
+                .tearDown(rows(row(2, null, 200), row(3, 30, 300)),
+                          rows(row(2, null, 200), row(3, 30, 300)));
+    }
+
+    /**
+     * Test range queries without restrictions but with a limit on a table with clustering columns.
+     */
+    @Test
+    public void testRangeQueryWithLimitOnWideTable()
+    {
+        tester().withQueryRestriction("WHERE token(k) >= token(1) LIMIT 2")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (1, 10, 100, 1000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 20, 200, 2000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 21, 201, 2001)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (3, 30, 300, 3000)")
+                .queryColumns("a",
+                              rows(row(100), row(200)),
+                              rows(row(1, 10, 100, 1000), row(2, 20, 200, 2000)),
+                              rows(row(1, 10, 100, null), row(2, 20, 200, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=2 AND c=20",
+                              "b",
+                              rows(row(1000), row(2000)),
+                              rows(row(1, 10, 100, 1000), row(2, 20, null, 2000)),
+                              rows(row(1, 10, 100, 1000), row(2, 20, 200, 2000)))
+                .deleteRows("DELETE FROM %s WHERE k=2 AND c=20",
+                            rows(row(1, 10, 100, 1000), row(2, 21, 201, 2001)),
+                            rows(row(1, 10, 100, 1000), row(2, 20, null, 2000)))
+                .deleteRows("DELETE FROM %s WHERE k=2",
+                            rows(row(1, 10, 100, 1000), row(3, 30, 300, 3000)),
+                            rows(row(1, 10, 100, 1000), row(2, 21, 201, 2001)))
+                .tearDown(rows(row(1, 10, 100, 1000), row(3, 30, 300, 3000)),
+                          rows(row(1, 10, 100, 1000), row(3, 30, 300, 3000)));
+    }
+
+    /**
+     * Test range queries using filtering on a selected column on a table without clustering columns.
+     */
+    @Test
+    public void testRangeQueryWithFilterOnSelectedColumnOnSkinnyTable()
+    {
+        tester().withQueryRestriction("WHERE a=2 ALLOW FILTERING")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a int, b int)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (1, 2, 3)",
+                              "INSERT INTO %s (k, a, b) VALUES (10, 20, 30)")
+                .queryColumns("a",
+                              rows(row(2)),
+                              rows(row(1, 2, 3)),
+                              rows(row(1, 2, null)))
+                .deleteColumn("DELETE b FROM %s WHERE k=1",
+                              "a",
+                              rows(row(2)),
+                              rows(row(1, 2, null)),
+                              rows(row(1, 2, 3)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(),
+                            rows(row(1, 2, null)))
+                .tearDown(rows(row(10, 20, 30)),
+                          rows());
+    }
+
+    /**
+     * Test range queries using filtering on an selected column on a table with clustering columns.
+     */
+    @Test
+    public void testRangeQueryWithFilterOnSelectedColumnOnWideTable()
+    {
+        tester().withQueryRestriction("WHERE a=1 ALLOW FILTERING")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (1, 1, 1, 1)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (1, 2, 2, 2)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 1, 1, 1)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 2, 2, 2)")
+                .queryColumns("a",
+                              rows(row(1), row(1)),
+                              rows(row(1, 1, 1, 1), row(2, 1, 1, 1)),
+                              rows(row(1, 1, 1, null), row(2, 1, 1, null)))
+                .deleteColumn("DELETE b FROM %s WHERE k=1 AND c=1",
+                              "a",
+                              rows(row(1), row(1)),
+                              rows(row(1, 1, 1, null), row(2, 1, 1, 1)),
+                              rows(row(1, 1, 1, 1), row(2, 1, 1, 1)))
+                .deleteRows("DELETE FROM %s WHERE k=1 AND c=1",
+                            rows(row(2, 1, 1, 1)),
+                            rows(row(1, 1, 1, null), row(2, 1, 1, 1)))
+                .deleteRows("DELETE FROM %s WHERE k=2",
+                            rows(),
+                            rows(row(2, 1, 1, 1)))
+                .tearDown(rows(row(1, 2, 2, 2)),
+                          rows());
+    }
+
+    /**
+     * Test range queries using filtering on an unselected column on a table without clustering columns.
+     */
+    @Test
+    public void testRangeQueryWithFilterOnUnselectedColumnOnSkinnyTable()
+    {
+        tester().withQueryRestriction("WHERE b=3 ALLOW FILTERING")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a int, b int)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (1, 2, 3)",
+                              "INSERT INTO %s (k, a, b) VALUES (10, 20, 30)")
+                .queryColumns("a",
+                              rows(row(2)),
+                              rows(row(1, 2, 3)),
+                              rows(row(1, 2, 3))) // the filtered column is repaired even if it isn't selected
+                .deleteColumn("DELETE a FROM %s WHERE k=1",
+                              "b",
+                              rows(row(3)),
+                              rows(row(1, null, 3)),
+                              rows(row(1, 2, 3)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(),
+                            rows(row(1, null, 3)))
+                .tearDown(rows(row(10, 20, 30)),
+                          rows());
+    }
+
+    /**
+     * Test range queries using filtering on an unselected column on a table with clustering columns.
+     */
+    @Test
+    public void testRangeQueryWithFilterOnUnselectedColumnOnWideTable()
+    {
+        tester().withQueryRestriction("WHERE b=2 ALLOW FILTERING")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (1, 1, 1, 1)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (1, 2, 2, 2)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 1, 1, 1)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 2, 2, 2)")
+                .queryColumns("a",
+                              rows(row(2), row(2)),
+                              rows(row(1, 2, 2, 2), row(2, 2, 2, 2)),
+                              rows(row(1, 2, 2, 2), row(2, 2, 2, 2))) // the filtered column is repaired even if it isn't selected
+                .deleteColumn("DELETE a FROM %s WHERE k=1 AND c=2",
+                              "b",
+                              rows(row(2), row(2)),
+                              rows(row(1, 2, null, 2), row(2, 2, 2, 2)),
+                              rows(row(1, 2, 2, 2), row(2, 2, 2, 2)))
+                .deleteRows("DELETE FROM %s WHERE k=2 AND c=2",
+                            rows(row(1, 2, null, 2)),
+                            rows(row(1, 2, null, 2), row(2, 2, 2, 2)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(),
+                            rows(row(1, 2, null, 2)))
+                .tearDown(rows(row(2, 1, 1, 1)),
+                          rows());
+    }
+
+    /**
+     * Test slice queries without additional restrictions.
+     */
+    @Test
+    public void testSliceQuery()
+    {
+        tester().withQueryRestriction("WHERE k=0 AND c>1 AND c<4")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (0, 1, 10, 100)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (0, 2, 20, 200)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (0, 3, 30, 300)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (0, 4, 40, 400)")
+                .queryColumns("a",
+                              rows(row(20), row(30)),
+                              rows(row(0, 2, 20, 200), row(0, 3, 30, 300)),
+                              rows(row(0, 2, 20, null), row(0, 3, 30, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=0 AND c=2",
+                              "b",
+                              rows(row(200), row(300)),
+                              rows(row(0, 2, null, 200), row(0, 3, 30, 300)),
+                              rows(row(0, 2, 20, 200), row(0, 3, 30, 300)))
+                .deleteRows("DELETE FROM %s WHERE k=0 AND c=3",
+                            rows(row(0, 2, null, 200)),
+                            rows(row(0, 2, null, 200), row(0, 3, 30, 300)))
+                .deleteRows("DELETE FROM %s WHERE k=0",
+                            rows(),
+                            rows(row(0, 2, null, 200)))
+                .tearDown();
+    }
+
+    /**
+     * Test slice queries using filtering.
+     */
+    @Test
+    public void testSliceQueryWithFilter()
+    {
+        tester().withQueryRestriction("WHERE k=0 AND a>10 AND a<40 ALLOW FILTERING")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (0, 1, 10, 100)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (0, 2, 20, 200)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (0, 3, 30, 300)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (0, 4, 40, 400)")
+                .queryColumns("a",
+                              rows(row(20), row(30)),
+                              rows(row(0, 2, 20, 200), row(0, 3, 30, 300)),
+                              rows(row(0, 2, 20, null), row(0, 3, 30, null)))
+                .deleteColumn("DELETE b FROM %s WHERE k=0 AND c=2",
+                              "a",
+                              rows(row(20), row(30)),
+                              rows(row(0, 2, 20, null), row(0, 3, 30, 300)),
+                              rows(row(0, 2, 20, 200), row(0, 3, 30, 300)))
+                .deleteRows("DELETE FROM %s WHERE k=0 AND c=3",
+                            rows(row(0, 2, 20, null)),
+                            rows(row(0, 2, 20, null), row(0, 3, 30, 300)))
+                .deleteRows("DELETE FROM %s WHERE k=0",
+                            rows(),
+                            rows(row(0, 2, 20, null)))
+                .tearDown();
+    }
+
+    /**
+     * Test slice queries without restrictions but with a limit.
+     */
+    @Test
+    public void testSliceQueryWithLimit()
+    {
+        tester().withQueryRestriction("WHERE k=0 AND c>1 LIMIT 2")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (0, 1, 10, 100)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (0, 2, 20, 200)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (0, 3, 30, 300)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (0, 4, 40, 400)")
+                .queryColumns("a",
+                              rows(row(20), row(30)),
+                              rows(row(0, 2, 20, 200), row(0, 3, 30, 300)),
+                              rows(row(0, 2, 20, null), row(0, 3, 30, null)))
+                .deleteColumn("DELETE b FROM %s WHERE k=0 AND c=2",
+                              "a",
+                              rows(row(20), row(30)),
+                              rows(row(0, 2, 20, null), row(0, 3, 30, 300)),
+                              rows(row(0, 2, 20, 200), row(0, 3, 30, 300)))
+                .deleteRows("DELETE FROM %s WHERE k=0 AND c=3",
+                            rows(row(0, 2, 20, null), row(0, 4, 40, 400)),
+                            rows(row(0, 2, 20, null), row(0, 3, 30, 300)))
+                .deleteRows("DELETE FROM %s WHERE k=0",
+                            rows(),
+                            rows(row(0, 2, 20, null), row(0, 4, 40, 400)))
+                .tearDown();
+    }
+
+    /**
+     * Test slice queries on a table with static columns.
+     */
+    @Test
+    public void testSliceQueryWithStaticColumns()
+    {
+        tester().withQueryRestriction("WHERE k=0 AND c>1")
+                .createTable("CREATE TABLE %s (k int, s1 int static, s2 int static, c int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, s1, s2) VALUES (0, 10, 100)",
+                              "INSERT INTO %s (k, c) VALUES (0, 1)",
+                              "INSERT INTO %s (k, c) VALUES (0, 2)",
+                              "INSERT INTO %s (k, c) VALUES (0, 3)")
+                .queryColumns("s1,c",
+                              rows(row(10, 2), row(10, 3)),
+                              rows(row(0, 2, 10, 100), row(0, 3, 10, 100)),
+                              rows(row(0, 2, 10, null), row(0, 3, 10, null)))
+                .deleteColumn("DELETE s1 FROM %s WHERE k=0",
+                              "s2,c",
+                              rows(row(100, 2), row(100, 3)),
+                              rows(row(0, 2, null, 100), row(0, 3, null, 100)),
+                              rows(row(0, 2, 10, 100), row(0, 3, 10, 100)))
+                .deleteRows("DELETE FROM %s WHERE k=0 AND c=3",
+                            rows(row(0, 2, null, 100)),
+                            rows(row(0, 2, null, 100), row(0, 3, null, 100)))
+                .deleteRows("DELETE FROM %s WHERE k=0",
+                            rows(),
+                            rows(row(0, 2, null, 100)))
+                .tearDown();
+    }
+
+    /**
+     * Test queries with an IN restriction on a table without clustering columns.
+     */
+    @Test
+    public void testInQueryOnSkinnyTable()
+    {
+        tester().withQueryRestriction("WHERE k IN (1, 3)")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a int, b int)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (1, 10, 100)",
+                              "INSERT INTO %s (k, a, b) VALUES (2, 20, 200)",
+                              "INSERT INTO %s (k, a, b) VALUES (3, 30, 300)")
+                .queryColumns("a",
+                              rows(row(10), row(30)),
+                              rows(row(1, 10, 100), row(3, 30, 300)),
+                              rows(row(1, 10, null), row(3, 30, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=1",
+                              "b",
+                              rows(row(100), row(300)),
+                              rows(row(1, null, 100), row(3, 30, 300)),
+                              rows(row(1, 10, 100), row(3, 30, 300)))
+                .deleteRows("DELETE FROM %s WHERE k=3",
+                            rows(row(1, null, 100)),
+                            rows(row(1, null, 100), row(3, 30, 300)))
+                .tearDown(rows(row(1, null, 100), row(2, 20, 200)),
+                          rows(row(1, null, 100)));
+    }
+
+    /**
+     * Test queries with an IN restriction on a table with clustering columns.
+     */
+    @Test
+    public void testInQueryOnWideTable()
+    {
+        tester().withQueryRestriction("WHERE k IN (1, 3)")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (1, 10, 100, 1000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 20, 200, 2000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (3, 30, 300, 3000)")
+                .queryColumns("a",
+                              rows(row(100), row(300)),
+                              rows(row(1, 10, 100, 1000), row(3, 30, 300, 3000)),
+                              rows(row(1, 10, 100, null), row(3, 30, 300, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=1 AND c=10",
+                              "b",
+                              rows(row(1000), row(3000)),
+                              rows(row(1, 10, null, 1000), row(3, 30, 300, 3000)),
+                              rows(row(1, 10, 100, 1000), row(3, 30, 300, 3000)))
+                .deleteRows("DELETE FROM %s WHERE k=3",
+                            rows(row(1, 10, null, 1000)),
+                            rows(row(1, 10, null, 1000), row(3, 30, 300, 3000)))
+                .tearDown(rows(row(1, 10, null, 1000), row(2, 20, 200, 2000)),
+                          rows(row(1, 10, null, 1000)));
+    }
+
+    /**
+     * Test queries with an IN restriction and a limit on a table without clustering columns.
+     */
+    @Test
+    public void testInQueryWithLimitOnSkinnyTable()
+    {
+        tester().withQueryRestriction("WHERE k IN (1, 3) LIMIT 1")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a int, b int)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (1, 10, 100)",
+                              "INSERT INTO %s (k, a, b) VALUES (2, 20, 200)",
+                              "INSERT INTO %s (k, a, b) VALUES (3, 30, 300)")
+                .queryColumns("a",
+                              rows(row(10)),
+                              rows(row(1, 10, 100)),
+                              rows(row(1, 10, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=1",
+                              "b",
+                              rows(row(100)),
+                              rows(row(1, null, 100)),
+                              rows(row(1, 10, 100)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(row(3, 30, 300)),
+                            rows(row(1, null, 100)))
+                .tearDown(rows(row(2, 20, 200), row(3, 30, 300)),
+                          rows(row(3, 30, 300)));
+    }
+
+    /**
+     * Test queries with an IN restriction and a limit on a table with clustering columns.
+     */
+    @Test
+    public void testInQueryWithLimitOnWideTable()
+    {
+        tester().withQueryRestriction("WHERE k IN (1, 3) LIMIT 1")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (1, 10, 100, 1000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 20, 200, 2000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (3, 30, 300, 3000)")
+                .queryColumns("a",
+                              rows(row(100)),
+                              rows(row(1, 10, 100, 1000)),
+                              rows(row(1, 10, 100, null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=1 AND c=10",
+                              "b",
+                              rows(row(1000)),
+                              rows(row(1, 10, null, 1000)),
+                              rows(row(1, 10, 100, 1000)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(row(3, 30, 300, 3000)),
+                            rows(row(1, 10, null, 1000)))
+                .tearDown(rows(row(2, 20, 200, 2000), row(3, 30, 300, 3000)),
+                          rows(row(3, 30, 300, 3000)));
+    }
+
+    /**
+     * Test queries with an IN restriction and a row filter on one of the selected columns without clustering columns.
+     */
+    @Test
+    public void testInQueryWithFilterOnSelectedColumnOnSkinnyTable()
+    {
+        tester().withQueryRestriction("WHERE k IN (1, 3) AND a=10 ALLOW FILTERING")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a int, b int)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (1, 10, 100)",
+                              "INSERT INTO %s (k, a, b) VALUES (2, 10, 200)",
+                              "INSERT INTO %s (k, a, b) VALUES (3, 10, 300)",
+                              "INSERT INTO %s (k, a, b) VALUES (4, 40, 400)")
+                .queryColumns("a",
+                              rows(row(10), row(10)),
+                              rows(row(1, 10, 100), row(3, 10, 300)),
+                              rows(row(1, 10, null), row(3, 10, null)))
+                .deleteColumn("DELETE b FROM %s WHERE k=1",
+                              "a",
+                              rows(row(10), row(10)),
+                              rows(row(1, 10, null), row(3, 10, 300)),
+                              rows(row(1, 10, 100), row(3, 10, 300)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(row(3, 10, 300)),
+                            rows(row(1, 10, null), row(3, 10, 300)))
+                .tearDown(rows(row(2, 10, 200), row(4, 40, 400), row(3, 10, 300)),
+                          rows(row(3, 10, 300)));
+    }
+
+    /**
+     * Test queries with an IN restriction and a row filter on one of the selected columns with clustering columns.
+     */
+    @Test
+    public void testInQueryWithFilterOnSelectedColumnOnWideTable()
+    {
+        tester().withQueryRestriction("WHERE k IN (1, 3) AND a=100 ALLOW FILTERING")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (1, 10, 100, 1000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 20, 100, 2000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (3, 30, 100, 3000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (4, 40, 400, 4000)")
+                .queryColumns("a",
+                              rows(row(100), row(100)),
+                              rows(row(1, 10, 100, 1000), row(3, 30, 100, 3000)),
+                              rows(row(1, 10, 100, null), row(3, 30, 100, null)))
+                .deleteColumn("DELETE b FROM %s WHERE k=1 AND c=10",
+                              "a",
+                              rows(row(100), row(100)),
+                              rows(row(1, 10, 100, null), row(3, 30, 100, 3000)),
+                              rows(row(1, 10, 100, 1000), row(3, 30, 100, 3000)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(row(3, 30, 100, 3000)),
+                            rows(row(1, 10, 100, null), row(3, 30, 100, 3000)))
+                .tearDown(rows(row(2, 20, 100, 2000), row(4, 40, 400, 4000), row(3, 30, 100, 3000)),
+                          rows(row(3, 30, 100, 3000)));
+    }
+
+    /**
+     * Test queries with an IN restriction and a row filter on unselected columns without clustering columns.
+     */
+    @Test
+    public void testInQueryWithFilterOnUnselectedColumnOnSkinnyTable()
+    {
+        tester().withQueryRestriction("WHERE k IN (1, 3) AND b=100 ALLOW FILTERING")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a int, b int)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (1, 10, 100)",
+                              "INSERT INTO %s (k, a, b) VALUES (2, 20, 100)",
+                              "INSERT INTO %s (k, a, b) VALUES (3, 30, 100)")
+                .queryColumns("a",
+                              rows(row(10), row(30)),
+                              rows(row(1, 10, 100), row(3, 30, 100)),
+                              rows(row(1, 10, 100), row(3, 30, 100))) // the filtered column is repaired even if it isn't selected
+                .deleteColumn("DELETE a FROM %s WHERE k=1",
+                              "b",
+                              rows(row(100), row(100)),
+                              rows(row(1, null, 100), row(3, 30, 100)),
+                              rows(row(1, 10, 100), row(3, 30, 100)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(row(3, 30, 100)),
+                            rows(row(1, null, 100), row(3, 30, 100)))
+                .tearDown(rows(row(2, 20, 100), row(3, 30, 100)),
+                          rows(row(3, 30, 100)));
+    }
+
+    /**
+     * Test queries with an IN restriction and a row filter on unselected columns with clustering columns.
+     */
+    @Test
+    public void testInQueryWithFilterOnUnselectedColumnOnWideTable()
+    {
+        tester().withQueryRestriction("WHERE k IN (1, 3) AND b=1000 ALLOW FILTERING")
+                .createTable("CREATE TABLE %s (k int, c int, a int, b int, PRIMARY KEY(k, c))")
+                .populateNode("INSERT INTO %s (k, c, a, b) VALUES (1, 10, 100, 1000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (2, 20, 200, 2000)",
+                              "INSERT INTO %s (k, c, a, b) VALUES (3, 30, 300, 3000)")
+                .queryColumns("a",
+                              rows(row(100)),
+                              rows(row(1, 10, 100, 1000)),
+                              rows(row(1, 10, 100, 1000))) // the filtered column is repaired even if it isn't selected
+                .deleteColumn("DELETE a FROM %s WHERE k=1 AND c=10",
+                              "b",
+                              rows(row(1000)),
+                              rows(row(1, 10, null, 1000)),
+                              rows(row(1, 10, 100, 1000)))
+                .deleteRows("DELETE FROM %s WHERE k=1",
+                            rows(),
+                            rows(row(1, 10, null, 1000)))
+                .tearDown(rows(row(2, 20, 200, 2000), row(3, 30, 300, 3000)),
+                          rows());
+    }
+
+    /**
+     * Test unrestricted queries with frozen tuples.
+     */
+    @Test
+    public void testTuple()
+    {
+        tester().withQueryRestriction("")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a tuple<int,int>, b tuple<int,int>)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (0, (1, 2), (3, 4))")
+                .queryColumns("a",
+                              rows(row(tuple(1, 2))),
+                              rows(row(0, tuple(1, 2), tuple(3, 4))),
+                              rows(row(0, tuple(1, 2), null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=0",
+                              "b",
+                              rows(row(tuple(3, 4))),
+                              rows(row(0, null, tuple(3, 4))),
+                              rows(row(0, tuple(1, 2), tuple(3, 4))))
+                .deleteRows("DELETE FROM %s WHERE k=0",
+                            rows(),
+                            rows(row(0, null, tuple(3, 4))))
+                .tearDown();
+    }
+
+    /**
+     * Test unrestricted queries with frozen sets.
+     */
+    @Test
+    public void testFrozenSet()
+    {
+        tester().withQueryRestriction("")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a frozen<set<int>>, b frozen<set<int>>)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (0, {1, 2}, {3, 4})")
+                .queryColumns("a[1]",
+                              rows(row(1)),
+                              rows(row(0, set(1, 2), set(3, 4))),
+                              rows(row(0, set(1, 2), null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=0",
+                              "b[4]",
+                              rows(row(4)),
+                              rows(row(0, null, set(3, 4))),
+                              rows(row(0, set(1, 2), set(3, 4))))
+                .deleteRows("DELETE FROM %s WHERE k=0",
+                            rows(),
+                            rows(row(0, null, set(3, 4))))
+                .tearDown();
+    }
+
+    /**
+     * Test unrestricted queries with frozen lists.
+     */
+    @Test
+    public void testFrozenList()
+    {
+        tester().withQueryRestriction("")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a frozen<list<int>>, b frozen<list<int>>)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (0, [1, 2], [3, 4])")
+                .queryColumns("a",
+                              rows(row(list(1, 2))),
+                              rows(row(0, list(1, 2), list(3, 4))),
+                              rows(row(0, list(1, 2), null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=0",
+                              "b",
+                              rows(row(list(3, 4))),
+                              rows(row(0, null, list(3, 4))),
+                              rows(row(0, list(1, 2), list(3, 4))))
+                .deleteRows("DELETE FROM %s WHERE k=0",
+                            rows(),
+                            rows(row(0, null, list(3, 4))))
+                .tearDown();
+    }
+
+    /**
+     * Test unrestricted queries with frozen maps.
+     */
+    @Test
+    public void testFrozenMap()
+    {
+        tester().withQueryRestriction("")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a frozen<map<int,int>>, b frozen<map<int,int>>)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (0, {1:10, 2:20}, {3:30, 4:40})")
+                .queryColumns("a[2]",
+                              rows(row(20)),
+                              rows(row(0, map(1, 10, 2, 20), map(3, 30, 4, 40))),
+                              rows(row(0, map(1, 10, 2, 20), null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=0",
+                              "b[4]",
+                              rows(row(40)),
+                              rows(row(0, null, map(3, 30, 4, 40))),
+                              rows(row(0, map(1, 10, 2, 20), map(3, 30, 4, 40))))
+                .deleteRows("DELETE FROM %s WHERE k=0",
+                            rows(),
+                            rows(row(0, null, map(3, 30, 4, 40))))
+                .tearDown();
+    }
+
+    /**
+     * Test unrestricted queries with frozen user-defined types.
+     */
+    @Test
+    public void testFrozenUDT()
+    {
+        tester().withQueryRestriction("")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a frozen<udt>, b frozen<udt>)")
+                .populateNode("INSERT INTO %s (k, a, b) VALUES (0, {x:1, y:2}, {x:3, y:4})")
+                .queryColumns("a.x",
+                              rows(row(1)),
+                              rows(row(0, udt("x", 1, "y", 2), udt("x", 3, "y", 4))),
+                              rows(row(0, udt("x", 1, "y", 2), null)))
+                .deleteColumn("DELETE a FROM %s WHERE k=0",
+                              "b.y",
+                              rows(row(4)),
+                              rows(row(0, null, udt("x", 3, "y", 4))),
+                              rows(row(0, udt("x", 1, "y", 2), udt("x", 3, "y", 4))))
+                .deleteRows("DELETE FROM %s WHERE k=0",
+                            rows(),
+                            rows(row(0, null, udt("x", 3, "y", 4))))
+                .tearDown();
+    }
+
+    /**
+     * Test unrestricted queries with non-frozen sets.
+     */
+    @Test
+    public void testNonFrozenSet()
+    {
+        tester().withQueryRestriction("")
+                .createTable("CREATE TABLE %s (k int PRIMARY KEY, a set<int>, b set<int>, c int)")
+                .populateNode("INSERT INTO %s (k, a, b, c) VALUES (0, {1, 2}, {3, 4}, 10)")
+                .queryColumns("a[1]",
+                              rows(row(1)),
+                              rows(row(0, set(1, 2), set(3, 4), 10)),
+                              rows(row(0, set(1), set(3, 4), null))) // unselected 'b' is repaired, see CASSANDRA-10657

Review comment:
       @maedhroz here the complex column `b` is read-repaired even though it's not selected by the query. This happens in [`ColumnFilter#fetchedCellIsQueried`](https://github.com/apache/cassandra/blob/474de80de5179e51fcc5b125c94ef68111c63c90/src/java/org/apache/cassandra/db/filter/ColumnFilter.java#L240-L242) since at least CASSANDRA-10657. The same happens for other complex column types below. Not sure this repair is necessary, but at least it doesn't seem to break anything, so we could take a closer look at it on a followup ticket, as a performance improvement.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



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