From 64d8a1d9fdacf3e7396cdf2f5c61171c1c9bccf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20de=20la=20Pe=C3=B1a?= Date: Fri, 7 Apr 2017 11:13:39 +0200 Subject: [PATCH] Fix 2ndary index queries on partition keys for tables with static columns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit patch by Andrés de la Peña; reviewed by Benjamin Lerer for CASSANDRA-13147 --- CHANGES.txt | 1 + .../cql3/statements/SelectStatement.java | 18 +++++++-- .../entities/SecondaryIndexTest.java | 38 +++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 31c7b8a424..eacd275553 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.1.18 + * Fix 2ndary index queries on partition keys for tables with static columns (CASSANDRA-13147) * Fix ParseError unhashable type list in cqlsh copy from (CASSANDRA-13364) * Log stacktrace of uncaught exceptions (CASSANDRA-13108) * Remove unused repositories (CASSANDRA-13278) diff --git a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java index fe63b44995..74fb201741 100644 --- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java @@ -1368,11 +1368,11 @@ public class SelectStatement implements CQLStatement CQL3Row.RowIterator iter = cfm.comparator.CQL3RowBuilder(cfm, now).group(cells); - // If there is static columns but there is no non-static row, then provided the select was a full - // partition selection (i.e. not a 2ndary index search and there was no condition on clustering columns) - // then we want to include the static columns in the result set (and we're done). + // If there is static columns but there is no non-static row, + // and the select was a full partition selection (i.e. there was no condition on clustering or regular columns), + // we want to include the static columns in the result set (and we're done). CQL3Row staticRow = iter.getStaticRow(); - if (staticRow != null && !iter.hasNext() && !usesSecondaryIndexing && hasNoClusteringColumnsRestriction()) + if (staticRow != null && !iter.hasNext() && hasNoClusteringColumnsRestriction() && hasNoRegularColumnsRestriction()) { result.newRow(); for (ColumnDefinition def : selection.getColumns()) @@ -1452,6 +1452,16 @@ public class SelectStatement implements CQLStatement return true; } + private boolean hasNoRegularColumnsRestriction() + { + for (ColumnDefinition def : restrictedColumns.keySet()) + { + if (def.kind == ColumnDefinition.Kind.REGULAR) + return false; + } + return true; + } + private boolean needsPostQueryOrdering() { // We need post-query ordering only for queries with IN on the partition key and an ORDER BY. diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java index 4a54a9a41c..b723f60244 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/SecondaryIndexTest.java @@ -551,6 +551,29 @@ public class SecondaryIndexTest extends CQLTester succeedInsert("INSERT INTO %s (a, b, c) VALUES (0, 0, ?)", ByteBuffer.allocate(TOO_BIG)); } + @Test + public void testIndexOnPartitionKeyWithStaticColumnAndNoRows() throws Throwable + { + createTable("CREATE TABLE %s (pk1 int, pk2 int, c int, s int static, v int, PRIMARY KEY((pk1, pk2), c))"); + createIndex("CREATE INDEX ON %s (pk2)"); + execute("INSERT INTO %s (pk1, pk2, c, s, v) VALUES (?, ?, ?, ?, ?)", 1, 1, 1, 9, 1); + execute("INSERT INTO %s (pk1, pk2, c, s, v) VALUES (?, ?, ?, ?, ?)", 1, 1, 2, 9, 2); + execute("INSERT INTO %s (pk1, pk2, s) VALUES (?, ?, ?)", 2, 1, 9); + execute("INSERT INTO %s (pk1, pk2, c, s, v) VALUES (?, ?, ?, ?, ?)", 3, 1, 1, 9, 1); + + assertRows(execute("SELECT * FROM %s WHERE pk2 = ?", 1), + row(2, 1, null, 9, null), + row(1, 1, 1, 9, 1), + row(1, 1, 2, 9, 2), + row(3, 1, 1, 9, 1)); + + execute("UPDATE %s SET s=?, v=? WHERE pk1=? AND pk2=? AND c=?", 9, 1, 1, 10, 2); + assertRows(execute("SELECT * FROM %s WHERE pk2 = ?", 10), row(1, 10, 2, 9, 1)); + + execute("UPDATE %s SET s=? WHERE pk1=? AND pk2=?", 9, 1, 20); + assertRows(execute("SELECT * FROM %s WHERE pk2 = ?", 20), row(1, 20, null, 9, null)); + } + @Test public void testIndexOnClusteringColumnInsertValueOver64k() throws Throwable { @@ -781,4 +804,19 @@ public class SecondaryIndexTest extends CQLTester assertRows(execute("SELECT * FROM %s WHERE v = textAsBlob('');"), row(bytes("foo124"), EMPTY_BYTE_BUFFER)); } + + @Test + public void testIndexOnRegularColumnWithPartitionWithoutRows() throws Throwable + { + createTable("CREATE TABLE %s (pk int, c int, s int static, v int, PRIMARY KEY(pk, c))"); + createIndex("CREATE INDEX ON %s (v)"); + execute("INSERT INTO %s (pk, c, s, v) VALUES (?, ?, ?, ?)", 1, 1, 9, 1); + execute("INSERT INTO %s (pk, c, s, v) VALUES (?, ?, ?, ?)", 1, 2, 9, 2); + execute("INSERT INTO %s (pk, s) VALUES (?, ?)", 2, 9); + execute("INSERT INTO %s (pk, c, s, v) VALUES (?, ?, ?, ?)", 3, 1, 9, 1); + flush(); + execute("DELETE FROM %s WHERE pk = ? and c = ?", 3, 1); + assertRows(execute("SELECT * FROM %s WHERE v = ?", 1), + row(1, 1, 9, 1)); + } }