Repository: cassandra Updated Branches: refs/heads/trunk 540e9cf75 -> 1faca1cb5
Fix AssertionError when binding nested collections in DELETE patch by Stefania Alborghetti; reviewed by Benjamin Lerer for CASSANDRA-8900 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/bcf0ec68 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/bcf0ec68 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/bcf0ec68 Branch: refs/heads/trunk Commit: bcf0ec681912e891d66a7b0ba28ff3d41ab3e304 Parents: ff14d7a Author: Stefania Alborghetti <[email protected]> Authored: Wed Mar 11 15:09:21 2015 +0800 Committer: Aleksey Yeschenko <[email protected]> Committed: Mon Mar 23 18:54:11 2015 +0300 ---------------------------------------------------------------------- CHANGES.txt | 1 + src/java/org/apache/cassandra/cql3/Lists.java | 4 +- src/java/org/apache/cassandra/cql3/Maps.java | 3 +- .../org/apache/cassandra/cql3/Operation.java | 2 +- src/java/org/apache/cassandra/cql3/Sets.java | 25 +- .../cassandra/cql3/FrozenCollectionsTest.java | 260 +++++++++++++++++++ 6 files changed, 286 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/bcf0ec68/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 924bdcf..0e75973 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.1.4 + * Fix AssertionError when binding nested collections in DELETE (CASSANDRA-8900) * Check for overlap with non-early sstables in LCS (CASSANDRA-8739) * Only calculate max purgable timestamp if we have to (CASSANDRA-8914) * (cqlsh) Greatly improve performance of COPY FROM (CASSANDRA-8225) http://git-wip-us.apache.org/repos/asf/cassandra/blob/bcf0ec68/src/java/org/apache/cassandra/cql3/Lists.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/Lists.java b/src/java/org/apache/cassandra/cql3/Lists.java index 26d5de2..fc81900 100644 --- a/src/java/org/apache/cassandra/cql3/Lists.java +++ b/src/java/org/apache/cassandra/cql3/Lists.java @@ -494,10 +494,8 @@ public abstract class Lists if (index == null) throw new InvalidRequestException("Invalid null value for list index"); - assert index instanceof Constants.Value; - List<Cell> existingList = params.getPrefetchedList(rowKey, column.name); - int idx = ByteBufferUtil.toInt(((Constants.Value)index).bytes); + int idx = ByteBufferUtil.toInt(index.get(params.options)); if (idx < 0 || idx >= existingList.size()) throw new InvalidRequestException(String.format("List index %d out of bound, list has size %d", idx, existingList.size())); http://git-wip-us.apache.org/repos/asf/cassandra/blob/bcf0ec68/src/java/org/apache/cassandra/cql3/Maps.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/Maps.java b/src/java/org/apache/cassandra/cql3/Maps.java index 5b58833..8a64663 100644 --- a/src/java/org/apache/cassandra/cql3/Maps.java +++ b/src/java/org/apache/cassandra/cql3/Maps.java @@ -378,9 +378,8 @@ public abstract class Maps Term.Terminal key = t.bind(params.options); if (key == null) throw new InvalidRequestException("Invalid null map key"); - assert key instanceof Constants.Value; - CellName cellName = cf.getComparator().create(prefix, column, ((Constants.Value)key).bytes); + CellName cellName = cf.getComparator().create(prefix, column, key.get(params.options)); cf.addColumn(params.makeTombstone(cellName)); } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/bcf0ec68/src/java/org/apache/cassandra/cql3/Operation.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/Operation.java b/src/java/org/apache/cassandra/cql3/Operation.java index 816acb2..ac25e29 100644 --- a/src/java/org/apache/cassandra/cql3/Operation.java +++ b/src/java/org/apache/cassandra/cql3/Operation.java @@ -414,7 +414,7 @@ public abstract class Operation return new Lists.DiscarderByIndex(receiver, idx); case SET: Term elt = element.prepare(keyspace, Sets.valueSpecOf(receiver)); - return new Sets.Discarder(receiver, elt); + return new Sets.ElementDiscarder(receiver, elt); case MAP: Term key = element.prepare(keyspace, Maps.keySpecOf(receiver)); return new Maps.DiscarderByKey(receiver, key); http://git-wip-us.apache.org/repos/asf/cassandra/blob/bcf0ec68/src/java/org/apache/cassandra/cql3/Sets.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/Sets.java b/src/java/org/apache/cassandra/cql3/Sets.java index c5a8e05..a7e146f 100644 --- a/src/java/org/apache/cassandra/cql3/Sets.java +++ b/src/java/org/apache/cassandra/cql3/Sets.java @@ -315,9 +315,9 @@ public abstract class Sets return; // This can be either a set or a single element - Set<ByteBuffer> toDiscard = value instanceof Constants.Value - ? Collections.singleton(((Constants.Value)value).bytes) - : ((Sets.Value)value).elements; + Set<ByteBuffer> toDiscard = value instanceof Sets.Value + ? ((Sets.Value)value).elements + : Collections.singleton(value.get(params.options)); for (ByteBuffer bb : toDiscard) { @@ -325,4 +325,23 @@ public abstract class Sets } } } + + public static class ElementDiscarder extends Operation + { + public ElementDiscarder(ColumnDefinition column, Term k) + { + super(column, k); + } + + public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException + { + assert column.type.isMultiCell() : "Attempted to delete a single element in a frozen set"; + Term.Terminal elt = t.bind(params.options); + if (elt == null) + throw new InvalidRequestException("Invalid null set element"); + + CellName cellName = cf.getComparator().create(prefix, column, elt.get(params.options)); + cf.addColumn(params.makeTombstone(cellName)); + } + } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/bcf0ec68/test/unit/org/apache/cassandra/cql3/FrozenCollectionsTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/FrozenCollectionsTest.java b/test/unit/org/apache/cassandra/cql3/FrozenCollectionsTest.java index bf7ccfd..bf347f0 100644 --- a/test/unit/org/apache/cassandra/cql3/FrozenCollectionsTest.java +++ b/test/unit/org/apache/cassandra/cql3/FrozenCollectionsTest.java @@ -794,6 +794,266 @@ public class FrozenCollectionsTest extends CQLTester } @Test + public void testFrozenListInMap() throws Throwable + { + createTable("CREATE TABLE %s (k int primary key, m map<frozen<list<int>>, int>)"); + + execute("INSERT INTO %s (k, m) VALUES (1, {[1, 2, 3] : 1})"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, map(list(1, 2, 3), 1))); + + execute("UPDATE %s SET m[[1, 2, 3]]=2 WHERE k=1"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, map(list(1, 2, 3), 2))); + + execute("UPDATE %s SET m = m + ? WHERE k=1", map(list(4, 5, 6), 3)); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, + map(list(1, 2, 3), 2, + list(4, 5, 6), 3))); + + execute("DELETE m[[1, 2, 3]] FROM %s WHERE k = 1"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, map(list(4, 5, 6), 3))); + } + + @Test + public void testFrozenListInSet() throws Throwable + { + createTable("CREATE TABLE %s (k int primary key, s set<frozen<list<int>>>)"); + + execute("INSERT INTO %s (k, s) VALUES (1, {[1, 2, 3]})"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, set(list(1, 2, 3))) + ); + + execute("UPDATE %s SET s = s + ? WHERE k=1", set(list(4, 5, 6))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, set(list(1, 2, 3), list(4, 5, 6))) + ); + + execute("UPDATE %s SET s = s - ? WHERE k=1", set(list(4, 5, 6))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, set(list(1, 2, 3))) + ); + + execute("DELETE s[[1, 2, 3]] FROM %s WHERE k = 1"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, null) + ); + } + + @Test + public void testFrozenListInList() throws Throwable + { + createTable("CREATE TABLE %s (k int primary key, l list<frozen<list<int>>>)"); + + execute("INSERT INTO %s (k, l) VALUES (1, [[1, 2, 3]])"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(list(1, 2, 3))) + ); + + execute("UPDATE %s SET l[?]=? WHERE k=1", 0, list(4, 5, 6)); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(list(4, 5, 6))) + ); + + execute("UPDATE %s SET l = ? + l WHERE k=1", list(list(1, 2, 3))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(list(1, 2, 3), list(4, 5, 6))) + ); + + execute("UPDATE %s SET l = l + ? WHERE k=1", list(list(7, 8, 9))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(list(1, 2, 3), list(4, 5, 6), list(7, 8, 9))) + ); + + execute("UPDATE %s SET l = l - ? WHERE k=1", list(list(4, 5, 6))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(list(1, 2, 3), list(7, 8, 9))) + ); + + execute("DELETE l[0] FROM %s WHERE k = 1"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(list(7, 8, 9))) + ); + } + + @Test + public void testFrozenMapInMap() throws Throwable + { + createTable("CREATE TABLE %s (k int primary key, m map<frozen<map<int, int>>, int>)"); + + execute("INSERT INTO %s (k, m) VALUES (1, {{1 : 1, 2 : 2} : 1})"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, map(map(1, 1, 2, 2), 1))); + + execute("UPDATE %s SET m[?]=2 WHERE k=1", map(1, 1, 2, 2)); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, map(map(1, 1, 2, 2), 2))); + + execute("UPDATE %s SET m = m + ? WHERE k=1", map(map(3, 3, 4, 4), 3)); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, + map(map(1, 1, 2, 2), 2, + map(3, 3, 4, 4), 3))); + + execute("DELETE m[?] FROM %s WHERE k = 1", map(1, 1, 2, 2)); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, map(map(3, 3, 4, 4), 3))); + } + + @Test + public void testFrozenMapInSet() throws Throwable + { + createTable("CREATE TABLE %s (k int primary key, s set<frozen<map<int, int>>>)"); + + execute("INSERT INTO %s (k, s) VALUES (1, {{1 : 1, 2 : 2}})"); + + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, set(map(1, 1, 2, 2))) + ); + + execute("UPDATE %s SET s = s + ? WHERE k=1", set(map(3, 3, 4, 4))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, set(map(1, 1, 2, 2), map(3, 3, 4, 4))) + ); + + execute("UPDATE %s SET s = s - ? WHERE k=1", set(map(3, 3, 4, 4))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, set(map(1, 1, 2, 2))) + ); + + execute("DELETE s[?] FROM %s WHERE k = 1", map(1, 1, 2, 2)); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, null) + ); + } + + @Test + public void testFrozenMapInList() throws Throwable + { + createTable("CREATE TABLE %s (k int primary key, l list<frozen<map<int, int>>>)"); + + execute("INSERT INTO %s (k, l) VALUES (1, [{1 : 1, 2 : 2}])"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(map(1, 1, 2, 2))) + ); + + execute("UPDATE %s SET l[?]=? WHERE k=1", 0, map(3, 3, 4, 4)); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(map(3, 3, 4, 4))) + ); + + execute("UPDATE %s SET l = ? + l WHERE k=1", list(map(1, 1, 2, 2))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(map(1, 1, 2, 2), map(3, 3, 4, 4))) + ); + + execute("UPDATE %s SET l = l + ? WHERE k=1", list(map(5, 5, 6, 6))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(map(1, 1, 2, 2), map(3, 3, 4, 4), map(5, 5, 6, 6))) + ); + + execute("UPDATE %s SET l = l - ? WHERE k=1", list(map(3, 3, 4, 4))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(map(1, 1, 2, 2), map(5, 5, 6, 6))) + ); + + execute("DELETE l[0] FROM %s WHERE k = 1"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(map(5, 5, 6, 6))) + ); + } + + @Test + public void testFrozenSetInMap() throws Throwable + { + createTable("CREATE TABLE %s (k int primary key, m map<frozen<set<int>>, int>)"); + + execute("INSERT INTO %s (k, m) VALUES (1, {{1, 2, 3} : 1})"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, map(set(1, 2, 3), 1))); + + execute("UPDATE %s SET m[?]=2 WHERE k=1", set(1, 2, 3)); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, map(set(1, 2, 3), 2))); + + execute("UPDATE %s SET m = m + ? WHERE k=1", map(set(4, 5, 6), 3)); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, + map(set(1, 2, 3), 2, + set(4, 5, 6), 3))); + + execute("DELETE m[?] FROM %s WHERE k = 1", set(1, 2, 3)); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, map(set(4, 5, 6), 3))); + } + + @Test + public void testFrozenSetInSet() throws Throwable + { + createTable("CREATE TABLE %s (k int primary key, s set<frozen<set<int>>>)"); + + execute("INSERT INTO %s (k, s) VALUES (1, {{1, 2, 3}})"); + + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, set(set(1, 2, 3))) + ); + + execute("UPDATE %s SET s = s + ? WHERE k=1", set(set(4, 5, 6))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, set(set(1, 2, 3), set(4, 5, 6))) + ); + + execute("UPDATE %s SET s = s - ? WHERE k=1", set(set(4, 5, 6))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, set(set(1, 2, 3))) + ); + + execute("DELETE s[?] FROM %s WHERE k = 1", set(1, 2, 3)); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, null) + ); + } + + @Test + public void testFrozenSetInList() throws Throwable + { + createTable("CREATE TABLE %s (k int primary key, l list<frozen<set<int>>>)"); + + execute("INSERT INTO %s (k, l) VALUES (1, [{1, 2, 3}])"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(set(1, 2, 3))) + ); + + execute("UPDATE %s SET l[?]=? WHERE k=1", 0, set(4, 5, 6)); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(set(4, 5, 6))) + ); + + execute("UPDATE %s SET l = ? + l WHERE k=1", list(set(1, 2, 3))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(set(1, 2, 3), set(4, 5, 6))) + ); + + execute("UPDATE %s SET l = l + ? WHERE k=1", list(set(7, 8, 9))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(set(1, 2, 3), set(4, 5, 6), set(7, 8, 9))) + ); + + execute("UPDATE %s SET l = l - ? WHERE k=1", list(set(4, 5, 6))); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(set(1, 2, 3), set(7, 8, 9))) + ); + + execute("DELETE l[0] FROM %s WHERE k = 1"); + assertRows(execute("SELECT * FROM %s WHERE k = 1"), + row(1, list(set(7, 8, 9))) + ); + } + + @Test public void testUserDefinedTypes() throws Throwable { String myType = createType("CREATE TYPE %s (a set<int>, b tuple<list<int>>)");
