Repository: cassandra Updated Branches: refs/heads/trunk 795c1f36e -> 471835815
Add additional unit tests for batch behavior, TTLs, Timestamps Patch by Jeff Jirsa; Reviewed by Jason Brown for CASSANDRA-13846 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/47183581 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/47183581 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/47183581 Branch: refs/heads/trunk Commit: 471835815811d4de42474a3e3899a42cb6d969ce Parents: 795c1f3 Author: Jeff Jirsa <jji...@apple.com> Authored: Sun Jul 9 16:16:29 2017 -0700 Committer: Jeff Jirsa <jji...@apple.com> Committed: Mon Sep 11 15:59:44 2017 -0700 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../apache/cassandra/batchlog/BatchTest.java | 107 ------- .../apache/cassandra/batchlog/BatchlogTest.java | 107 +++++++ .../cql3/validation/entities/CountersTest.java | 68 ++++ .../cql3/validation/entities/TimestampTest.java | 37 +++ .../cql3/validation/operations/BatchTest.java | 320 ++++++++++++++++++- 6 files changed, 528 insertions(+), 112 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/47183581/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 5e9cb72..c688d6d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 4.0 + * Add additional unit tests for batch behavior, TTLs, Timestamps (CASSANDRA-13846) * Add keyspace and table name in schema validation exception (CASSANDRA-13845) * Emit metrics whenever we hit tombstone failures and warn thresholds (CASSANDRA-13771) * Make netty EventLoopGroups daemon threads (CASSANDRA-13837) http://git-wip-us.apache.org/repos/asf/cassandra/blob/47183581/test/unit/org/apache/cassandra/batchlog/BatchTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/batchlog/BatchTest.java b/test/unit/org/apache/cassandra/batchlog/BatchTest.java deleted file mode 100644 index 8ed1811..0000000 --- a/test/unit/org/apache/cassandra/batchlog/BatchTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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.batchlog; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.UUID; - -import org.junit.BeforeClass; -import org.junit.Test; - -import org.apache.cassandra.SchemaLoader; -import org.apache.cassandra.schema.TableMetadata; -import org.apache.cassandra.db.Keyspace; -import org.apache.cassandra.db.Mutation; -import org.apache.cassandra.db.RowUpdateBuilder; -import org.apache.cassandra.db.marshal.BytesType; -import org.apache.cassandra.exceptions.ConfigurationException; -import org.apache.cassandra.io.util.DataInputBuffer; -import org.apache.cassandra.io.util.DataInputPlus; -import org.apache.cassandra.io.util.DataOutputBuffer; -import org.apache.cassandra.net.MessagingService; -import org.apache.cassandra.schema.KeyspaceParams; -import org.apache.cassandra.utils.FBUtilities; -import org.apache.cassandra.utils.UUIDGen; - -import static org.apache.cassandra.utils.ByteBufferUtil.bytes; -import static org.junit.Assert.assertEquals; - -public class BatchTest -{ - private static final String KEYSPACE = "BatchRequestTest"; - private static final String CF_STANDARD = "Standard"; - - @BeforeClass - public static void defineSchema() throws ConfigurationException - { - SchemaLoader.prepareServer(); - SchemaLoader.createKeyspace(KEYSPACE, - KeyspaceParams.simple(1), - SchemaLoader.standardCFMD(KEYSPACE, CF_STANDARD, 1, BytesType.instance)); - } - - @Test - public void testSerialization() throws IOException - { - TableMetadata cfm = Keyspace.open(KEYSPACE).getColumnFamilyStore(CF_STANDARD).metadata(); - - long now = FBUtilities.timestampMicros(); - int version = MessagingService.current_version; - UUID uuid = UUIDGen.getTimeUUID(); - - List<Mutation> mutations = new ArrayList<>(10); - for (int i = 0; i < 10; i++) - { - mutations.add(new RowUpdateBuilder(cfm, FBUtilities.timestampMicros(), bytes(i)) - .clustering("name" + i) - .add("val", "val" + i) - .build()); - } - - Batch batch1 = Batch.createLocal(uuid, now, mutations); - assertEquals(uuid, batch1.id); - assertEquals(now, batch1.creationTime); - assertEquals(mutations, batch1.decodedMutations); - - DataOutputBuffer out = new DataOutputBuffer(); - Batch.serializer.serialize(batch1, out, version); - - assertEquals(out.getLength(), Batch.serializer.serializedSize(batch1, version)); - - DataInputPlus dis = new DataInputBuffer(out.getData()); - Batch batch2 = Batch.serializer.deserialize(dis, version); - - assertEquals(batch1.id, batch2.id); - assertEquals(batch1.creationTime, batch2.creationTime); - assertEquals(batch1.decodedMutations.size(), batch2.encodedMutations.size()); - - Iterator<Mutation> it1 = batch1.decodedMutations.iterator(); - Iterator<ByteBuffer> it2 = batch2.encodedMutations.iterator(); - while (it1.hasNext()) - { - try (DataInputBuffer in = new DataInputBuffer(it2.next().array())) - { - assertEquals(it1.next().toString(), Mutation.serializer.deserialize(in, version).toString()); - } - } - } -} http://git-wip-us.apache.org/repos/asf/cassandra/blob/47183581/test/unit/org/apache/cassandra/batchlog/BatchlogTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/batchlog/BatchlogTest.java b/test/unit/org/apache/cassandra/batchlog/BatchlogTest.java new file mode 100644 index 0000000..8fa4afc --- /dev/null +++ b/test/unit/org/apache/cassandra/batchlog/BatchlogTest.java @@ -0,0 +1,107 @@ +/* + * 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.batchlog; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.UUID; + +import org.junit.BeforeClass; +import org.junit.Test; + +import org.apache.cassandra.SchemaLoader; +import org.apache.cassandra.schema.TableMetadata; +import org.apache.cassandra.db.Keyspace; +import org.apache.cassandra.db.Mutation; +import org.apache.cassandra.db.RowUpdateBuilder; +import org.apache.cassandra.db.marshal.BytesType; +import org.apache.cassandra.exceptions.ConfigurationException; +import org.apache.cassandra.io.util.DataInputBuffer; +import org.apache.cassandra.io.util.DataInputPlus; +import org.apache.cassandra.io.util.DataOutputBuffer; +import org.apache.cassandra.net.MessagingService; +import org.apache.cassandra.schema.KeyspaceParams; +import org.apache.cassandra.utils.FBUtilities; +import org.apache.cassandra.utils.UUIDGen; + +import static org.apache.cassandra.utils.ByteBufferUtil.bytes; +import static org.junit.Assert.assertEquals; + +public class BatchlogTest +{ + private static final String KEYSPACE = "BatchRequestTest"; + private static final String CF_STANDARD = "Standard"; + + @BeforeClass + public static void defineSchema() throws ConfigurationException + { + SchemaLoader.prepareServer(); + SchemaLoader.createKeyspace(KEYSPACE, + KeyspaceParams.simple(1), + SchemaLoader.standardCFMD(KEYSPACE, CF_STANDARD, 1, BytesType.instance)); + } + + @Test + public void testSerialization() throws IOException + { + TableMetadata cfm = Keyspace.open(KEYSPACE).getColumnFamilyStore(CF_STANDARD).metadata(); + + long now = FBUtilities.timestampMicros(); + int version = MessagingService.current_version; + UUID uuid = UUIDGen.getTimeUUID(); + + List<Mutation> mutations = new ArrayList<>(10); + for (int i = 0; i < 10; i++) + { + mutations.add(new RowUpdateBuilder(cfm, FBUtilities.timestampMicros(), bytes(i)) + .clustering("name" + i) + .add("val", "val" + i) + .build()); + } + + Batch batch1 = Batch.createLocal(uuid, now, mutations); + assertEquals(uuid, batch1.id); + assertEquals(now, batch1.creationTime); + assertEquals(mutations, batch1.decodedMutations); + + DataOutputBuffer out = new DataOutputBuffer(); + Batch.serializer.serialize(batch1, out, version); + + assertEquals(out.getLength(), Batch.serializer.serializedSize(batch1, version)); + + DataInputPlus dis = new DataInputBuffer(out.getData()); + Batch batch2 = Batch.serializer.deserialize(dis, version); + + assertEquals(batch1.id, batch2.id); + assertEquals(batch1.creationTime, batch2.creationTime); + assertEquals(batch1.decodedMutations.size(), batch2.encodedMutations.size()); + + Iterator<Mutation> it1 = batch1.decodedMutations.iterator(); + Iterator<ByteBuffer> it2 = batch2.encodedMutations.iterator(); + while (it1.hasNext()) + { + try (DataInputBuffer in = new DataInputBuffer(it2.next().array())) + { + assertEquals(it1.next().toString(), Mutation.serializer.deserialize(in, version).toString()); + } + } + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/47183581/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java index 94e1c52..69ad4d3 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/CountersTest.java @@ -238,4 +238,72 @@ public class CountersTest extends CQLTester assertRows(execute("SELECT k FROM %s"), row(0)); } } + + /* + * Check that a counter batch works as intended + */ + @Test + public void testCounterBatch() throws Throwable + { + createTable("CREATE TABLE %s (userid int, url text, total counter, PRIMARY KEY (userid, url)) WITH COMPACT STORAGE"); + + // Ensure we handle updates to the same CQL row in the same partition properly + execute("BEGIN UNLOGGED BATCH " + + "UPDATE %1$s SET total = total + 1 WHERE userid = 1 AND url = 'http://foo.com'; " + + "UPDATE %1$s SET total = total + 1 WHERE userid = 1 AND url = 'http://foo.com'; " + + "UPDATE %1$s SET total = total + 1 WHERE userid = 1 AND url = 'http://foo.com'; " + + "APPLY BATCH; "); + assertRows(execute("SELECT total FROM %s WHERE userid = 1 AND url = 'http://foo.com'"), + row(3L)); + + // Ensure we handle different CQL rows in the same partition properly + execute("BEGIN UNLOGGED BATCH " + + "UPDATE %1$s SET total = total + 1 WHERE userid = 1 AND url = 'http://bar.com'; " + + "UPDATE %1$s SET total = total + 1 WHERE userid = 1 AND url = 'http://baz.com'; " + + "UPDATE %1$s SET total = total + 1 WHERE userid = 1 AND url = 'http://bad.com'; " + + "APPLY BATCH; "); + assertRows(execute("SELECT url, total FROM %s WHERE userid = 1"), + row("http://bad.com", 1L), + row("http://bar.com", 1L), + row("http://baz.com", 1L), + row("http://foo.com", 3L)); // from previous batch + + // Different counters in the same CQL Row + createTable("CREATE TABLE %s (userid int, url text, first counter, second counter, third counter, PRIMARY KEY (userid, url))"); + execute("BEGIN UNLOGGED BATCH " + + "UPDATE %1$s SET first = first + 1 WHERE userid = 1 AND url = 'http://foo.com'; " + + "UPDATE %1$s SET first = first + 1 WHERE userid = 1 AND url = 'http://foo.com'; " + + "UPDATE %1$s SET second = second + 1 WHERE userid = 1 AND url = 'http://foo.com'; " + + "APPLY BATCH; "); + assertRows(execute("SELECT first, second, third FROM %s WHERE userid = 1 AND url = 'http://foo.com'"), + row(2L, 1L, null)); + + // Different counters in different CQL Rows + execute("BEGIN UNLOGGED BATCH " + + "UPDATE %1$s SET first = first + 1 WHERE userid = 1 AND url = 'http://bad.com'; " + + "UPDATE %1$s SET first = first + 1, second = second + 1 WHERE userid = 1 AND url = 'http://bar.com'; " + + "UPDATE %1$s SET first = first - 1, second = second - 1 WHERE userid = 1 AND url = 'http://bar.com'; " + + "UPDATE %1$s SET second = second + 1 WHERE userid = 1 AND url = 'http://baz.com'; " + + "APPLY BATCH; "); + assertRows(execute("SELECT url, first, second, third FROM %s WHERE userid = 1"), + row("http://bad.com", 1L, null, null), + row("http://bar.com", 0L, 0L, null), + row("http://baz.com", null, 1L, null), + row("http://foo.com", 2L, 1L, null)); // from previous batch + + + // Different counters in different partitions + execute("BEGIN UNLOGGED BATCH " + + "UPDATE %1$s SET first = first + 1 WHERE userid = 2 AND url = 'http://bad.com'; " + + "UPDATE %1$s SET first = first + 1, second = second + 1 WHERE userid = 3 AND url = 'http://bar.com'; " + + "UPDATE %1$s SET first = first - 1, second = second - 1 WHERE userid = 4 AND url = 'http://bar.com'; " + + "UPDATE %1$s SET second = second + 1 WHERE userid = 5 AND url = 'http://baz.com'; " + + "APPLY BATCH; "); + assertRowsIgnoringOrder(execute("SELECT userid, url, first, second, third FROM %s WHERE userid IN (2, 3, 4, 5)"), + row(2, "http://bad.com", 1L, null, null), + row(3, "http://bar.com", 1L, 1L, null), + row(4, "http://bar.com", -1L, -1L, null), + row(5, "http://baz.com", null, 1L, null)); + + } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/47183581/test/unit/org/apache/cassandra/cql3/validation/entities/TimestampTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/TimestampTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/TimestampTest.java index 985a5e0..ddc402c 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/TimestampTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/TimestampTest.java @@ -182,4 +182,41 @@ public class TimestampTest extends CQLTester row(3, 3, 3, 1L)); } + @Test + public void testTimestampAndTTLPrepared() throws Throwable + { + + createTable("CREATE TABLE %s (k int , c int, i int, PRIMARY KEY (k, c))"); + execute("INSERT INTO %s (k, c, i) VALUES (1, 1, 1) USING TIMESTAMP ? AND TTL ?;", 1L,5); + execute("INSERT INTO %s (k, c) VALUES (1, 2) USING TIMESTAMP ? AND TTL ? ;", 1L, 5); + execute("INSERT INTO %s (k, c, i) VALUES (1, 3, 1) USING TIMESTAMP ? AND TTL ?;", 1L, 5); + execute("INSERT INTO %s (k, c) VALUES (2, 2) USING TIMESTAMP ? AND TTL ?;", 2L, 5); + execute("INSERT INTO %s (k, c, i) VALUES (3, 3, 3) USING TIMESTAMP ? AND TTL ?;", 1L, 5); + assertRows(execute("SELECT k, c, i, writetime(i) FROM %s "), + row(1, 1, 1, 1L), + row(1, 2, null, null), + row(1, 3, 1, 1L), + row(2, 2, null, null), + row(3, 3, 3, 1L)); + Thread.sleep(6*1000); + assertEmpty(execute("SELECT k, c, i, writetime(i) FROM %s ")); + } + + @Test + public void testTimestampAndTTLUpdatePrepared() throws Throwable + { + + createTable("CREATE TABLE %s (k int , c int, i int, PRIMARY KEY (k, c))"); + execute("UPDATE %s USING TIMESTAMP ? AND TTL ? SET i=1 WHERE k=1 AND c = 1 ;", 1L, 5); + execute("UPDATE %s USING TIMESTAMP ? AND TTL ? SET i=1 WHERE k=1 AND c = 3 ;", 1L, 5); + execute("UPDATE %s USING TIMESTAMP ? AND TTL ? SET i=1 WHERE k=2 AND c = 2 ;", 2L, 5); + execute("UPDATE %s USING TIMESTAMP ? AND TTL ? SET i=3 WHERE k=3 AND c = 3 ;", 1L, 5); + assertRows(execute("SELECT k, c, i, writetime(i) FROM %s "), + row(1, 1, 1, 1L), + row(1, 3, 1, 1L), + row(2, 2, 1, 2L), + row(3, 3, 3, 1L)); + Thread.sleep(6*1000); + assertEmpty(execute("SELECT k, c, i, writetime(i) FROM %s ")); + } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/47183581/test/unit/org/apache/cassandra/cql3/validation/operations/BatchTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/BatchTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/BatchTest.java index d0bdd15..ae93b6e 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/operations/BatchTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/operations/BatchTest.java @@ -241,7 +241,7 @@ public class BatchTest extends CQLTester } @Test - public void testBatchAndConditionalInteraction() throws Throwable + public void testBatchTTLConditionalInteraction() throws Throwable { createTable(String.format("CREATE TABLE %s.clustering (\n" + @@ -256,10 +256,16 @@ public class BatchTest extends CQLTester execute("DELETE FROM " + KEYSPACE +".clustering WHERE id=1"); String clusteringInsert = "INSERT INTO " + KEYSPACE + ".clustering(id, clustering1, clustering2, clustering3, val) VALUES(%s, %s, %s, %s, %s); "; + String clusteringTTLInsert = "INSERT INTO " + KEYSPACE + ".clustering(id, clustering1, clustering2, clustering3, val) VALUES(%s, %s, %s, %s, %s) USING TTL %s; "; + String clusteringConditionalInsert = "INSERT INTO " + KEYSPACE + ".clustering(id, clustering1, clustering2, clustering3, val) VALUES(%s, %s, %s, %s, %s) IF NOT EXISTS; "; + String clusteringConditionalTTLInsert = "INSERT INTO " + KEYSPACE + ".clustering(id, clustering1, clustering2, clustering3, val) VALUES(%s, %s, %s, %s, %s) IF NOT EXISTS USING TTL %s; "; String clusteringUpdate = "UPDATE " + KEYSPACE + ".clustering SET val=%s WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s ;"; + String clusteringTTLUpdate = "UPDATE " + KEYSPACE + ".clustering USING TTL %s SET val=%s WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s ;"; String clusteringConditionalUpdate = "UPDATE " + KEYSPACE + ".clustering SET val=%s WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s IF val=%s ;"; + String clusteringConditionalTTLUpdate = "UPDATE " + KEYSPACE + ".clustering USING TTL %s SET val=%s WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s IF val=%s ;"; String clusteringDelete = "DELETE FROM " + KEYSPACE + ".clustering WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s ;"; String clusteringRangeDelete = "DELETE FROM " + KEYSPACE + ".clustering WHERE id=%s AND clustering1=%s ;"; + String clusteringConditionalDelete = "DELETE FROM " + KEYSPACE + ".clustering WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s IF val=%s ; "; execute("BEGIN BATCH " + String.format(clusteringInsert, 1, 1, 1, 1, 1) + " APPLY BATCH"); @@ -300,7 +306,6 @@ public class BatchTest extends CQLTester cmd4.append("APPLY BATCH "); execute(cmd4.toString()); - System.out.println(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1")); assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1"), row(1, 1, 1, 2, 234), row(1, 1, 2, 3, 23), @@ -314,7 +319,6 @@ public class BatchTest extends CQLTester cmd5.append("APPLY BATCH "); execute(cmd5.toString()); - System.out.println(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1")); assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1"), row(1, 1, 1, 2, 1234), row(1, 1, 2, 3, 23) @@ -327,7 +331,6 @@ public class BatchTest extends CQLTester cmd6.append("APPLY BATCH "); execute(cmd6.toString()); - System.out.println(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1")); assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1"), row(1, 1, 1, 2, 1), row(1, 1, 2, 3, 23), @@ -342,12 +345,319 @@ public class BatchTest extends CQLTester cmd7.append("APPLY BATCH "); execute(cmd7.toString()); - System.out.println(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1")); assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1"), row(1, 1, 1, 2, 1), row(1, 1, 2, 3, 23), row(1, 3, 4, 5, 345) ); + + StringBuilder cmd8 = new StringBuilder(); + cmd8.append("BEGIN BATCH "); + cmd8.append(String.format(clusteringConditionalDelete, 1, 3, 4, 5, 345)); + cmd8.append(String.format(clusteringRangeDelete, 1, 1)); + cmd8.append(String.format(clusteringInsert, 1, 2, 3, 4, 5)); + cmd8.append("APPLY BATCH "); + execute(cmd8.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1"), + row(1, 2, 3, 4, 5) + ); + + StringBuilder cmd9 = new StringBuilder(); + cmd9.append("BEGIN BATCH "); + cmd9.append(String.format(clusteringConditionalInsert, 1, 3, 4, 5, 345)); + cmd9.append(String.format(clusteringDelete, 1, 2, 3, 4)); + cmd9.append("APPLY BATCH "); + execute(cmd9.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1"), + row(1, 3, 4, 5, 345) + ); + + StringBuilder cmd10 = new StringBuilder(); + cmd10.append("BEGIN BATCH "); + cmd10.append(String.format(clusteringTTLInsert, 1, 2, 3, 4, 5, 5)); + cmd10.append(String.format(clusteringConditionalTTLUpdate, 10, 5, 1, 3, 4, 5, 345)); + cmd10.append("APPLY BATCH "); + execute(cmd10.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1"), + row(1, 2, 3, 4, 5), // 5 second TTL + row(1, 3, 4, 5, 5) // 10 second TTL + ); + + Thread.sleep(6000); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1"), + row(1, 3, 4, 5, 5) // now 4 second TTL + ); + + StringBuilder cmd11 = new StringBuilder(); + cmd11.append("BEGIN BATCH "); + cmd11.append(String.format(clusteringConditionalTTLInsert, 1, 2, 3, 4, 5, 5)); + cmd11.append(String.format(clusteringInsert,1, 4, 5, 6, 7)); + cmd11.append("APPLY BATCH "); + execute(cmd11.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1"), + row(1, 2, 3, 4, 5), // This one has 5 seconds left + row(1, 3, 4, 5, 5), // This one should have 4 seconds left + row(1, 4, 5, 6, 7) // This one has no TTL + ); + + Thread.sleep(6000); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1"), + row(1, 3, 4, 5, null), // We had a row here before from cmd9, but we've ttl'd out the value in cmd11 + row(1, 4, 5, 6, 7) + ); + + StringBuilder cmd12 = new StringBuilder(); + cmd12.append("BEGIN BATCH "); + cmd12.append(String.format(clusteringConditionalTTLUpdate, 5, 5, 1, 3, 4, 5, null)); + cmd12.append(String.format(clusteringTTLUpdate, 5, 8, 1, 4, 5, 6)); + cmd12.append("APPLY BATCH "); + execute(cmd12.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1"), + row(1, 3, 4, 5, 5), + row(1, 4, 5, 6, 8) + ); + + Thread.sleep(6000); + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering WHERE id=1"), + row(1, 3, 4, 5, null), + row(1, 4, 5, 6, null) + ); + } + + + @Test + public void testBatchStaticTTLConditionalInteraction() throws Throwable + { + + createTable(String.format("CREATE TABLE %s.clustering_static (\n" + + " id int,\n" + + " clustering1 int,\n" + + " clustering2 int,\n" + + " clustering3 int,\n" + + " sval int static, \n" + + " val int, \n" + + " PRIMARY KEY(id, clustering1, clustering2, clustering3)" + + ")", KEYSPACE)); + + execute("DELETE FROM " + KEYSPACE +".clustering_static WHERE id=1"); + + String clusteringInsert = "INSERT INTO " + KEYSPACE + ".clustering_static(id, clustering1, clustering2, clustering3, val) VALUES(%s, %s, %s, %s, %s); "; + String clusteringTTLInsert = "INSERT INTO " + KEYSPACE + ".clustering_static(id, clustering1, clustering2, clustering3, val) VALUES(%s, %s, %s, %s, %s) USING TTL %s; "; + String clusteringStaticInsert = "INSERT INTO " + KEYSPACE + ".clustering_static(id, clustering1, clustering2, clustering3, sval, val) VALUES(%s, %s, %s, %s, %s, %s); "; + String clusteringConditionalInsert = "INSERT INTO " + KEYSPACE + ".clustering_static(id, clustering1, clustering2, clustering3, val) VALUES(%s, %s, %s, %s, %s) IF NOT EXISTS; "; + String clusteringConditionalTTLInsert = "INSERT INTO " + KEYSPACE + ".clustering_static(id, clustering1, clustering2, clustering3, val) VALUES(%s, %s, %s, %s, %s) IF NOT EXISTS USING TTL %s; "; + String clusteringUpdate = "UPDATE " + KEYSPACE + ".clustering_static SET val=%s WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s ;"; + String clusteringStaticUpdate = "UPDATE " + KEYSPACE + ".clustering_static SET sval=%s WHERE id=%s ;"; + String clusteringTTLUpdate = "UPDATE " + KEYSPACE + ".clustering_static USING TTL %s SET val=%s WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s ;"; + String clusteringStaticConditionalUpdate = "UPDATE " + KEYSPACE + ".clustering_static SET val=%s WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s IF sval=%s ;"; + String clusteringConditionalTTLUpdate = "UPDATE " + KEYSPACE + ".clustering_static USING TTL %s SET val=%s WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s IF val=%s ;"; + String clusteringStaticConditionalTTLUpdate = "UPDATE " + KEYSPACE + ".clustering_static USING TTL %s SET val=%s WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s IF sval=%s ;"; + String clusteringStaticConditionalStaticUpdate = "UPDATE " + KEYSPACE +".clustering_static SET sval=%s WHERE id=%s IF sval=%s; "; + String clusteringDelete = "DELETE FROM " + KEYSPACE + ".clustering_static WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s ;"; + String clusteringRangeDelete = "DELETE FROM " + KEYSPACE + ".clustering_static WHERE id=%s AND clustering1=%s ;"; + String clusteringConditionalDelete = "DELETE FROM " + KEYSPACE + ".clustering_static WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s IF val=%s ; "; + String clusteringStaticConditionalDelete = "DELETE FROM " + KEYSPACE + ".clustering_static WHERE id=%s AND clustering1=%s AND clustering2=%s AND clustering3=%s IF sval=%s ; "; + + + execute("BEGIN BATCH " + String.format(clusteringStaticInsert, 1, 1, 1, 1, 1, 1) + " APPLY BATCH"); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), row(1, 1, 1, 1, 1, 1)); + + StringBuilder cmd2 = new StringBuilder(); + cmd2.append("BEGIN BATCH "); + cmd2.append(String.format(clusteringInsert, 1, 1, 1, 2, 2)); + cmd2.append(String.format(clusteringStaticConditionalUpdate, 11, 1, 1, 1, 1, 1)); + cmd2.append("APPLY BATCH "); + execute(cmd2.toString()); + + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 1, 1, 1, 1, 11), + row(1, 1, 1, 2, 1, 2) + ); + + + StringBuilder cmd3 = new StringBuilder(); + cmd3.append("BEGIN BATCH "); + cmd3.append(String.format(clusteringInsert, 1, 1, 2, 3, 23)); + cmd3.append(String.format(clusteringStaticUpdate, 22, 1)); + cmd3.append(String.format(clusteringDelete, 1, 1, 1, 1)); + cmd3.append("APPLY BATCH "); + execute(cmd3.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 1, 1, 2, 22, 2), + row(1, 1, 2, 3, 22, 23) + ); + + StringBuilder cmd4 = new StringBuilder(); + cmd4.append("BEGIN BATCH "); + cmd4.append(String.format(clusteringInsert, 1, 2, 3, 4, 1234)); + cmd4.append(String.format(clusteringStaticConditionalTTLUpdate, 5, 234, 1, 1, 1, 2, 22)); + cmd4.append("APPLY BATCH "); + execute(cmd4.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 1, 1, 2, 22, 234), + row(1, 1, 2, 3, 22, 23), + row(1, 2, 3, 4, 22, 1234) + ); + + Thread.sleep(6000); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 1, 1, 2, 22, null), + row(1, 1, 2, 3, 22, 23), + row(1, 2, 3, 4, 22, 1234) + ); + + StringBuilder cmd5 = new StringBuilder(); + cmd5.append("BEGIN BATCH "); + cmd5.append(String.format(clusteringRangeDelete, 1, 2)); + cmd5.append(String.format(clusteringStaticConditionalUpdate, 1234, 1, 1, 1, 2, 22)); + cmd5.append("APPLY BATCH "); + execute(cmd5.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 1, 1, 2, 22, 1234), + row(1, 1, 2, 3, 22, 23) + ); + + StringBuilder cmd6 = new StringBuilder(); + cmd6.append("BEGIN BATCH "); + cmd6.append(String.format(clusteringUpdate, 345, 1, 3, 4, 5)); + cmd6.append(String.format(clusteringStaticConditionalUpdate, 1, 1, 1, 1, 2, 22)); + cmd6.append("APPLY BATCH "); + execute(cmd6.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 1, 1, 2, 22, 1), + row(1, 1, 2, 3, 22, 23), + row(1, 3, 4, 5, 22, 345) + ); + + + StringBuilder cmd7 = new StringBuilder(); + cmd7.append("BEGIN BATCH "); + cmd7.append(String.format(clusteringDelete, 1, 3, 4, 5)); + cmd7.append(String.format(clusteringStaticConditionalUpdate, 2300, 1, 1, 2, 3, 1)); // SHOULD NOT MATCH + cmd7.append("APPLY BATCH "); + execute(cmd7.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 1, 1, 2, 22, 1), + row(1, 1, 2, 3, 22, 23), + row(1, 3, 4, 5, 22, 345) + ); + + StringBuilder cmd8 = new StringBuilder(); + cmd8.append("BEGIN BATCH "); + cmd8.append(String.format(clusteringConditionalDelete, 1, 3, 4, 5, 345)); + cmd8.append(String.format(clusteringRangeDelete, 1, 1)); + cmd8.append(String.format(clusteringInsert, 1, 2, 3, 4, 5)); + cmd8.append("APPLY BATCH "); + execute(cmd8.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 2, 3, 4, 22, 5) + ); + + StringBuilder cmd9 = new StringBuilder(); + cmd9.append("BEGIN BATCH "); + cmd9.append(String.format(clusteringConditionalInsert, 1, 3, 4, 5, 345)); + cmd9.append(String.format(clusteringDelete, 1, 2, 3, 4)); + cmd9.append("APPLY BATCH "); + execute(cmd9.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 3, 4, 5, 22, 345) + ); + + StringBuilder cmd10 = new StringBuilder(); + cmd10.append("BEGIN BATCH "); + cmd10.append(String.format(clusteringTTLInsert, 1, 2, 3, 4, 5, 5)); + cmd10.append(String.format(clusteringConditionalTTLUpdate, 10, 5, 1, 3, 4, 5, 345)); + cmd10.append("APPLY BATCH "); + execute(cmd10.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 2, 3, 4, 22, 5), // 5 second TTL + row(1, 3, 4, 5, 22, 5) // 10 second TTL + ); + + Thread.sleep(6000); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 3, 4, 5, 22, 5) // now 4 second TTL + ); + + StringBuilder cmd11 = new StringBuilder(); + cmd11.append("BEGIN BATCH "); + cmd11.append(String.format(clusteringConditionalTTLInsert, 1, 2, 3, 4, 5, 5)); + cmd11.append(String.format(clusteringInsert,1, 4, 5, 6, 7)); + cmd11.append("APPLY BATCH "); + execute(cmd11.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 2, 3, 4, 22, 5), // This one has 5 seconds left + row(1, 3, 4, 5, 22, 5), // This one should have 4 seconds left + row(1, 4, 5, 6, 22, 7) // This one has no TTL + ); + + Thread.sleep(6000); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 3, 4, 5, 22, null), // We had a row here before from cmd9, but we've ttl'd out the value in cmd11 + row(1, 4, 5, 6, 22, 7) + ); + + StringBuilder cmd12 = new StringBuilder(); + cmd12.append("BEGIN BATCH "); + cmd12.append(String.format(clusteringConditionalTTLUpdate, 5, 5, 1, 3, 4, 5, null)); + cmd12.append(String.format(clusteringTTLUpdate, 5, 8, 1, 4, 5, 6)); + cmd12.append("APPLY BATCH "); + execute(cmd12.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 3, 4, 5, 22, 5), + row(1, 4, 5, 6, 22, 8) + ); + + Thread.sleep(6000); + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 3, 4, 5, 22, null), + row(1, 4, 5, 6, 22, null) + ); + + StringBuilder cmd13 = new StringBuilder(); + cmd13.append("BEGIN BATCH "); + cmd13.append(String.format(clusteringStaticConditionalDelete, 1, 3, 4, 5, 22)); + cmd13.append(String.format(clusteringInsert, 1, 2, 3, 4, 5)); + cmd13.append("APPLY BATCH "); + execute(cmd13.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 2, 3, 4, 22, 5), + row(1, 4, 5, 6, 22, null) + ); + + StringBuilder cmd14 = new StringBuilder(); + cmd14.append("BEGIN BATCH "); + cmd14.append(String.format(clusteringStaticConditionalStaticUpdate, 23, 1, 22)); + cmd14.append(String.format(clusteringDelete, 1, 4, 5, 6)); + cmd14.append("APPLY BATCH "); + execute(cmd14.toString()); + + assertRows(execute("SELECT * FROM " + KEYSPACE+".clustering_static WHERE id=1"), + row(1, 2, 3, 4, 23, 5) + ); } } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org