This is an automated email from the ASF dual-hosted git repository. bereng pushed a commit to branch cassandra-4.0 in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/cassandra-4.0 by this push: new 6d16a53 Flaky ViewTest patch by Berenguer Blasi; reviewed by Andres de la Peña for CASSANDRA-16777 new ba0f622 Merge branch 'cassandra-4.0.0' into cassandra-4.0 6d16a53 is described below commit 6d16a531b1b4b3d63dfa182cd8484fb4d9e93c86 Author: Bereng <berenguerbl...@gmail.com> AuthorDate: Thu Jul 1 07:52:46 2021 +0200 Flaky ViewTest patch by Berenguer Blasi; reviewed by Andres de la Peña for CASSANDRA-16777 --- .../apache/cassandra/cql3/ViewAbstractTest.java | 108 +++ .../unit/org/apache/cassandra/cql3/ViewPKTest.java | 461 +++++++++++ .../org/apache/cassandra/cql3/ViewRangesTest.java | 197 +++++ test/unit/org/apache/cassandra/cql3/ViewTest.java | 917 +-------------------- .../org/apache/cassandra/cql3/ViewTimesTest.java | 300 +++++++ 5 files changed, 1076 insertions(+), 907 deletions(-) diff --git a/test/unit/org/apache/cassandra/cql3/ViewAbstractTest.java b/test/unit/org/apache/cassandra/cql3/ViewAbstractTest.java new file mode 100644 index 0000000..bbd21dc --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/ViewAbstractTest.java @@ -0,0 +1,108 @@ +/* + * 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.cql3; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; + +import com.datastax.driver.core.exceptions.OperationTimedOutException; +import org.apache.cassandra.concurrent.Stage; +import org.awaitility.Awaitility; + +@Ignore +public abstract class ViewAbstractTest extends CQLTester +{ + protected final List<String> views = new ArrayList<>(); + + @BeforeClass + public static void startup() + { + requireNetwork(); + } + + @Before + public void begin() + { + begin(views); + } + + private static void begin(List<String> views) + { + views.clear(); + } + + @After + public void end() throws Throwable + { + end(views, this); + } + + private static void end(List<String> views, CQLTester tester) throws Throwable + { + for (String viewName : views) + tester.executeNet("DROP MATERIALIZED VIEW " + viewName); + } + + protected void createView(String name, String query) throws Throwable + { + createView(name, query, views, this); + } + + private static void createView(String name, String query, List<String> views, CQLTester tester) throws Throwable + { + try + { + tester.executeNet(String.format(query, name)); + // If exception is thrown, the view will not be added to the list; since it shouldn't have been created, this is + // the desired behavior + views.add(name); + } + catch (OperationTimedOutException ex) + { + // ... except for timeout, when we actually do not know whether the view was created or not + views.add(name); + throw ex; + } + } + + protected void updateView(String query, Object... params) throws Throwable + { + updateView(query, this, params); + } + + private static void updateView(String query, CQLTester tester, Object... params) throws Throwable + { + tester.executeNet(query, params); + waitForViewMutations(); + } + + protected static void waitForViewMutations() + { + Awaitility.await() + .atMost(5, TimeUnit.MINUTES) + .until(() -> Stage.VIEW_MUTATION.executor().getPendingTaskCount() == 0 + && Stage.VIEW_MUTATION.executor().getActiveTaskCount() == 0); + } +} diff --git a/test/unit/org/apache/cassandra/cql3/ViewPKTest.java b/test/unit/org/apache/cassandra/cql3/ViewPKTest.java new file mode 100644 index 0000000..06664cb --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/ViewPKTest.java @@ -0,0 +1,461 @@ +/* + * 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.cql3; + +import java.util.HashSet; + +import org.junit.Assert; +import org.junit.Test; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.exceptions.InvalidQueryException; +import org.apache.cassandra.schema.ColumnMetadata; +import org.apache.cassandra.schema.TableMetadata; + +import static org.junit.Assert.assertTrue; + +/* + * This test class was too large and used to timeout CASSANDRA-16777. We're splitting it into: + * - ViewTest + * - ViewPKTest + * - ViewRangesTest + * - ViewTimesTest + */ +public class ViewPKTest extends ViewAbstractTest +{ + @Test + public void testPartitionTombstone() throws Throwable + { + createTable("CREATE TABLE %s (k1 int, c1 int , val int, PRIMARY KEY (k1, c1))"); + + execute("USE " + keyspace()); + executeNet("USE " + keyspace()); + + createView("view1", "CREATE MATERIALIZED VIEW view1 AS SELECT k1, c1, val FROM %%s WHERE k1 IS NOT NULL AND c1 IS NOT NULL AND val IS NOT NULL PRIMARY KEY (val, k1, c1)"); + + updateView("INSERT INTO %s (k1, c1, val) VALUES (1, 2, 200)"); + updateView("INSERT INTO %s (k1, c1, val) VALUES (1, 3, 300)"); + + Assert.assertEquals(2, execute("select * from %s").size()); + Assert.assertEquals(2, execute("select * from view1").size()); + + updateView("DELETE FROM %s WHERE k1 = 1"); + + Assert.assertEquals(0, execute("select * from %s").size()); + Assert.assertEquals(0, execute("select * from view1").size()); + } + + @Test + public void createMvWithUnrestrictedPKParts() throws Throwable + { + createTable("CREATE TABLE %s (k1 int, c1 int , val int, PRIMARY KEY (k1, c1))"); + + execute("USE " + keyspace()); + executeNet("USE " + keyspace()); + + createView("view1", "CREATE MATERIALIZED VIEW view1 AS SELECT val, k1, c1 FROM %%s WHERE k1 IS NOT NULL AND c1 IS NOT NULL AND val IS NOT NULL PRIMARY KEY (val, k1, c1)"); + + } + + @Test + public void testClusteringKeyTombstone() throws Throwable + { + createTable("CREATE TABLE %s (k1 int, c1 int , val int, PRIMARY KEY (k1, c1))"); + + execute("USE " + keyspace()); + executeNet("USE " + keyspace()); + + createView("view1", "CREATE MATERIALIZED VIEW view1 AS SELECT k1, c1, val FROM %%s WHERE k1 IS NOT NULL AND c1 IS NOT NULL AND val IS NOT NULL PRIMARY KEY (val, k1, c1)"); + + updateView("INSERT INTO %s (k1, c1, val) VALUES (1, 2, 200)"); + updateView("INSERT INTO %s (k1, c1, val) VALUES (1, 3, 300)"); + + Assert.assertEquals(2, execute("select * from %s").size()); + Assert.assertEquals(2, execute("select * from view1").size()); + + updateView("DELETE FROM %s WHERE k1 = 1 and c1 = 3"); + + Assert.assertEquals(1, execute("select * from %s").size()); + Assert.assertEquals(1, execute("select * from view1").size()); + } + + @Test + public void testPrimaryKeyIsNotNull() throws Throwable + { + createTable("CREATE TABLE %s (" + + "k int, " + + "asciival ascii, " + + "bigintval bigint, " + + "PRIMARY KEY((k, asciival)))"); + + execute("USE " + keyspace()); + executeNet("USE " + keyspace()); + + // Must include "IS NOT NULL" for primary keys + try + { + createView("mv_test", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s"); + Assert.fail("Should fail if no primary key is filtered as NOT NULL"); + } + catch (Exception e) + { + } + + // Must include both when the partition key is composite + try + { + createView("mv_test", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE bigintval IS NOT NULL AND asciival IS NOT NULL PRIMARY KEY (bigintval, k, asciival)"); + Assert.fail("Should fail if compound primary is not completely filtered as NOT NULL"); + } + catch (Exception e) + { + } + + dropTable("DROP TABLE %s"); + + createTable("CREATE TABLE %s (" + + "k int, " + + "asciival ascii, " + + "bigintval bigint, " + + "PRIMARY KEY(k, asciival))"); + try + { + createView("mv_test", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s"); + Assert.fail("Should fail if no primary key is filtered as NOT NULL"); + } + catch (Exception e) + { + } + + // Must still include both even when the partition key is composite + try + { + createView("mv_test", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE bigintval IS NOT NULL AND asciival IS NOT NULL PRIMARY KEY (bigintval, k, asciival)"); + Assert.fail("Should fail if compound primary is not completely filtered as NOT NULL"); + } + catch (Exception e) + { + } + } + + @Test + public void testCompoundPartitionKey() throws Throwable + { + createTable("CREATE TABLE %s (" + + "k int, " + + "asciival ascii, " + + "bigintval bigint, " + + "PRIMARY KEY((k, asciival)))"); + + TableMetadata metadata = currentTableMetadata(); + + execute("USE " + keyspace()); + executeNet("USE " + keyspace()); + + for (ColumnMetadata def : new HashSet<>(metadata.columns())) + { + try + { + String query = "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE " + def.name + " IS NOT NULL AND k IS NOT NULL " + + (def.name.toString().equals("asciival") ? "" : "AND asciival IS NOT NULL ") + "PRIMARY KEY (" + + def.name + ", k" + (def.name.toString().equals("asciival") ? "" : ", asciival") + ")"; + createView("mv1_" + def.name, query); + + if (def.type.isMultiCell()) + Assert.fail("MV on a multicell should fail " + def); + } + catch (InvalidQueryException e) + { + if (!def.type.isMultiCell() && !def.isPartitionKey()) + Assert.fail("MV creation failed on " + def); + } + + + try + { + String query = "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE " + def.name + " IS NOT NULL AND k IS NOT NULL " + + (def.name.toString().equals("asciival") ? "" : "AND asciival IS NOT NULL ") + " PRIMARY KEY (" + + def.name + ", asciival" + (def.name.toString().equals("k") ? "" : ", k") + ")"; + createView("mv2_" + def.name, query); + + if (def.type.isMultiCell()) + Assert.fail("MV on a multicell should fail " + def); + } + catch (InvalidQueryException e) + { + if (!def.type.isMultiCell() && !def.isPartitionKey()) + Assert.fail("MV creation failed on " + def); + } + + try + { + String query = "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE " + def.name + " IS NOT NULL AND k IS NOT NULL " + + (def.name.toString().equals("asciival") ? "" : "AND asciival IS NOT NULL ") + "PRIMARY KEY ((" + def.name + ", k), asciival)"; + createView("mv3_" + def.name, query); + + if (def.type.isMultiCell()) + Assert.fail("MV on a multicell should fail " + def); + } + catch (InvalidQueryException e) + { + if (!def.type.isMultiCell() && !def.isPartitionKey()) + Assert.fail("MV creation failed on " + def); + } + + + try + { + String query = "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE " + def.name + " IS NOT NULL AND k IS NOT NULL " + + (def.name.toString().equals("asciival") ? "" : "AND asciival IS NOT NULL ") + "PRIMARY KEY ((" + def.name + ", k), asciival)"; + createView("mv3_" + def.name, query); + + Assert.fail("Should fail on duplicate name"); + } + catch (Exception e) + { + } + + try + { + String query = "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE " + def.name + " IS NOT NULL AND k IS NOT NULL " + + (def.name.toString().equals("asciival") ? "" : "AND asciival IS NOT NULL ") + "PRIMARY KEY ((" + def.name + ", k), nonexistentcolumn)"; + createView("mv4_" + def.name, query); + Assert.fail("Should fail with unknown base column"); + } + catch (InvalidQueryException e) + { + } + } + + updateView("INSERT INTO %s (k, asciival, bigintval) VALUES (?, ?, fromJson(?))", 0, "ascii text", "123123123123"); + updateView("INSERT INTO %s (k, asciival) VALUES (?, fromJson(?))", 0, "\"ascii text\""); + assertRows(execute("SELECT bigintval FROM %s WHERE k = ? and asciival = ?", 0, "ascii text"), row(123123123123L)); + + //Check the MV + assertRows(execute("SELECT k, bigintval from mv1_asciival WHERE asciival = ?", "ascii text"), row(0, 123123123123L)); + assertRows(execute("SELECT k, bigintval from mv2_k WHERE asciival = ? and k = ?", "ascii text", 0), row(0, 123123123123L)); + assertRows(execute("SELECT k from mv1_bigintval WHERE bigintval = ?", 123123123123L), row(0)); + assertRows(execute("SELECT asciival from mv3_bigintval where bigintval = ? AND k = ?", 123123123123L, 0), row("ascii text")); + + + //UPDATE BASE + updateView("INSERT INTO %s (k, asciival, bigintval) VALUES (?, ?, fromJson(?))", 0, "ascii text", "1"); + assertRows(execute("SELECT bigintval FROM %s WHERE k = ? and asciival = ?", 0, "ascii text"), row(1L)); + + //Check the MV + assertRows(execute("SELECT k, bigintval from mv1_asciival WHERE asciival = ?", "ascii text"), row(0, 1L)); + assertRows(execute("SELECT k, bigintval from mv2_k WHERE asciival = ? and k = ?", "ascii text", 0), row(0, 1L)); + assertRows(execute("SELECT k from mv1_bigintval WHERE bigintval = ?", 123123123123L)); + assertRows(execute("SELECT asciival from mv3_bigintval where bigintval = ? AND k = ?", 123123123123L, 0)); + assertRows(execute("SELECT asciival from mv3_bigintval where bigintval = ? AND k = ?", 1L, 0), row("ascii text")); + + + //test truncate also truncates all MV + updateView("TRUNCATE %s"); + + assertRows(execute("SELECT bigintval FROM %s WHERE k = ? and asciival = ?", 0, "ascii text")); + assertRows(execute("SELECT k, bigintval from mv1_asciival WHERE asciival = ?", "ascii text")); + assertRows(execute("SELECT k, bigintval from mv2_k WHERE asciival = ? and k = ?", "ascii text", 0)); + assertRows(execute("SELECT asciival from mv3_bigintval where bigintval = ? AND k = ?", 1L, 0)); + } + + @Test + public void testClusteringOrder() throws Throwable + { + createTable("CREATE TABLE %s (" + + "a int," + + "b int," + + "c int," + + "d int," + + "PRIMARY KEY (a, b, c))" + + "WITH CLUSTERING ORDER BY (b ASC, c DESC)"); + + executeNet("USE " + keyspace()); + + createView("mv1", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (a, b, c) WITH CLUSTERING ORDER BY (b DESC, c ASC)"); + createView("mv2", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (a, c, b) WITH CLUSTERING ORDER BY (c ASC, b ASC)"); + createView("mv3", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (a, b, c)"); + createView("mv4", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (a, c, b) WITH CLUSTERING ORDER BY (c DESC, b ASC)"); + + updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, 1, 1, 1); + updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, 2, 2, 2); + + ResultSet mvRows = executeNet("SELECT b FROM mv1"); + assertRowsNet(mvRows, row(2), row(1)); + + mvRows = executeNet("SELECT c FROM mv2"); + assertRowsNet(mvRows, row(1), row(2)); + + mvRows = executeNet("SELECT b FROM mv3"); + assertRowsNet(mvRows, row(1), row(2)); + + mvRows = executeNet("SELECT c FROM mv4"); + assertRowsNet(mvRows, row(2), row(1)); + } + + @Test + public void testPrimaryKeyOnlyTable() throws Throwable + { + createTable("CREATE TABLE %s (" + + "a int," + + "b int," + + "PRIMARY KEY (a, b))"); + + executeNet("USE " + keyspace()); + + // Cannot use SELECT *, as those are always handled by the includeAll shortcut in View.updateAffectsView + createView("mv1", "CREATE MATERIALIZED VIEW %s AS SELECT a, b FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (b, a)"); + + updateView("INSERT INTO %s (a, b) VALUES (?, ?)", 1, 1); + + ResultSet mvRows = executeNet("SELECT a, b FROM mv1"); + assertRowsNet(mvRows, row(1, 1)); + } + + @Test + public void testPartitionKeyOnlyTable() throws Throwable + { + createTable("CREATE TABLE %s (" + + "a int," + + "b int," + + "PRIMARY KEY ((a, b)))"); + + executeNet("USE " + keyspace()); + + // Cannot use SELECT *, as those are always handled by the includeAll shortcut in View.updateAffectsView + createView("mv1", "CREATE MATERIALIZED VIEW %s AS SELECT a, b FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (b, a)"); + + updateView("INSERT INTO %s (a, b) VALUES (?, ?)", 1, 1); + + ResultSet mvRows = executeNet("SELECT a, b FROM mv1"); + assertRowsNet(mvRows, row(1, 1)); + } + + @Test + public void testDeleteSingleColumnInViewClustering() throws Throwable + { + createTable("CREATE TABLE %s (" + + "a int," + + "b int," + + "c int," + + "d int," + + "PRIMARY KEY (a, b))"); + + executeNet("USE " + keyspace()); + createView("mv1", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND d IS NOT NULL PRIMARY KEY (a, d, b)"); + + updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, 0, 0); + ResultSet mvRows = executeNet("SELECT a, d, b, c FROM mv1"); + assertRowsNet(mvRows, row(0, 0, 0, 0)); + + updateView("DELETE c FROM %s WHERE a = ? AND b = ?", 0, 0); + mvRows = executeNet("SELECT a, d, b, c FROM mv1"); + assertRowsNet(mvRows, row(0, 0, 0, null)); + + updateView("DELETE d FROM %s WHERE a = ? AND b = ?", 0, 0); + mvRows = executeNet("SELECT a, d, b FROM mv1"); + assertTrue(mvRows.isExhausted()); + } + + @Test + public void testDeleteSingleColumnInViewPartitionKey() throws Throwable + { + createTable("CREATE TABLE %s (" + + "a int," + + "b int," + + "c int," + + "d int," + + "PRIMARY KEY (a, b))"); + + executeNet("USE " + keyspace()); + createView("mv1", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND d IS NOT NULL PRIMARY KEY (d, a, b)"); + + updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, 0, 0); + ResultSet mvRows = executeNet("SELECT a, d, b, c FROM mv1"); + assertRowsNet(mvRows, row(0, 0, 0, 0)); + + updateView("DELETE c FROM %s WHERE a = ? AND b = ?", 0, 0); + mvRows = executeNet("SELECT a, d, b, c FROM mv1"); + assertRowsNet(mvRows, row(0, 0, 0, null)); + + updateView("DELETE d FROM %s WHERE a = ? AND b = ?", 0, 0); + mvRows = executeNet("SELECT a, d, b FROM mv1"); + assertTrue(mvRows.isExhausted()); + } + + @Test + public void testMultipleNonPrimaryKeysInView() throws Throwable + { + createTable("CREATE TABLE %s (" + + "a int," + + "b int," + + "c int," + + "d int," + + "e int," + + "PRIMARY KEY ((a, b), c))"); + + try + { + createView("mv_de", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL AND d IS NOT NULL AND e IS NOT NULL PRIMARY KEY ((d, a), b, e, c)"); + Assert.fail("Should have rejected a query including multiple non-primary key base columns"); + } + catch (Exception e) + { + } + + try + { + createView("mv_de", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL AND d IS NOT NULL AND e IS NOT NULL PRIMARY KEY ((a, b), c, d, e)"); + Assert.fail("Should have rejected a query including multiple non-primary key base columns"); + } + catch (Exception e) + { + } + + } + + @Test + public void testNullInClusteringColumns() throws Throwable + { + createTable("CREATE TABLE %s (id1 int, id2 int, v1 text, v2 text, PRIMARY KEY (id1, id2))"); + + executeNet("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(executeNet("SELECT * FROM %s"), row(0, 1, "foo", "bar")); + assertRowsNet(executeNet("SELECT * FROM mv"), row(0, "foo", 1, "bar")); + + executeNet("UPDATE %s SET v1=? WHERE id1=? AND id2=?", null, 0, 1); + assertRowsNet(executeNet("SELECT * FROM %s"), row(0, 1, null, "bar")); + assertRowsNet(executeNet("SELECT * FROM mv")); + + executeNet("UPDATE %s SET v2=? WHERE id1=? AND id2=?", "rab", 0, 1); + assertRowsNet(executeNet("SELECT * FROM %s"), row(0, 1, null, "rab")); + assertRowsNet(executeNet("SELECT * FROM mv")); + } +} diff --git a/test/unit/org/apache/cassandra/cql3/ViewRangesTest.java b/test/unit/org/apache/cassandra/cql3/ViewRangesTest.java new file mode 100644 index 0000000..ce67a9b --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/ViewRangesTest.java @@ -0,0 +1,197 @@ +/* + * 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.cql3; + +import org.junit.Assert; +import org.junit.Test; + +import org.apache.cassandra.db.Keyspace; +import org.apache.cassandra.db.SystemKeyspace; + +/* + * This test class was too large and used to timeout CASSANDRA-16777. We're splitting it into: + * - ViewTest + * - ViewPKTest + * - ViewRangesTest + * - ViewTimesTest + */ +public class ViewRangesTest extends ViewAbstractTest +{ + @Test + public void testExistingRangeTombstoneWithFlush() throws Throwable + { + testExistingRangeTombstone(true); + } + + @Test + public void testExistingRangeTombstoneWithoutFlush() throws Throwable + { + testExistingRangeTombstone(false); + } + + public void testExistingRangeTombstone(boolean flush) throws Throwable + { + createTable("CREATE TABLE %s (k1 int, c1 int, c2 int, v1 int, v2 int, PRIMARY KEY (k1, c1, c2))"); + + execute("USE " + keyspace()); + executeNet("USE " + keyspace()); + + createView("view1", + "CREATE MATERIALIZED VIEW view1 AS SELECT * FROM %%s WHERE k1 IS NOT NULL AND c1 IS NOT NULL AND c2 IS NOT NULL PRIMARY KEY (k1, c2, c1)"); + + updateView("DELETE FROM %s USING TIMESTAMP 10 WHERE k1 = 1 and c1=1"); + + if (flush) + Keyspace.open(keyspace()).getColumnFamilyStore(currentTable()).forceBlockingFlush(); + + String table = KEYSPACE + "." + currentTable(); + updateView("BEGIN BATCH " + + "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 0, 0, 0, 0) USING TIMESTAMP 5; " + + "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 0, 1, 0, 1) USING TIMESTAMP 5; " + + "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 1, 0, 1, 0) USING TIMESTAMP 5; " + + "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 1, 1, 1, 1) USING TIMESTAMP 5; " + + "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 1, 2, 1, 2) USING TIMESTAMP 5; " + + "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 1, 3, 1, 3) USING TIMESTAMP 5; " + + "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 2, 0, 2, 0) USING TIMESTAMP 5; " + + "APPLY BATCH"); + + assertRowsIgnoringOrder(execute("select * from %s"), + row(1, 0, 0, 0, 0), + row(1, 0, 1, 0, 1), + row(1, 2, 0, 2, 0)); + assertRowsIgnoringOrder(execute("select k1,c1,c2,v1,v2 from view1"), + row(1, 0, 0, 0, 0), + row(1, 0, 1, 0, 1), + row(1, 2, 0, 2, 0)); + } + + @Test + public void testRangeTombstone() throws Throwable + { + createTable("CREATE TABLE %s (" + + "k int, " + + "asciival ascii, " + + "bigintval bigint, " + + "textval1 text, " + + "textval2 text, " + + "PRIMARY KEY((k, asciival), bigintval, textval1)" + + ")"); + + execute("USE " + keyspace()); + executeNet("USE " + keyspace()); + + createView("mv_test1", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE textval2 IS NOT NULL AND k IS NOT NULL AND asciival IS NOT NULL AND bigintval IS NOT NULL AND textval1 IS NOT NULL PRIMARY KEY ((textval2, k), asciival, bigintval, textval1)"); + + for (int i = 0; i < 100; i++) + updateView("INSERT into %s (k,asciival,bigintval,textval1,textval2)VALUES(?,?,?,?,?)", 0, "foo", (long) i % 2, "bar" + i, "baz"); + + Assert.assertEquals(50, execute("select * from %s where k = 0 and asciival = 'foo' and bigintval = 0").size()); + Assert.assertEquals(50, execute("select * from %s where k = 0 and asciival = 'foo' and bigintval = 1").size()); + + Assert.assertEquals(100, execute("select * from mv_test1").size()); + + //Check the builder works + createView("mv_test2", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE textval2 IS NOT NULL AND k IS NOT NULL AND asciival IS NOT NULL AND bigintval IS NOT NULL AND textval1 IS NOT NULL PRIMARY KEY ((textval2, k), asciival, bigintval, textval1)"); + + while (!SystemKeyspace.isViewBuilt(keyspace(), "mv_test2")) + Thread.sleep(10); + + Assert.assertEquals(100, execute("select * from mv_test2").size()); + + createView("mv_test3", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE textval2 IS NOT NULL AND k IS NOT NULL AND asciival IS NOT NULL AND bigintval IS NOT NULL AND textval1 IS NOT NULL PRIMARY KEY ((textval2, k), bigintval, textval1, asciival)"); + + while (!SystemKeyspace.isViewBuilt(keyspace(), "mv_test3")) + Thread.sleep(10); + + Assert.assertEquals(100, execute("select * from mv_test3").size()); + Assert.assertEquals(100, execute("select asciival from mv_test3 where textval2 = ? and k = ?", "baz", 0).size()); + + //Write a RT and verify the data is removed from index + updateView("DELETE FROM %s WHERE k = ? AND asciival = ? and bigintval = ?", 0, "foo", 0L); + + Assert.assertEquals(50, execute("select asciival from mv_test3 where textval2 = ? and k = ?", "baz", 0).size()); + } + + + @Test + public void testRangeTombstone2() throws Throwable + { + createTable("CREATE TABLE %s (" + + "k int, " + + "asciival ascii, " + + "bigintval bigint, " + + "textval1 text, " + + "PRIMARY KEY((k, asciival), bigintval)" + + ")"); + + execute("USE " + keyspace()); + executeNet("USE " + keyspace()); + + createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE textval1 IS NOT NULL AND k IS NOT NULL AND asciival IS NOT NULL AND bigintval IS NOT NULL PRIMARY KEY ((textval1, k), asciival, bigintval)"); + + for (int i = 0; i < 100; i++) + updateView("INSERT into %s (k,asciival,bigintval,textval1)VALUES(?,?,?,?)", 0, "foo", (long) i % 2, "bar" + i); + + Assert.assertEquals(1, execute("select * from %s where k = 0 and asciival = 'foo' and bigintval = 0").size()); + Assert.assertEquals(1, execute("select * from %s where k = 0 and asciival = 'foo' and bigintval = 1").size()); + + + Assert.assertEquals(2, execute("select * from %s").size()); + Assert.assertEquals(2, execute("select * from mv").size()); + + //Write a RT and verify the data is removed from index + updateView("DELETE FROM %s WHERE k = ? AND asciival = ? and bigintval = ?", 0, "foo", 0L); + + Assert.assertEquals(1, execute("select * from %s").size()); + Assert.assertEquals(1, execute("select * from mv").size()); + } + + @Test + public void testRangeTombstone3() throws Throwable + { + createTable("CREATE TABLE %s (" + + "k int, " + + "asciival ascii, " + + "bigintval bigint, " + + "textval1 text, " + + "PRIMARY KEY((k, asciival), bigintval)" + + ")"); + + execute("USE " + keyspace()); + executeNet("USE " + keyspace()); + + createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE textval1 IS NOT NULL AND k IS NOT NULL AND asciival IS NOT NULL AND bigintval IS NOT NULL PRIMARY KEY ((textval1, k), asciival, bigintval)"); + + for (int i = 0; i < 100; i++) + updateView("INSERT into %s (k,asciival,bigintval,textval1)VALUES(?,?,?,?)", 0, "foo", (long) i % 2, "bar" + i); + + Assert.assertEquals(1, execute("select * from %s where k = 0 and asciival = 'foo' and bigintval = 0").size()); + Assert.assertEquals(1, execute("select * from %s where k = 0 and asciival = 'foo' and bigintval = 1").size()); + + + Assert.assertEquals(2, execute("select * from %s").size()); + Assert.assertEquals(2, execute("select * from mv").size()); + + //Write a RT and verify the data is removed from index + updateView("DELETE FROM %s WHERE k = ? AND asciival = ? and bigintval >= ?", 0, "foo", 0L); + + Assert.assertEquals(0, execute("select * from %s").size()); + Assert.assertEquals(0, execute("select * from mv").size()); + } +} diff --git a/test/unit/org/apache/cassandra/cql3/ViewTest.java b/test/unit/org/apache/cassandra/cql3/ViewTest.java index 8040229..8fb0a23 100644 --- a/test/unit/org/apache/cassandra/cql3/ViewTest.java +++ b/test/unit/org/apache/cassandra/cql3/ViewTest.java @@ -18,34 +18,25 @@ package org.apache.cassandra.cql3; -import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; + import com.google.common.util.concurrent.Uninterruptibles; import org.junit.Assert; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import com.datastax.driver.core.ResultSet; -import com.datastax.driver.core.Row; import com.datastax.driver.core.exceptions.InvalidQueryException; -import com.datastax.driver.core.exceptions.OperationTimedOutException; -import org.apache.cassandra.concurrent.Stage; import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.db.view.View; -import org.apache.cassandra.schema.TableMetadata; -import org.apache.cassandra.schema.ColumnMetadata; import org.apache.cassandra.db.ColumnFamilyStore; import org.apache.cassandra.db.Keyspace; import org.apache.cassandra.db.SystemKeyspace; import org.apache.cassandra.db.compaction.CompactionManager; +import org.apache.cassandra.db.view.View; import org.apache.cassandra.service.ClientWarn; import org.apache.cassandra.utils.FBUtilities; import org.awaitility.Awaitility; @@ -59,65 +50,20 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +/* + * This test class was too large and used to timeout CASSANDRA-16777. We're splitting it into: + * - ViewTest + * - ViewPKTest + * - ViewRangesTest + * - ViewTimesTest + */ @RunWith(BMUnitRunner.class) -public class ViewTest extends CQLTester +public class ViewTest extends ViewAbstractTest { /** Latch used by {@link #testTruncateWhileBuilding()} Byteman injections. */ @SuppressWarnings("unused") private static final CountDownLatch blockViewBuild = new CountDownLatch(1); - private final List<String> views = new ArrayList<>(); - - @BeforeClass - public static void startup() - { - requireNetwork(); - } - - @Before - public void begin() - { - views.clear(); - } - - @After - public void end() throws Throwable - { - for (String viewName : views) - executeNet("DROP MATERIALIZED VIEW " + viewName); - } - - private void createView(String name, String query) throws Throwable - { - try - { - executeNet(String.format(query, name)); - // If exception is thrown, the view will not be added to the list; since it shouldn't have been created, this is - // the desired behavior - views.add(name); - } - catch (OperationTimedOutException ex) - { - // ... except for timeout, when we actually do not know whether the view was created or not - views.add(name); - throw ex; - } - } - - private void updateView(String query, Object... params) throws Throwable - { - executeNet(query, params); - waitForViewMutations(); - } - - private void waitForViewMutations() - { - Awaitility.await() - .atMost(5, TimeUnit.MINUTES) - .until(() -> Stage.VIEW_MUTATION.executor().getPendingTaskCount() == 0 - && Stage.VIEW_MUTATION.executor().getActiveTaskCount() == 0); - } - @Test public void testNonExistingOnes() throws Throwable { @@ -129,169 +75,6 @@ public class ViewTest extends CQLTester } @Test - public void testExistingRangeTombstoneWithFlush() throws Throwable - { - testExistingRangeTombstone(true); - } - - @Test - public void testExistingRangeTombstoneWithoutFlush() throws Throwable - { - testExistingRangeTombstone(false); - } - - public void testExistingRangeTombstone(boolean flush) throws Throwable - { - createTable("CREATE TABLE %s (k1 int, c1 int, c2 int, v1 int, v2 int, PRIMARY KEY (k1, c1, c2))"); - - execute("USE " + keyspace()); - executeNet("USE " + keyspace()); - - createView("view1", - "CREATE MATERIALIZED VIEW view1 AS SELECT * FROM %%s WHERE k1 IS NOT NULL AND c1 IS NOT NULL AND c2 IS NOT NULL PRIMARY KEY (k1, c2, c1)"); - - updateView("DELETE FROM %s USING TIMESTAMP 10 WHERE k1 = 1 and c1=1"); - - if (flush) - Keyspace.open(keyspace()).getColumnFamilyStore(currentTable()).forceBlockingFlush(); - - String table = KEYSPACE + "." + currentTable(); - updateView("BEGIN BATCH " + - "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 0, 0, 0, 0) USING TIMESTAMP 5; " + - "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 0, 1, 0, 1) USING TIMESTAMP 5; " + - "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 1, 0, 1, 0) USING TIMESTAMP 5; " + - "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 1, 1, 1, 1) USING TIMESTAMP 5; " + - "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 1, 2, 1, 2) USING TIMESTAMP 5; " + - "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 1, 3, 1, 3) USING TIMESTAMP 5; " + - "INSERT INTO " + table + " (k1, c1, c2, v1, v2) VALUES (1, 2, 0, 2, 0) USING TIMESTAMP 5; " + - "APPLY BATCH"); - - assertRowsIgnoringOrder(execute("select * from %s"), - row(1, 0, 0, 0, 0), - row(1, 0, 1, 0, 1), - row(1, 2, 0, 2, 0)); - assertRowsIgnoringOrder(execute("select k1,c1,c2,v1,v2 from view1"), - row(1, 0, 0, 0, 0), - row(1, 0, 1, 0, 1), - row(1, 2, 0, 2, 0)); - } - - @Test - public void testPartitionTombstone() throws Throwable - { - createTable("CREATE TABLE %s (k1 int, c1 int , val int, PRIMARY KEY (k1, c1))"); - - execute("USE " + keyspace()); - executeNet("USE " + keyspace()); - - createView("view1", "CREATE MATERIALIZED VIEW view1 AS SELECT k1, c1, val FROM %%s WHERE k1 IS NOT NULL AND c1 IS NOT NULL AND val IS NOT NULL PRIMARY KEY (val, k1, c1)"); - - updateView("INSERT INTO %s (k1, c1, val) VALUES (1, 2, 200)"); - updateView("INSERT INTO %s (k1, c1, val) VALUES (1, 3, 300)"); - - Assert.assertEquals(2, execute("select * from %s").size()); - Assert.assertEquals(2, execute("select * from view1").size()); - - updateView("DELETE FROM %s WHERE k1 = 1"); - - Assert.assertEquals(0, execute("select * from %s").size()); - Assert.assertEquals(0, execute("select * from view1").size()); - } - - @Test - public void createMvWithUnrestrictedPKParts() throws Throwable - { - createTable("CREATE TABLE %s (k1 int, c1 int , val int, PRIMARY KEY (k1, c1))"); - - execute("USE " + keyspace()); - executeNet("USE " + keyspace()); - - createView("view1", "CREATE MATERIALIZED VIEW view1 AS SELECT val, k1, c1 FROM %%s WHERE k1 IS NOT NULL AND c1 IS NOT NULL AND val IS NOT NULL PRIMARY KEY (val, k1, c1)"); - - } - - @Test - public void testClusteringKeyTombstone() throws Throwable - { - createTable("CREATE TABLE %s (k1 int, c1 int , val int, PRIMARY KEY (k1, c1))"); - - execute("USE " + keyspace()); - executeNet("USE " + keyspace()); - - createView("view1", "CREATE MATERIALIZED VIEW view1 AS SELECT k1, c1, val FROM %%s WHERE k1 IS NOT NULL AND c1 IS NOT NULL AND val IS NOT NULL PRIMARY KEY (val, k1, c1)"); - - updateView("INSERT INTO %s (k1, c1, val) VALUES (1, 2, 200)"); - updateView("INSERT INTO %s (k1, c1, val) VALUES (1, 3, 300)"); - - Assert.assertEquals(2, execute("select * from %s").size()); - Assert.assertEquals(2, execute("select * from view1").size()); - - updateView("DELETE FROM %s WHERE k1 = 1 and c1 = 3"); - - Assert.assertEquals(1, execute("select * from %s").size()); - Assert.assertEquals(1, execute("select * from view1").size()); - } - - @Test - public void testPrimaryKeyIsNotNull() throws Throwable - { - createTable("CREATE TABLE %s (" + - "k int, " + - "asciival ascii, " + - "bigintval bigint, " + - "PRIMARY KEY((k, asciival)))"); - - execute("USE " + keyspace()); - executeNet("USE " + keyspace()); - - // Must include "IS NOT NULL" for primary keys - try - { - createView("mv_test", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s"); - Assert.fail("Should fail if no primary key is filtered as NOT NULL"); - } - catch (Exception e) - { - } - - // Must include both when the partition key is composite - try - { - createView("mv_test", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE bigintval IS NOT NULL AND asciival IS NOT NULL PRIMARY KEY (bigintval, k, asciival)"); - Assert.fail("Should fail if compound primary is not completely filtered as NOT NULL"); - } - catch (Exception e) - { - } - - dropTable("DROP TABLE %s"); - - createTable("CREATE TABLE %s (" + - "k int, " + - "asciival ascii, " + - "bigintval bigint, " + - "PRIMARY KEY(k, asciival))"); - try - { - createView("mv_test", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s"); - Assert.fail("Should fail if no primary key is filtered as NOT NULL"); - } - catch (Exception e) - { - } - - // Must still include both even when the partition key is composite - try - { - createView("mv_test", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE bigintval IS NOT NULL AND asciival IS NOT NULL PRIMARY KEY (bigintval, k, asciival)"); - Assert.fail("Should fail if compound primary is not completely filtered as NOT NULL"); - } - catch (Exception e) - { - } - } - - @Test public void testStaticTable() throws Throwable { createTable("CREATE TABLE %s (" + @@ -385,38 +168,6 @@ public class ViewTest extends CQLTester } @Test - public void testRegularColumnTimestampUpdates() throws Throwable - { - // Regression test for CASSANDRA-10910 - - createTable("CREATE TABLE %s (" + - "k int PRIMARY KEY, " + - "c int, " + - "val int)"); - - execute("USE " + keyspace()); - executeNet("USE " + keyspace()); - - createView("mv_rctstest", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE k IS NOT NULL AND c IS NOT NULL PRIMARY KEY (k,c)"); - - updateView("UPDATE %s SET c = ?, val = ? WHERE k = ?", 0, 0, 0); - updateView("UPDATE %s SET val = ? WHERE k = ?", 1, 0); - updateView("UPDATE %s SET c = ? WHERE k = ?", 1, 0); - assertRows(execute("SELECT c, k, val FROM mv_rctstest"), row(1, 0, 1)); - - updateView("TRUNCATE %s"); - - updateView("UPDATE %s USING TIMESTAMP 1 SET c = ?, val = ? WHERE k = ?", 0, 0, 0); - updateView("UPDATE %s USING TIMESTAMP 3 SET c = ? WHERE k = ?", 1, 0); - updateView("UPDATE %s USING TIMESTAMP 2 SET val = ? WHERE k = ?", 1, 0); - updateView("UPDATE %s USING TIMESTAMP 4 SET c = ? WHERE k = ?", 2, 0); - updateView("UPDATE %s USING TIMESTAMP 3 SET val = ? WHERE k = ?", 2, 0); - - assertRows(execute("SELECT c, k, val FROM mv_rctstest"), row(2, 0, 2)); - assertRows(execute("SELECT c, k, val FROM mv_rctstest limit 1"), row(2, 0, 2)); - } - - @Test public void testCountersTable() throws Throwable { createTable("CREATE TABLE %s (" + @@ -458,123 +209,6 @@ public class ViewTest extends CQLTester } @Test - public void complexTimestampUpdateTestWithFlush() throws Throwable - { - complexTimestampUpdateTest(true); - } - - @Test - public void complexTimestampUpdateTestWithoutFlush() throws Throwable - { - complexTimestampUpdateTest(false); - } - - public void complexTimestampUpdateTest(boolean flush) throws Throwable - { - createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, PRIMARY KEY (a, b))"); - - execute("USE " + keyspace()); - executeNet("USE " + keyspace()); - Keyspace ks = Keyspace.open(keyspace()); - - createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (c, a, b)"); - ks.getColumnFamilyStore("mv").disableAutoCompaction(); - - //Set initial values TS=0, leaving e null and verify view - executeNet("INSERT INTO %s (a, b, c, d) VALUES (0, 0, 1, 0) USING TIMESTAMP 0"); - assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row(0)); - - //update c's timestamp TS=2 - executeNet("UPDATE %s USING TIMESTAMP 2 SET c = ? WHERE a = ? and b = ? ", 1, 0, 0); - assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row(0)); - - if (flush) - FBUtilities.waitOnFutures(ks.flush()); - - // change c's value and TS=3, tombstones c=1 and adds c=0 record - executeNet("UPDATE %s USING TIMESTAMP 3 SET c = ? WHERE a = ? and b = ? ", 0, 0, 0); - if (flush) - FBUtilities.waitOnFutures(ks.flush()); - assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0)); - - if(flush) - { - ks.getColumnFamilyStore("mv").forceMajorCompaction(); - FBUtilities.waitOnFutures(ks.flush()); - } - - - //change c's value back to 1 with TS=4, check we can see d - executeNet("UPDATE %s USING TIMESTAMP 4 SET c = ? WHERE a = ? and b = ? ", 1, 0, 0); - if (flush) - { - ks.getColumnFamilyStore("mv").forceMajorCompaction(); - FBUtilities.waitOnFutures(ks.flush()); - } - - assertRows(execute("SELECT d,e from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row(0, null)); - - - //Add e value @ TS=1 - executeNet("UPDATE %s USING TIMESTAMP 1 SET e = ? WHERE a = ? and b = ? ", 1, 0, 0); - assertRows(execute("SELECT d,e from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row(0, 1)); - - if (flush) - FBUtilities.waitOnFutures(ks.flush()); - - - //Change d value @ TS=2 - executeNet("UPDATE %s USING TIMESTAMP 2 SET d = ? WHERE a = ? and b = ? ", 2, 0, 0); - assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row(2)); - - if (flush) - FBUtilities.waitOnFutures(ks.flush()); - - - //Change d value @ TS=3 - executeNet("UPDATE %s USING TIMESTAMP 3 SET d = ? WHERE a = ? and b = ? ", 1, 0, 0); - assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row(1)); - - - //Tombstone c - executeNet("DELETE FROM %s WHERE a = ? and b = ?", 0, 0); - assertRows(execute("SELECT d from mv")); - - //Add back without D - executeNet("INSERT INTO %s (a, b, c) VALUES (0, 0, 1)"); - - //Make sure D doesn't pop back in. - assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row((Object) null)); - - - //New partition - // insert a row with timestamp 0 - executeNet("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?) USING TIMESTAMP 0", 1, 0, 0, 0, 0); - - // overwrite pk and e with timestamp 1, but don't overwrite d - executeNet("INSERT INTO %s (a, b, c, e) VALUES (?, ?, ?, ?) USING TIMESTAMP 1", 1, 0, 0, 0); - - // delete with timestamp 0 (which should only delete d) - executeNet("DELETE FROM %s USING TIMESTAMP 0 WHERE a = ? AND b = ?", 1, 0); - assertRows(execute("SELECT a, b, c, d, e from mv WHERE c = ? and a = ? and b = ?", 0, 1, 0), - row(1, 0, 0, null, 0) - ); - - executeNet("UPDATE %s USING TIMESTAMP 2 SET c = ? WHERE a = ? AND b = ?", 1, 1, 0); - executeNet("UPDATE %s USING TIMESTAMP 3 SET c = ? WHERE a = ? AND b = ?", 0, 1, 0); - assertRows(execute("SELECT a, b, c, d, e from mv WHERE c = ? and a = ? and b = ?", 0, 1, 0), - row(1, 0, 0, null, 0) - ); - - executeNet("UPDATE %s USING TIMESTAMP 3 SET d = ? WHERE a = ? AND b = ?", 0, 1, 0); - assertRows(execute("SELECT a, b, c, d, e from mv WHERE c = ? and a = ? and b = ?", 0, 1, 0), - row(1, 0, 0, 0, 0) - ); - - - } - - @Test public void testBuilderWidePartition() throws Throwable { createTable("CREATE TABLE %s (" + @@ -601,241 +235,6 @@ public class ViewTest extends CQLTester } @Test - public void testRangeTombstone() throws Throwable - { - createTable("CREATE TABLE %s (" + - "k int, " + - "asciival ascii, " + - "bigintval bigint, " + - "textval1 text, " + - "textval2 text, " + - "PRIMARY KEY((k, asciival), bigintval, textval1)" + - ")"); - - execute("USE " + keyspace()); - executeNet("USE " + keyspace()); - - createView("mv_test1", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE textval2 IS NOT NULL AND k IS NOT NULL AND asciival IS NOT NULL AND bigintval IS NOT NULL AND textval1 IS NOT NULL PRIMARY KEY ((textval2, k), asciival, bigintval, textval1)"); - - for (int i = 0; i < 100; i++) - updateView("INSERT into %s (k,asciival,bigintval,textval1,textval2)VALUES(?,?,?,?,?)", 0, "foo", (long) i % 2, "bar" + i, "baz"); - - Assert.assertEquals(50, execute("select * from %s where k = 0 and asciival = 'foo' and bigintval = 0").size()); - Assert.assertEquals(50, execute("select * from %s where k = 0 and asciival = 'foo' and bigintval = 1").size()); - - Assert.assertEquals(100, execute("select * from mv_test1").size()); - - //Check the builder works - createView("mv_test2", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE textval2 IS NOT NULL AND k IS NOT NULL AND asciival IS NOT NULL AND bigintval IS NOT NULL AND textval1 IS NOT NULL PRIMARY KEY ((textval2, k), asciival, bigintval, textval1)"); - - while (!SystemKeyspace.isViewBuilt(keyspace(), "mv_test2")) - Thread.sleep(10); - - Assert.assertEquals(100, execute("select * from mv_test2").size()); - - createView("mv_test3", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE textval2 IS NOT NULL AND k IS NOT NULL AND asciival IS NOT NULL AND bigintval IS NOT NULL AND textval1 IS NOT NULL PRIMARY KEY ((textval2, k), bigintval, textval1, asciival)"); - - while (!SystemKeyspace.isViewBuilt(keyspace(), "mv_test3")) - Thread.sleep(10); - - Assert.assertEquals(100, execute("select * from mv_test3").size()); - Assert.assertEquals(100, execute("select asciival from mv_test3 where textval2 = ? and k = ?", "baz", 0).size()); - - //Write a RT and verify the data is removed from index - updateView("DELETE FROM %s WHERE k = ? AND asciival = ? and bigintval = ?", 0, "foo", 0L); - - Assert.assertEquals(50, execute("select asciival from mv_test3 where textval2 = ? and k = ?", "baz", 0).size()); - } - - - @Test - public void testRangeTombstone2() throws Throwable - { - createTable("CREATE TABLE %s (" + - "k int, " + - "asciival ascii, " + - "bigintval bigint, " + - "textval1 text, " + - "PRIMARY KEY((k, asciival), bigintval)" + - ")"); - - execute("USE " + keyspace()); - executeNet("USE " + keyspace()); - - createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE textval1 IS NOT NULL AND k IS NOT NULL AND asciival IS NOT NULL AND bigintval IS NOT NULL PRIMARY KEY ((textval1, k), asciival, bigintval)"); - - for (int i = 0; i < 100; i++) - updateView("INSERT into %s (k,asciival,bigintval,textval1)VALUES(?,?,?,?)", 0, "foo", (long) i % 2, "bar" + i); - - Assert.assertEquals(1, execute("select * from %s where k = 0 and asciival = 'foo' and bigintval = 0").size()); - Assert.assertEquals(1, execute("select * from %s where k = 0 and asciival = 'foo' and bigintval = 1").size()); - - - Assert.assertEquals(2, execute("select * from %s").size()); - Assert.assertEquals(2, execute("select * from mv").size()); - - //Write a RT and verify the data is removed from index - updateView("DELETE FROM %s WHERE k = ? AND asciival = ? and bigintval = ?", 0, "foo", 0L); - - Assert.assertEquals(1, execute("select * from %s").size()); - Assert.assertEquals(1, execute("select * from mv").size()); - } - - @Test - public void testRangeTombstone3() throws Throwable - { - createTable("CREATE TABLE %s (" + - "k int, " + - "asciival ascii, " + - "bigintval bigint, " + - "textval1 text, " + - "PRIMARY KEY((k, asciival), bigintval)" + - ")"); - - execute("USE " + keyspace()); - executeNet("USE " + keyspace()); - - createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE textval1 IS NOT NULL AND k IS NOT NULL AND asciival IS NOT NULL AND bigintval IS NOT NULL PRIMARY KEY ((textval1, k), asciival, bigintval)"); - - for (int i = 0; i < 100; i++) - updateView("INSERT into %s (k,asciival,bigintval,textval1)VALUES(?,?,?,?)", 0, "foo", (long) i % 2, "bar" + i); - - Assert.assertEquals(1, execute("select * from %s where k = 0 and asciival = 'foo' and bigintval = 0").size()); - Assert.assertEquals(1, execute("select * from %s where k = 0 and asciival = 'foo' and bigintval = 1").size()); - - - Assert.assertEquals(2, execute("select * from %s").size()); - Assert.assertEquals(2, execute("select * from mv").size()); - - //Write a RT and verify the data is removed from index - updateView("DELETE FROM %s WHERE k = ? AND asciival = ? and bigintval >= ?", 0, "foo", 0L); - - Assert.assertEquals(0, execute("select * from %s").size()); - Assert.assertEquals(0, execute("select * from mv").size()); - } - - @Test - public void testCompoundPartitionKey() throws Throwable - { - createTable("CREATE TABLE %s (" + - "k int, " + - "asciival ascii, " + - "bigintval bigint, " + - "PRIMARY KEY((k, asciival)))"); - - TableMetadata metadata = currentTableMetadata(); - - execute("USE " + keyspace()); - executeNet("USE " + keyspace()); - - for (ColumnMetadata def : new HashSet<>(metadata.columns())) - { - try - { - String query = "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE " + def.name + " IS NOT NULL AND k IS NOT NULL " - + (def.name.toString().equals("asciival") ? "" : "AND asciival IS NOT NULL ") + "PRIMARY KEY (" - + def.name + ", k" + (def.name.toString().equals("asciival") ? "" : ", asciival") + ")"; - createView("mv1_" + def.name, query); - - if (def.type.isMultiCell()) - Assert.fail("MV on a multicell should fail " + def); - } - catch (InvalidQueryException e) - { - if (!def.type.isMultiCell() && !def.isPartitionKey()) - Assert.fail("MV creation failed on " + def); - } - - - try - { - String query = "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE " + def.name + " IS NOT NULL AND k IS NOT NULL " - + (def.name.toString().equals("asciival") ? "" : "AND asciival IS NOT NULL ") + " PRIMARY KEY (" - + def.name + ", asciival" + (def.name.toString().equals("k") ? "" : ", k") + ")"; - createView("mv2_" + def.name, query); - - if (def.type.isMultiCell()) - Assert.fail("MV on a multicell should fail " + def); - } - catch (InvalidQueryException e) - { - if (!def.type.isMultiCell() && !def.isPartitionKey()) - Assert.fail("MV creation failed on " + def); - } - - try - { - String query = "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE " + def.name + " IS NOT NULL AND k IS NOT NULL " - + (def.name.toString().equals("asciival") ? "" : "AND asciival IS NOT NULL ") + "PRIMARY KEY ((" + def.name + ", k), asciival)"; - createView("mv3_" + def.name, query); - - if (def.type.isMultiCell()) - Assert.fail("MV on a multicell should fail " + def); - } - catch (InvalidQueryException e) - { - if (!def.type.isMultiCell() && !def.isPartitionKey()) - Assert.fail("MV creation failed on " + def); - } - - - try - { - String query = "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE " + def.name + " IS NOT NULL AND k IS NOT NULL " - + (def.name.toString().equals("asciival") ? "" : "AND asciival IS NOT NULL ") + "PRIMARY KEY ((" + def.name + ", k), asciival)"; - createView("mv3_" + def.name, query); - - Assert.fail("Should fail on duplicate name"); - } - catch (Exception e) - { - } - - try - { - String query = "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE " + def.name + " IS NOT NULL AND k IS NOT NULL " - + (def.name.toString().equals("asciival") ? "" : "AND asciival IS NOT NULL ") + "PRIMARY KEY ((" + def.name + ", k), nonexistentcolumn)"; - createView("mv4_" + def.name, query); - Assert.fail("Should fail with unknown base column"); - } - catch (InvalidQueryException e) - { - } - } - - updateView("INSERT INTO %s (k, asciival, bigintval) VALUES (?, ?, fromJson(?))", 0, "ascii text", "123123123123"); - updateView("INSERT INTO %s (k, asciival) VALUES (?, fromJson(?))", 0, "\"ascii text\""); - assertRows(execute("SELECT bigintval FROM %s WHERE k = ? and asciival = ?", 0, "ascii text"), row(123123123123L)); - - //Check the MV - assertRows(execute("SELECT k, bigintval from mv1_asciival WHERE asciival = ?", "ascii text"), row(0, 123123123123L)); - assertRows(execute("SELECT k, bigintval from mv2_k WHERE asciival = ? and k = ?", "ascii text", 0), row(0, 123123123123L)); - assertRows(execute("SELECT k from mv1_bigintval WHERE bigintval = ?", 123123123123L), row(0)); - assertRows(execute("SELECT asciival from mv3_bigintval where bigintval = ? AND k = ?", 123123123123L, 0), row("ascii text")); - - - //UPDATE BASE - updateView("INSERT INTO %s (k, asciival, bigintval) VALUES (?, ?, fromJson(?))", 0, "ascii text", "1"); - assertRows(execute("SELECT bigintval FROM %s WHERE k = ? and asciival = ?", 0, "ascii text"), row(1L)); - - //Check the MV - assertRows(execute("SELECT k, bigintval from mv1_asciival WHERE asciival = ?", "ascii text"), row(0, 1L)); - assertRows(execute("SELECT k, bigintval from mv2_k WHERE asciival = ? and k = ?", "ascii text", 0), row(0, 1L)); - assertRows(execute("SELECT k from mv1_bigintval WHERE bigintval = ?", 123123123123L)); - assertRows(execute("SELECT asciival from mv3_bigintval where bigintval = ? AND k = ?", 123123123123L, 0)); - assertRows(execute("SELECT asciival from mv3_bigintval where bigintval = ? AND k = ?", 1L, 0), row("ascii text")); - - - //test truncate also truncates all MV - updateView("TRUNCATE %s"); - - assertRows(execute("SELECT bigintval FROM %s WHERE k = ? and asciival = ?", 0, "ascii text")); - assertRows(execute("SELECT k, bigintval from mv1_asciival WHERE asciival = ?", "ascii text")); - assertRows(execute("SELECT k, bigintval from mv2_k WHERE asciival = ? and k = ?", "ascii text", 0)); - assertRows(execute("SELECT asciival from mv3_bigintval where bigintval = ? AND k = ?", 1L, 0)); - } - - @Test public void testCollections() throws Throwable { createTable("CREATE TABLE %s (" + @@ -956,51 +355,6 @@ public class ViewTest extends CQLTester } @Test - public void ttlTest() throws Throwable - { - createTable("CREATE TABLE %s (" + - "a int," + - "b int," + - "c int," + - "d int," + - "PRIMARY KEY (a, b))"); - - executeNet("USE " + keyspace()); - - createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE c IS NOT NULL AND a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (c, a, b)"); - - updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?) USING TTL 3", 1, 1, 1, 1); - - Thread.sleep(TimeUnit.SECONDS.toMillis(1)); - updateView("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 1, 1, 2); - - Thread.sleep(TimeUnit.SECONDS.toMillis(5)); - List<Row> results = executeNet("SELECT d FROM mv WHERE c = 2 AND a = 1 AND b = 1").all(); - Assert.assertEquals(1, results.size()); - Assert.assertTrue("There should be a null result given back due to ttl expiry", results.get(0).isNull(0)); - } - - @Test - public void ttlExpirationTest() throws Throwable - { - createTable("CREATE TABLE %s (" + - "a int," + - "b int," + - "c int," + - "d int," + - "PRIMARY KEY (a, b))"); - - executeNet("USE " + keyspace()); - - createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE c IS NOT NULL AND a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (c, a, b)"); - - updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?) USING TTL 3", 1, 1, 1, 1); - - Thread.sleep(TimeUnit.SECONDS.toMillis(4)); - Assert.assertEquals(0, executeNet("SELECT * FROM mv WHERE c = 1 AND a = 1 AND b = 1").all().size()); - } - - @Test public void rowDeletionTest() throws Throwable { createTable("CREATE TABLE %s (" + @@ -1021,65 +375,6 @@ public class ViewTest extends CQLTester } @Test - public void conflictingTimestampTest() throws Throwable - { - createTable("CREATE TABLE %s (" + - "a int," + - "b int," + - "c int," + - "PRIMARY KEY (a, b))"); - - executeNet("USE " + keyspace()); - - createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE c IS NOT NULL AND a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (c, a, b)"); - - for (int i = 0; i < 50; i++) - { - updateView("INSERT INTO %s (a, b, c) VALUES (?, ?, ?) USING TIMESTAMP 1", 1, 1, i); - } - - ResultSet mvRows = executeNet("SELECT c FROM mv"); - List<Row> rows = executeNet("SELECT c FROM %s").all(); - Assert.assertEquals("There should be exactly one row in base", 1, rows.size()); - int expected = rows.get(0).getInt("c"); - assertRowsNet(mvRows, row(expected)); - } - - @Test - public void testClusteringOrder() throws Throwable - { - createTable("CREATE TABLE %s (" + - "a int," + - "b int," + - "c int," + - "d int," + - "PRIMARY KEY (a, b, c))" + - "WITH CLUSTERING ORDER BY (b ASC, c DESC)"); - - executeNet("USE " + keyspace()); - - createView("mv1", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (a, b, c) WITH CLUSTERING ORDER BY (b DESC, c ASC)"); - createView("mv2", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (a, c, b) WITH CLUSTERING ORDER BY (c ASC, b ASC)"); - createView("mv3", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (a, b, c)"); - createView("mv4", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (a, c, b) WITH CLUSTERING ORDER BY (c DESC, b ASC)"); - - updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, 1, 1, 1); - updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 1, 2, 2, 2); - - ResultSet mvRows = executeNet("SELECT b FROM mv1"); - assertRowsNet(mvRows, row(2), row(1)); - - mvRows = executeNet("SELECT c FROM mv2"); - assertRowsNet(mvRows, row(1), row(2)); - - mvRows = executeNet("SELECT b FROM mv3"); - assertRowsNet(mvRows, row(1), row(2)); - - mvRows = executeNet("SELECT c FROM mv4"); - assertRowsNet(mvRows, row(2), row(1)); - } - - @Test public void testMultipleDeletes() throws Throwable { createTable("CREATE TABLE %s (" + @@ -1108,96 +403,6 @@ public class ViewTest extends CQLTester } @Test - public void testPrimaryKeyOnlyTable() throws Throwable - { - createTable("CREATE TABLE %s (" + - "a int," + - "b int," + - "PRIMARY KEY (a, b))"); - - executeNet("USE " + keyspace()); - - // Cannot use SELECT *, as those are always handled by the includeAll shortcut in View.updateAffectsView - createView("mv1", "CREATE MATERIALIZED VIEW %s AS SELECT a, b FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (b, a)"); - - updateView("INSERT INTO %s (a, b) VALUES (?, ?)", 1, 1); - - ResultSet mvRows = executeNet("SELECT a, b FROM mv1"); - assertRowsNet(mvRows, row(1, 1)); - } - - @Test - public void testPartitionKeyOnlyTable() throws Throwable - { - createTable("CREATE TABLE %s (" + - "a int," + - "b int," + - "PRIMARY KEY ((a, b)))"); - - executeNet("USE " + keyspace()); - - // Cannot use SELECT *, as those are always handled by the includeAll shortcut in View.updateAffectsView - createView("mv1", "CREATE MATERIALIZED VIEW %s AS SELECT a, b FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (b, a)"); - - updateView("INSERT INTO %s (a, b) VALUES (?, ?)", 1, 1); - - ResultSet mvRows = executeNet("SELECT a, b FROM mv1"); - assertRowsNet(mvRows, row(1, 1)); - } - - @Test - public void testDeleteSingleColumnInViewClustering() throws Throwable - { - createTable("CREATE TABLE %s (" + - "a int," + - "b int," + - "c int," + - "d int," + - "PRIMARY KEY (a, b))"); - - executeNet("USE " + keyspace()); - createView("mv1", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND d IS NOT NULL PRIMARY KEY (a, d, b)"); - - updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, 0, 0); - ResultSet mvRows = executeNet("SELECT a, d, b, c FROM mv1"); - assertRowsNet(mvRows, row(0, 0, 0, 0)); - - updateView("DELETE c FROM %s WHERE a = ? AND b = ?", 0, 0); - mvRows = executeNet("SELECT a, d, b, c FROM mv1"); - assertRowsNet(mvRows, row(0, 0, 0, null)); - - updateView("DELETE d FROM %s WHERE a = ? AND b = ?", 0, 0); - mvRows = executeNet("SELECT a, d, b FROM mv1"); - assertTrue(mvRows.isExhausted()); - } - - @Test - public void testDeleteSingleColumnInViewPartitionKey() throws Throwable - { - createTable("CREATE TABLE %s (" + - "a int," + - "b int," + - "c int," + - "d int," + - "PRIMARY KEY (a, b))"); - - executeNet("USE " + keyspace()); - createView("mv1", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND d IS NOT NULL PRIMARY KEY (d, a, b)"); - - updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, 0, 0, 0); - ResultSet mvRows = executeNet("SELECT a, d, b, c FROM mv1"); - assertRowsNet(mvRows, row(0, 0, 0, 0)); - - updateView("DELETE c FROM %s WHERE a = ? AND b = ?", 0, 0); - mvRows = executeNet("SELECT a, d, b, c FROM mv1"); - assertRowsNet(mvRows, row(0, 0, 0, null)); - - updateView("DELETE d FROM %s WHERE a = ? AND b = ?", 0, 0); - mvRows = executeNet("SELECT a, d, b FROM mv1"); - assertTrue(mvRows.isExhausted()); - } - - @Test public void testCollectionInView() throws Throwable { createTable("CREATE TABLE %s (" + @@ -1223,66 +428,6 @@ public class ViewTest extends CQLTester } @Test - public void testMultipleNonPrimaryKeysInView() throws Throwable - { - createTable("CREATE TABLE %s (" + - "a int," + - "b int," + - "c int," + - "d int," + - "e int," + - "PRIMARY KEY ((a, b), c))"); - - try - { - createView("mv_de", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL AND d IS NOT NULL AND e IS NOT NULL PRIMARY KEY ((d, a), b, e, c)"); - Assert.fail("Should have rejected a query including multiple non-primary key base columns"); - } - catch (Exception e) - { - } - - try - { - createView("mv_de", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL AND d IS NOT NULL AND e IS NOT NULL PRIMARY KEY ((a, b), c, d, e)"); - Assert.fail("Should have rejected a query including multiple non-primary key base columns"); - } - catch (Exception e) - { - } - - } - - @Test - public void testNullInClusteringColumns() throws Throwable - { - createTable("CREATE TABLE %s (id1 int, id2 int, v1 text, v2 text, PRIMARY KEY (id1, id2))"); - - executeNet("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(executeNet("SELECT * FROM %s"), row(0, 1, "foo", "bar")); - assertRowsNet(executeNet("SELECT * FROM mv"), row(0, "foo", 1, "bar")); - - executeNet("UPDATE %s SET v1=? WHERE id1=? AND id2=?", null, 0, 1); - assertRowsNet(executeNet("SELECT * FROM %s"), row(0, 1, null, "bar")); - assertRowsNet(executeNet("SELECT * FROM mv")); - - executeNet("UPDATE %s SET v2=? WHERE id1=? AND id2=?", "rab", 0, 1); - assertRowsNet(executeNet("SELECT * FROM %s"), row(0, 1, null, "rab")); - assertRowsNet(executeNet("SELECT * FROM mv")); - } - - @Test public void testReservedKeywordsInMV() throws Throwable { createTable("CREATE TABLE %s (\"token\" int PRIMARY KEY, \"keyspace\" int)"); @@ -1302,48 +447,6 @@ public class ViewTest extends CQLTester assertRowsNet(executeNet("SELECT * FROM mv"), row(1, 0)); } - public void testCreateMvWithTTL() throws Throwable - { - createTable("CREATE TABLE %s (" + - "k int PRIMARY KEY, " + - "c int, " + - "val int) WITH default_time_to_live = 60"); - - execute("USE " + keyspace()); - executeNet("USE " + keyspace()); - - // Must NOT include "default_time_to_live" for Materialized View creation - try - { - createView("mv_ttl1", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE k IS NOT NULL AND c IS NOT NULL PRIMARY KEY (k,c) WITH default_time_to_live = 30"); - Assert.fail("Should fail if TTL is provided for materialized view"); - } - catch (Exception e) - { - } - } - - @Test - public void testAlterMvWithTTL() throws Throwable - { - createTable("CREATE TABLE %s (" + - "k int PRIMARY KEY, " + - "c int, " + - "val int) WITH default_time_to_live = 60"); - - createView("mv_ttl2", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE k IS NOT NULL AND c IS NOT NULL PRIMARY KEY (k,c)"); - - // Must NOT include "default_time_to_live" on alter Materialized View - try - { - executeNet("ALTER MATERIALIZED VIEW %s WITH default_time_to_live = 30"); - Assert.fail("Should fail if TTL is provided while altering materialized view"); - } - catch (Exception e) - { - } - } - private void testViewBuilderResume(int concurrentViewBuilders) throws Throwable { createTable("CREATE TABLE %s (" + diff --git a/test/unit/org/apache/cassandra/cql3/ViewTimesTest.java b/test/unit/org/apache/cassandra/cql3/ViewTimesTest.java new file mode 100644 index 0000000..4fee422 --- /dev/null +++ b/test/unit/org/apache/cassandra/cql3/ViewTimesTest.java @@ -0,0 +1,300 @@ +/* + * 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.cql3; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.junit.Assert; +import org.junit.Test; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import org.apache.cassandra.db.Keyspace; +import org.apache.cassandra.utils.FBUtilities; + +/* + * This test class was too large and used to timeout CASSANDRA-16777. We're splitting it into: + * - ViewTest + * - ViewPKTest + * - ViewRangesTest + * - ViewTimesTest + */ +public class ViewTimesTest extends ViewAbstractTest +{ + @Test + public void testRegularColumnTimestampUpdates() throws Throwable + { + // Regression test for CASSANDRA-10910 + + createTable("CREATE TABLE %s (" + + "k int PRIMARY KEY, " + + "c int, " + + "val int)"); + + execute("USE " + keyspace()); + executeNet("USE " + keyspace()); + + createView("mv_rctstest", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE k IS NOT NULL AND c IS NOT NULL PRIMARY KEY (k,c)"); + + updateView("UPDATE %s SET c = ?, val = ? WHERE k = ?", 0, 0, 0); + updateView("UPDATE %s SET val = ? WHERE k = ?", 1, 0); + updateView("UPDATE %s SET c = ? WHERE k = ?", 1, 0); + assertRows(execute("SELECT c, k, val FROM mv_rctstest"), row(1, 0, 1)); + + updateView("TRUNCATE %s"); + + updateView("UPDATE %s USING TIMESTAMP 1 SET c = ?, val = ? WHERE k = ?", 0, 0, 0); + updateView("UPDATE %s USING TIMESTAMP 3 SET c = ? WHERE k = ?", 1, 0); + updateView("UPDATE %s USING TIMESTAMP 2 SET val = ? WHERE k = ?", 1, 0); + updateView("UPDATE %s USING TIMESTAMP 4 SET c = ? WHERE k = ?", 2, 0); + updateView("UPDATE %s USING TIMESTAMP 3 SET val = ? WHERE k = ?", 2, 0); + + assertRows(execute("SELECT c, k, val FROM mv_rctstest"), row(2, 0, 2)); + assertRows(execute("SELECT c, k, val FROM mv_rctstest limit 1"), row(2, 0, 2)); + } + + @Test + public void complexTimestampUpdateTestWithFlush() throws Throwable + { + complexTimestampUpdateTest(true); + } + + @Test + public void complexTimestampUpdateTestWithoutFlush() throws Throwable + { + complexTimestampUpdateTest(false); + } + + public void complexTimestampUpdateTest(boolean flush) throws Throwable + { + createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, PRIMARY KEY (a, b))"); + + execute("USE " + keyspace()); + executeNet("USE " + keyspace()); + Keyspace ks = Keyspace.open(keyspace()); + + createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE a IS NOT NULL AND b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (c, a, b)"); + ks.getColumnFamilyStore("mv").disableAutoCompaction(); + + //Set initial values TS=0, leaving e null and verify view + executeNet("INSERT INTO %s (a, b, c, d) VALUES (0, 0, 1, 0) USING TIMESTAMP 0"); + assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row(0)); + + //update c's timestamp TS=2 + executeNet("UPDATE %s USING TIMESTAMP 2 SET c = ? WHERE a = ? and b = ? ", 1, 0, 0); + assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row(0)); + + if (flush) + FBUtilities.waitOnFutures(ks.flush()); + + // change c's value and TS=3, tombstones c=1 and adds c=0 record + executeNet("UPDATE %s USING TIMESTAMP 3 SET c = ? WHERE a = ? and b = ? ", 0, 0, 0); + if (flush) + FBUtilities.waitOnFutures(ks.flush()); + assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0)); + + if(flush) + { + ks.getColumnFamilyStore("mv").forceMajorCompaction(); + FBUtilities.waitOnFutures(ks.flush()); + } + + + //change c's value back to 1 with TS=4, check we can see d + executeNet("UPDATE %s USING TIMESTAMP 4 SET c = ? WHERE a = ? and b = ? ", 1, 0, 0); + if (flush) + { + ks.getColumnFamilyStore("mv").forceMajorCompaction(); + FBUtilities.waitOnFutures(ks.flush()); + } + + assertRows(execute("SELECT d,e from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row(0, null)); + + + //Add e value @ TS=1 + executeNet("UPDATE %s USING TIMESTAMP 1 SET e = ? WHERE a = ? and b = ? ", 1, 0, 0); + assertRows(execute("SELECT d,e from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row(0, 1)); + + if (flush) + FBUtilities.waitOnFutures(ks.flush()); + + + //Change d value @ TS=2 + executeNet("UPDATE %s USING TIMESTAMP 2 SET d = ? WHERE a = ? and b = ? ", 2, 0, 0); + assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row(2)); + + if (flush) + FBUtilities.waitOnFutures(ks.flush()); + + + //Change d value @ TS=3 + executeNet("UPDATE %s USING TIMESTAMP 3 SET d = ? WHERE a = ? and b = ? ", 1, 0, 0); + assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row(1)); + + + //Tombstone c + executeNet("DELETE FROM %s WHERE a = ? and b = ?", 0, 0); + assertRows(execute("SELECT d from mv")); + + //Add back without D + executeNet("INSERT INTO %s (a, b, c) VALUES (0, 0, 1)"); + + //Make sure D doesn't pop back in. + assertRows(execute("SELECT d from mv WHERE c = ? and a = ? and b = ?", 1, 0, 0), row((Object) null)); + + + //New partition + // insert a row with timestamp 0 + executeNet("INSERT INTO %s (a, b, c, d, e) VALUES (?, ?, ?, ?, ?) USING TIMESTAMP 0", 1, 0, 0, 0, 0); + + // overwrite pk and e with timestamp 1, but don't overwrite d + executeNet("INSERT INTO %s (a, b, c, e) VALUES (?, ?, ?, ?) USING TIMESTAMP 1", 1, 0, 0, 0); + + // delete with timestamp 0 (which should only delete d) + executeNet("DELETE FROM %s USING TIMESTAMP 0 WHERE a = ? AND b = ?", 1, 0); + assertRows(execute("SELECT a, b, c, d, e from mv WHERE c = ? and a = ? and b = ?", 0, 1, 0), + row(1, 0, 0, null, 0) + ); + + executeNet("UPDATE %s USING TIMESTAMP 2 SET c = ? WHERE a = ? AND b = ?", 1, 1, 0); + executeNet("UPDATE %s USING TIMESTAMP 3 SET c = ? WHERE a = ? AND b = ?", 0, 1, 0); + assertRows(execute("SELECT a, b, c, d, e from mv WHERE c = ? and a = ? and b = ?", 0, 1, 0), + row(1, 0, 0, null, 0) + ); + + executeNet("UPDATE %s USING TIMESTAMP 3 SET d = ? WHERE a = ? AND b = ?", 0, 1, 0); + assertRows(execute("SELECT a, b, c, d, e from mv WHERE c = ? and a = ? and b = ?", 0, 1, 0), + row(1, 0, 0, 0, 0) + ); + } + + @Test + public void ttlTest() throws Throwable + { + createTable("CREATE TABLE %s (" + + "a int," + + "b int," + + "c int," + + "d int," + + "PRIMARY KEY (a, b))"); + + executeNet("USE " + keyspace()); + + createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE c IS NOT NULL AND a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (c, a, b)"); + + updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?) USING TTL 3", 1, 1, 1, 1); + + Thread.sleep(TimeUnit.SECONDS.toMillis(1)); + updateView("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 1, 1, 2); + + Thread.sleep(TimeUnit.SECONDS.toMillis(5)); + List<Row> results = executeNet("SELECT d FROM mv WHERE c = 2 AND a = 1 AND b = 1").all(); + Assert.assertEquals(1, results.size()); + Assert.assertTrue("There should be a null result given back due to ttl expiry", results.get(0).isNull(0)); + } + + @Test + public void ttlExpirationTest() throws Throwable + { + createTable("CREATE TABLE %s (" + + "a int," + + "b int," + + "c int," + + "d int," + + "PRIMARY KEY (a, b))"); + + executeNet("USE " + keyspace()); + + createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE c IS NOT NULL AND a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (c, a, b)"); + + updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?) USING TTL 3", 1, 1, 1, 1); + + Thread.sleep(TimeUnit.SECONDS.toMillis(4)); + Assert.assertEquals(0, executeNet("SELECT * FROM mv WHERE c = 1 AND a = 1 AND b = 1").all().size()); + } + + @Test + public void conflictingTimestampTest() throws Throwable + { + createTable("CREATE TABLE %s (" + + "a int," + + "b int," + + "c int," + + "PRIMARY KEY (a, b))"); + + executeNet("USE " + keyspace()); + + createView("mv", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE c IS NOT NULL AND a IS NOT NULL AND b IS NOT NULL PRIMARY KEY (c, a, b)"); + + for (int i = 0; i < 50; i++) + { + updateView("INSERT INTO %s (a, b, c) VALUES (?, ?, ?) USING TIMESTAMP 1", 1, 1, i); + } + + ResultSet mvRows = executeNet("SELECT c FROM mv"); + List<Row> rows = executeNet("SELECT c FROM %s").all(); + Assert.assertEquals("There should be exactly one row in base", 1, rows.size()); + int expected = rows.get(0).getInt("c"); + assertRowsNet(mvRows, row(expected)); + } + + @Test + public void testCreateMvWithTTL() throws Throwable + { + createTable("CREATE TABLE %s (" + + "k int PRIMARY KEY, " + + "c int, " + + "val int) WITH default_time_to_live = 60"); + + execute("USE " + keyspace()); + executeNet("USE " + keyspace()); + + // Must NOT include "default_time_to_live" for Materialized View creation + try + { + createView("mv_ttl1", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE k IS NOT NULL AND c IS NOT NULL PRIMARY KEY (k,c) WITH default_time_to_live = 30"); + Assert.fail("Should fail if TTL is provided for materialized view"); + } + catch (Exception e) + { + } + } + + @Test + public void testAlterMvWithTTL() throws Throwable + { + createTable("CREATE TABLE %s (" + + "k int PRIMARY KEY, " + + "c int, " + + "val int) WITH default_time_to_live = 60"); + + createView("mv_ttl2", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE k IS NOT NULL AND c IS NOT NULL PRIMARY KEY (k,c)"); + + // Must NOT include "default_time_to_live" on alter Materialized View + try + { + executeNet("ALTER MATERIALIZED VIEW %s WITH default_time_to_live = 30"); + Assert.fail("Should fail if TTL is provided while altering materialized view"); + } + catch (Exception e) + { + } + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org