Merge branch 'cassandra-2.2' into cassandra-3.0
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/a91219e1 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/a91219e1 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/a91219e1 Branch: refs/heads/trunk Commit: a91219e12459c86899ab59f8f6706afbbdbc5f89 Parents: 0d5984b 52a827b Author: Carl Yeksigian <c...@apache.org> Authored: Tue Jun 14 10:34:13 2016 -0400 Committer: Carl Yeksigian <c...@apache.org> Committed: Tue Jun 14 10:34:13 2016 -0400 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../restrictions/StatementRestrictions.java | 8 +- .../cql3/statements/DeleteStatement.java | 15 ++- .../operations/InsertUpdateIfConditionTest.java | 120 ++++++++++++++++++- 4 files changed, 132 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/a91219e1/CHANGES.txt ---------------------------------------------------------------------- diff --cc CHANGES.txt index 8a04077,d0ca37f..2c42c94 --- a/CHANGES.txt +++ b/CHANGES.txt @@@ -1,29 -1,5 +1,30 @@@ -2.2.7 +3.0.8 + * Add TimeWindowCompactionStrategy (CASSANDRA-9666) +Merged from 2.2: * StorageService shutdown hook should use a volatile variable (CASSANDRA-11984) +Merged from 2.1: ++ * Allow LWT operation on static column with only partition keys (CASSANDRA-10532) + * Create interval tree over canonical sstables to avoid missing sstables during streaming (CASSANDRA-11886) + * cqlsh COPY FROM: shutdown parent cluster after forking, to avoid corrupting SSL connections (CASSANDRA-11749) + + +3.0.7 + * Fix legacy serialization of Thrift-generated non-compound range tombstones + when communicating with 2.x nodes (CASSANDRA-11930) + * Fix Directories instantiations where CFS.initialDirectories should be used (CASSANDRA-11849) + * Avoid referencing DatabaseDescriptor in AbstractType (CASSANDRA-11912) + * Fix sstables not being protected from removal during index build (CASSANDRA-11905) + * cqlsh: Suppress stack trace from Read/WriteFailures (CASSANDRA-11032) + * Remove unneeded code to repair index summaries that have + been improperly down-sampled (CASSANDRA-11127) + * Avoid WriteTimeoutExceptions during commit log replay due to materialized + view lock contention (CASSANDRA-11891) + * Prevent OOM failures on SSTable corruption, improve tests for corruption detection (CASSANDRA-9530) + * Use CFS.initialDirectories when clearing snapshots (CASSANDRA-11705) + * Allow compaction strategies to disable early open (CASSANDRA-11754) + * Refactor Materialized View code (CASSANDRA-11475) + * Update Java Driver (CASSANDRA-11615) +Merged from 2.2: * Persist local metadata earlier in startup sequence (CASSANDRA-11742) * Run CommitLog tests with different compression settings (CASSANDRA-9039) * cqlsh: fix tab completion for case-sensitive identifiers (CASSANDRA-11664) http://git-wip-us.apache.org/repos/asf/cassandra/blob/a91219e1/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java ---------------------------------------------------------------------- diff --cc src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java index 6ee554e,5b7c58d..ae0c9c4 --- a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java +++ b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java @@@ -773,19 -601,8 +773,19 @@@ public final class StatementRestriction checkFalse(selectsOnlyStaticColumns, "Queries using 2ndary indexes don't support selecting only static columns"); } - public void reverse() + /** + * Checks that all the primary key columns (partition key and clustering columns) are restricted by an equality + * relation ('=' or 'IN'). + * + * @return <code>true</code> if all the primary key columns are restricted by an equality relation. + */ + public boolean hasAllPKColumnsRestrictedByEqualities() { - clusteringColumnsRestrictions = new ReversedPrimaryKeyRestrictions(clusteringColumnsRestrictions); + return !isPartitionKeyRestrictionsOnToken() - && !hasUnrestrictedPartitionKeyComponents() - && (partitionKeyRestrictions.isEQ() || partitionKeyRestrictions.isIN()) - && !hasUnrestrictedClusteringColumns() - && (clusteringColumnsRestrictions.isEQ() || clusteringColumnsRestrictions.isIN()); ++ && !hasUnrestrictedPartitionKeyComponents() ++ && (partitionKeyRestrictions.isEQ() || partitionKeyRestrictions.isIN()) ++ && !hasUnrestrictedClusteringColumns() ++ && (clusteringColumnsRestrictions.isEQ() || clusteringColumnsRestrictions.isIN()); } + } http://git-wip-us.apache.org/repos/asf/cassandra/blob/a91219e1/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java ---------------------------------------------------------------------- diff --cc src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java index daeecfe,397928d..4888b43 --- a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java @@@ -149,26 -150,10 +149,33 @@@ public class DeleteStatement extends Mo Operation op = deletion.prepare(cfm.ksName, def); op.collectMarkerSpecification(boundNames); - stmt.addOperation(op); + operations.add(op); + } + + StatementRestrictions restrictions = newRestrictions(cfm, + boundNames, + operations, + whereClause, + conditions); + + DeleteStatement stmt = new DeleteStatement(boundNames.size(), + cfm, + operations, + restrictions, + conditions, + attrs); + - if (stmt.hasConditions()) - checkTrue(restrictions.hasAllPKColumnsRestrictedByEqualities(), - "DELETE statements must restrict all PRIMARY KEY columns with equality relations" + - " in order to use IF conditions"); ++ if (stmt.hasConditions() && !restrictions.hasAllPKColumnsRestrictedByEqualities()) ++ { ++ checkFalse(operations.appliesToRegularColumns(), ++ "DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns"); ++ ++ // All primary keys must be specified, unless this has static column restrictions ++ checkFalse(conditions.appliesToRegularColumns(), ++ "DELETE statements must restrict all PRIMARY KEY columns with equality relations" + ++ " in order to use IF condition on non static columns"); + } + - stmt.processWhereClause(whereClause, boundNames); return stmt; } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/a91219e1/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java ---------------------------------------------------------------------- diff --cc test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java index ade80bb,ca19a51..2d59a11 --- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java @@@ -188,25 -175,11 +188,25 @@@ public class InsertUpdateIfConditionTes assertRows(execute("DELETE FROM %s WHERE k='k' AND i=0 IF EXISTS"), row(false)); // CASSANDRA-6430 - assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to use IF conditions", - assertInvalid("DELETE FROM %s WHERE k = 'k' IF EXISTS"); - assertInvalid("DELETE FROM %s WHERE k = 'k' IF v = 'foo'"); - assertInvalid("DELETE FROM %s WHERE i = 0 IF EXISTS"); - assertInvalid("DELETE FROM %s WHERE k = 0 AND i > 0 IF EXISTS"); - assertInvalid("DELETE FROM %s WHERE k = 0 AND i > 0 IF v = 'foo'"); ++ assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns", + "DELETE FROM %s WHERE k = 'k' IF EXISTS"); - assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to use IF conditions", ++ assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns", + "DELETE FROM %s WHERE k = 'k' IF v = 'foo'"); + assertInvalidMessage("Some partition key parts are missing: k", + "DELETE FROM %s WHERE i = 0 IF EXISTS"); + + assertInvalidMessage("Invalid INTEGER constant (0) for \"k\" of type text", + "DELETE FROM %s WHERE k = 0 AND i > 0 IF EXISTS"); + assertInvalidMessage("Invalid INTEGER constant (0) for \"k\" of type text", + "DELETE FROM %s WHERE k = 0 AND i > 0 IF v = 'foo'"); - assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to use IF conditions", ++ assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns", + "DELETE FROM %s WHERE k = 'k' AND i > 0 IF EXISTS"); - assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to use IF conditions", ++ assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns", + "DELETE FROM %s WHERE k = 'k' AND i > 0 IF v = 'foo'"); + assertInvalidMessage("IN on the clustering key columns is not supported with conditional deletions", + "DELETE FROM %s WHERE k = 'k' AND i IN (0, 1) IF v = 'foo'"); + assertInvalidMessage("IN on the clustering key columns is not supported with conditional deletions", + "DELETE FROM %s WHERE k = 'k' AND i IN (0, 1) IF EXISTS"); createTable("CREATE TABLE %s(k int, s int static, i int, v text, PRIMARY KEY(k, i))"); execute("INSERT INTO %s (k, s, i, v) VALUES ( 1, 1, 2, '1')"); @@@ -338,6 -311,119 +338,118 @@@ } /** + * Test CASSANDRA-10532 + */ + @Test + public void testStaticColumnsCasDelete() throws Throwable + { + createTable("CREATE TABLE %s (pk int, ck int, static_col int static, value int, PRIMARY KEY (pk, ck))"); + execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 2); + execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 3, 4); + execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 5, 6); + execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 7, 8); + execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 2, 1, 2); + execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1); + + assertRows(execute("DELETE static_col FROM %s WHERE pk = ? IF static_col = ?", 1, 2), row(false, 1)); + assertRows(execute("DELETE static_col FROM %s WHERE pk = ? IF static_col = ?", 1, 1), row(true)); + + assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"), + row(1, 1, null, 2), + row(1, 3, null, 4), + row(1, 5, null, 6), + row(1, 7, null, 8)); + execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1); + - assertInvalidMessage("DELETE statements must restrict all PARTITION KEY columns with equality relations in order " + - "to use IF conditions on static columns, but column 'pk' is not restricted", ++ assertInvalidMessage("Some partition key parts are missing: pk", + "DELETE static_col FROM %s WHERE ck = ? IF static_col = ?", 1, 1); + - assertInvalidMessage("Invalid restriction on clustering column ck since the DELETE statement modifies only static columns", ++ assertInvalidMessage("Invalid restrictions on clustering columns since the DELETE statement modifies only static columns", + "DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF static_col = ?", 1, 1, 1); + - assertInvalidMessage("Primary key column 'ck' must be specified in order to delete column 'value'", ++ assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns", + "DELETE static_col, value FROM %s WHERE pk = ? IF static_col = ?", 1, 1); + + // Same query but with an invalid condition - assertInvalidMessage("Primary key column 'ck' must be specified in order to delete column 'value'", ++ assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order to delete non static columns", + "DELETE static_col, value FROM %s WHERE pk = ? IF static_col = ?", 1, 2); + + // DELETE of an underspecified PRIMARY KEY should not succeed if static is not only restriction - assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations in order " + - "to use IF conditions, but column 'ck' is not restricted", ++ assertInvalidMessage("DELETE statements must restrict all PRIMARY KEY columns with equality relations" + ++ " in order to use IF condition on non static columns", + "DELETE static_col FROM %s WHERE pk = ? IF value = ? AND static_col = ?", 1, 2, 1); + + assertRows(execute("DELETE value FROM %s WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 2, 2), row(false, 2, 1)); + assertRows(execute("DELETE value FROM %s WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 2, 1), row(true)); + assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"), + row(1, 1, 1, null), + row(1, 3, 1, 4), + row(1, 5, 1, 6), + row(1, 7, 1, 8)); + + assertRows(execute("DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF value = ?", 1, 5, 10), row(false, 6)); + assertRows(execute("DELETE static_col FROM %s WHERE pk = ? AND ck = ? IF value = ?", 1, 5, 6), row(true)); + assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"), + row(1, 1, null, null), + row(1, 3, null, 4), + row(1, 5, null, 6), + row(1, 7, null, 8)); + } + + @Test + public void testStaticColumnsCasUpdate() throws Throwable + { + createTable("CREATE TABLE %s (pk int, ck int, static_col int static, value int, PRIMARY KEY (pk, ck))"); + execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 1, 2); + execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 3, 4); + execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 5, 6); + execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 1, 7, 8); + execute("INSERT INTO %s (pk, ck, value) VALUES (?, ?, ?)", 2, 1, 2); + execute("INSERT INTO %s (pk, static_col) VALUES (?, ?)", 1, 1); + + assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? IF static_col = ?", 3, 1, 2), row(false, 1)); + assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? IF static_col = ?", 2, 1, 1), row(true)); + + assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"), + row(1, 1, 2, 2), + row(1, 3, 2, 4), + row(1, 5, 2, 6), + row(1, 7, 2, 8)); + - assertInvalidMessage("Missing mandatory PRIMARY KEY part pk", ++ assertInvalidMessage("Some partition key parts are missing: pk", + "UPDATE %s SET static_col = ? WHERE ck = ? IF static_col = ?", 3, 1, 1); + - assertInvalidMessage("Invalid restriction on clustering column ck since the UPDATE statement modifies only static columns", ++ assertInvalidMessage("Invalid restrictions on clustering columns since the UPDATE statement modifies only static columns", + "UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF static_col = ?", 3, 1, 1, 1); + - assertInvalidMessage("Missing mandatory PRIMARY KEY part ck", ++ assertInvalidMessage("Some clustering keys are missing: ck", + "UPDATE %s SET static_col = ?, value = ? WHERE pk = ? IF static_col = ?", 3, 1, 1, 2); + + // Same query but with an invalid condition - assertInvalidMessage("Missing mandatory PRIMARY KEY part ck", ++ assertInvalidMessage("Some clustering keys are missing: ck", + "UPDATE %s SET static_col = ?, value = ? WHERE pk = ? IF static_col = ?", 3, 1, 1, 1); + - assertInvalidMessage("Missing mandatory PRIMARY KEY part ck", ++ assertInvalidMessage("Some clustering keys are missing: ck", + "UPDATE %s SET static_col = ? WHERE pk = ? IF value = ? AND static_col = ?", 3, 1, 4, 2); + + assertRows(execute("UPDATE %s SET value = ? WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 3, 1, 1, 3, 2), row(false, 2, 2)); + assertRows(execute("UPDATE %s SET value = ? WHERE pk = ? AND ck = ? IF value = ? AND static_col = ?", 1, 1, 1, 2, 2), row(true)); + assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"), + row(1, 1, 2, 1), + row(1, 3, 2, 4), + row(1, 5, 2, 6), + row(1, 7, 2, 8)); + + assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF value = ?", 3, 1, 1, 2), row(false, 1)); + assertRows(execute("UPDATE %s SET static_col = ? WHERE pk = ? AND ck = ? IF value = ?", 1, 1, 1, 1), row(true)); + assertRows(execute("SELECT pk, ck, static_col, value FROM %s WHERE pk = 1"), + row(1, 1, 1, 1), + row(1, 3, 1, 4), + row(1, 5, 1, 6), + row(1, 7, 1, 8)); + } + + /** * Migrated from cql_tests.py:TestCQL.bug_6069_test() */ @Test