From 8d020e25c0bc9dc7e0d0201974d16ba72381172e Mon Sep 17 00:00:00 2001 From: Sylvain Lebresne Date: Mon, 25 Jul 2016 16:35:33 +0200 Subject: [PATCH] AssertionError with MVs on updating a row that isn't indexed due to a null value patch by Sylvain Lebresne; reviewed by Carl Yeksigian for CASSANDRA-12247 --- CHANGES.txt | 1 + .../db/view/ViewUpdateGenerator.java | 4 +-- .../org/apache/cassandra/cql3/ViewTest.java | 29 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 3c485dd1e3..90f1ee9eee 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.0.9 + * 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 af025cb69e..3bdc380cda 100644 --- a/src/java/org/apache/cassandra/db/view/ViewUpdateGenerator.java +++ b/src/java/org/apache/cassandra/db/view/ViewUpdateGenerator.java @@ -191,7 +191,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; @@ -452,7 +452,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.create(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")); + } }