Merge branch 'cassandra-3.0' into trunk

This commit is contained in:
Sylvain Lebresne 2015-09-18 12:13:21 +02:00
commit 5400b93bbc
3 changed files with 85 additions and 9 deletions

View File

@ -3,6 +3,7 @@
3.0.0-rc1
* Fix minor bugs in MV handling (CASSANDRA-10362)
* Allow custom indexes with 0,1 or multiple target columns (CASSANDRA-10124)
* Improve MV schema representation (CASSANDRA-9921)
* Add flag to enable/disable coordinator batchlog for MV writes (CASSANDRA-10230)

View File

@ -36,6 +36,7 @@ import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.config.ViewDefinition;
import org.apache.cassandra.config.Schema;
import org.apache.cassandra.cql3.ColumnIdentifier;
import org.apache.cassandra.db.AbstractReadCommandBuilder;
import org.apache.cassandra.db.AbstractReadCommandBuilder.SinglePartitionSliceBuilder;
import org.apache.cassandra.db.CBuilder;
import org.apache.cassandra.db.Clustering;
@ -62,6 +63,7 @@ import org.apache.cassandra.db.rows.Row;
import org.apache.cassandra.db.rows.RowIterator;
import org.apache.cassandra.schema.KeyspaceMetadata;
import org.apache.cassandra.service.pager.QueryPager;
import org.apache.cassandra.utils.FBUtilities;
/**
* A View copies data from a base table into a view table which can be queried independently from the
@ -214,11 +216,12 @@ public class View
// Check each row for deletion or update
for (Row row : partition)
{
if (row.hasComplexDeletion())
return true;
if (!row.deletion().isLive())
return true;
if (row.primaryKeyLivenessInfo().isLive(FBUtilities.nowInSeconds()))
return true;
for (ColumnData data : row)
{
if (definition.metadata.getColumnDefinition(data.column().name) != null)
@ -434,7 +437,11 @@ public class View
// entire partition of data which is not distributed on a single partition node.
DecoratedKey dk = rowSet.dk;
if (deletionInfo.hasRanges())
if (!deletionInfo.getPartitionDeletion().isLive())
{
command = SinglePartitionReadCommand.fullPartitionRead(baseCfs.metadata, rowSet.nowInSec, dk);
}
else
{
SinglePartitionSliceBuilder builder = new SinglePartitionSliceBuilder(baseCfs, dk);
Iterator<RangeTombstone> tombstones = deletionInfo.rangeIterator(false);
@ -447,10 +454,6 @@ public class View
command = builder.build();
}
else
{
command = SinglePartitionReadCommand.fullPartitionRead(baseCfs.metadata, rowSet.nowInSec, dk);
}
}
if (command == null)

View File

@ -186,6 +186,9 @@ public class ViewTest extends CQLTester
"bigintval bigint, " +
"PRIMARY KEY((k, asciival)))");
execute("USE " + keyspace());
executeNet(protocolVersion, "USE " + keyspace());
// Must include "IS NOT NULL" for primary keys
try
{
@ -1335,8 +1338,8 @@ public class ViewTest extends CQLTester
createView("mv3", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE 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 b IS NOT NULL AND c IS NOT NULL PRIMARY KEY (a, c, b) WITH CLUSTERING ORDER BY (c DESC)");
updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?) USING TIMESTAMP 1", 1, 1, 1, 1);
updateView("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?) USING TIMESTAMP 1", 1, 2, 2, 2);
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(protocolVersion, "SELECT b FROM mv1");
assertRowsNet(protocolVersion, mvRows,
@ -1384,4 +1387,73 @@ public class ViewTest extends CQLTester
Assert.assertEquals("Cannot use DROP TABLE on Materialized View", e.getMessage());
}
}
@Test
public void testMultipleDeletes() throws Throwable
{
createTable("CREATE TABLE %s (" +
"a int," +
"b int," +
"PRIMARY KEY (a, b))");
executeNet(protocolVersion, "USE " + keyspace());
createView("mv1", "CREATE MATERIALIZED VIEW %s AS SELECT * FROM %%s WHERE b IS NOT NULL PRIMARY KEY (b, a)");
updateView("INSERT INTO %s (a, b) VALUES (?, ?)", 1, 1);
updateView("INSERT INTO %s (a, b) VALUES (?, ?)", 1, 2);
updateView("INSERT INTO %s (a, b) VALUES (?, ?)", 1, 3);
ResultSet mvRows = executeNet(protocolVersion, "SELECT a, b FROM mv1");
assertRowsNet(protocolVersion, mvRows,
row(1, 1),
row(1, 2),
row(1, 3));
updateView(String.format("BEGIN UNLOGGED BATCH " +
"DELETE FROM %s WHERE a = 1 AND b > 1 AND b < 3;" +
"DELETE FROM %s WHERE a = 1;" +
"APPLY BATCH", currentTable(), currentTable()));
mvRows = executeNet(protocolVersion, "SELECT a, b FROM mv1");
assertRowsNet(protocolVersion, mvRows);
}
@Test
public void testPrimaryKeyOnlyTable() throws Throwable
{
createTable("CREATE TABLE %s (" +
"a int," +
"b int," +
"PRIMARY KEY (a, b))");
executeNet(protocolVersion, "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 b IS NOT NULL PRIMARY KEY (b, a)");
updateView("INSERT INTO %s (a, b) VALUES (?, ?)", 1, 1);
ResultSet mvRows = executeNet(protocolVersion, "SELECT a, b FROM mv1");
assertRowsNet(protocolVersion, mvRows, row(1, 1));
}
@Test
public void testPartitionKeyOnlyTable() throws Throwable
{
createTable("CREATE TABLE %s (" +
"a int," +
"b int," +
"PRIMARY KEY ((a, b)))");
executeNet(protocolVersion, "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(protocolVersion, "SELECT a, b FROM mv1");
assertRowsNet(protocolVersion, mvRows, row(1, 1));
}
}