diff --git a/CHANGES.txt b/CHANGES.txt index 52f8ccf1e7..67b5824ce4 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -21,6 +21,7 @@ * cqlsh: Fix handling of $$-escaped strings (CASSANDRA-12189) * Fix SSL JMX requiring truststore containing server cert (CASSANDRA-12109) Merged from 3.0: + * AssertionError with MVs on updating a row that isn't indexed due to a null value (CASSANDRA-12247) * Disable RR and speculative retry with EACH_QUORUM reads (CASSANDRA-11980) * Add option to override compaction space check (CASSANDRA-12180) * Faster startup by only scanning each directory for temporary files once (CASSANDRA-12114) diff --git a/src/java/org/apache/cassandra/db/view/ViewUpdateGenerator.java b/src/java/org/apache/cassandra/db/view/ViewUpdateGenerator.java index 12eb47416a..21613635ac 100644 --- a/src/java/org/apache/cassandra/db/view/ViewUpdateGenerator.java +++ b/src/java/org/apache/cassandra/db/view/ViewUpdateGenerator.java @@ -190,7 +190,7 @@ public class ViewUpdateGenerator // If the update didn't modified this column, the cells will be the same object so it's worth checking if (before == after) - return before == null ? UpdateAction.NONE : UpdateAction.UPDATE_EXISTING; + return isLive(before) ? UpdateAction.UPDATE_EXISTING : UpdateAction.NONE; if (!isLive(before)) return isLive(after) ? UpdateAction.NEW_ENTRY : UpdateAction.NONE; @@ -451,7 +451,7 @@ public class ViewUpdateGenerator ColumnDefinition baseColumn = view.baseNonPKColumnsInViewPK.get(0); Cell cell = baseRow.getCell(baseColumn); - assert isLive(cell) : "We shouldn't have got there is the base row had no associated entry"; + assert isLive(cell) : "We shouldn't have got there if the base row had no associated entry"; long timestamp = Math.max(baseLiveness.timestamp(), cell.timestamp()); return LivenessInfo.withExpirationTime(timestamp, cell.ttl(), cell.localDeletionTime()); diff --git a/test/unit/org/apache/cassandra/cql3/ViewTest.java b/test/unit/org/apache/cassandra/cql3/ViewTest.java index 85f01a6de5..c9ef401e23 100644 --- a/test/unit/org/apache/cassandra/cql3/ViewTest.java +++ b/test/unit/org/apache/cassandra/cql3/ViewTest.java @@ -1108,4 +1108,33 @@ public class ViewTest extends CQLTester } } + + @Test + public void testNullInClusteringColumns() throws Throwable + { + createTable("CREATE TABLE %s (id1 int, id2 int, v1 text, v2 text, PRIMARY KEY (id1, id2))"); + + executeNet(protocolVersion, "USE " + keyspace()); + + createView("mv", + "CREATE MATERIALIZED VIEW %s AS" + + " SELECT id1, v1, id2, v2" + + " FROM %%s" + + " WHERE id1 IS NOT NULL AND v1 IS NOT NULL AND id2 IS NOT NULL" + + " PRIMARY KEY (id1, v1, id2)" + + " WITH CLUSTERING ORDER BY (v1 DESC, id2 ASC)"); + + execute("INSERT INTO %s (id1, id2, v1, v2) VALUES (?, ?, ?, ?)", 0, 1, "foo", "bar"); + + assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM %s"), row(0, 1, "foo", "bar")); + assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM mv"), row(0, "foo", 1, "bar")); + + executeNet(protocolVersion, "UPDATE %s SET v1=? WHERE id1=? AND id2=?", null, 0, 1); + assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM %s"), row(0, 1, null, "bar")); + assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM mv")); + + executeNet(protocolVersion, "UPDATE %s SET v2=? WHERE id1=? AND id2=?", "rab", 0, 1); + assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM %s"), row(0, 1, null, "rab")); + assertRowsNet(protocolVersion, executeNet(protocolVersion, "SELECT * FROM mv")); + } }