Repository: cassandra Updated Branches: refs/heads/trunk 26eab4546 -> 113b92bcb
Fix duration type validation patch by Benjamin Lerer; reviewed by Tyler Hobbs for CASSANDRA-13143 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/91564aba Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/91564aba Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/91564aba Branch: refs/heads/trunk Commit: 91564abaddce59b06c024e8959c46ec1e4d19eda Parents: b234ca3 Author: Benjamin Lerer <[email protected]> Authored: Fri Jan 27 10:12:26 2017 +0100 Committer: Benjamin Lerer <[email protected]> Committed: Fri Jan 27 10:12:26 2017 +0100 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../serializers/DurationSerializer.java | 16 ++++++++++++ .../cql3/validation/operations/CreateTest.java | 26 +++++++++++++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/91564aba/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 55762e2..aec644f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.10 + * Fix duration type validation (CASSANDRA-13143) * Fix flaky GcCompactionTest (CASSANDRA-12664) * Fix TestHintedHandoff.hintedhandoff_decom_test (CASSANDRA-13058) * Fixed query monitoring for range queries (CASSANDRA-13050) http://git-wip-us.apache.org/repos/asf/cassandra/blob/91564aba/src/java/org/apache/cassandra/serializers/DurationSerializer.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/serializers/DurationSerializer.java b/src/java/org/apache/cassandra/serializers/DurationSerializer.java index d139b9e..03d08ae 100644 --- a/src/java/org/apache/cassandra/serializers/DurationSerializer.java +++ b/src/java/org/apache/cassandra/serializers/DurationSerializer.java @@ -80,6 +80,22 @@ public final class DurationSerializer implements TypeSerializer<Duration> { if (bytes.remaining() < 3) throw new MarshalException(String.format("Expected at least 3 bytes for a duration (%d)", bytes.remaining())); + + try (DataInputBuffer in = new DataInputBuffer(bytes, true)) + { + int months = (int) in.readVInt(); + int days = (int) in.readVInt(); + long nanoseconds = in.readVInt(); + + if (!((months >= 0 && days >= 0 && nanoseconds >= 0) || (months <= 0 && days <=0 && nanoseconds <=0))) + throw new MarshalException(String.format("The duration months, days and nanoseconds must be all of the same sign (%d, %d, %d)", + months, days, nanoseconds)); + } + catch (IOException e) + { + // this should never happen with a DataInputBuffer + throw new AssertionError("Unexpected error", e); + } } public String toString(Duration duration) http://git-wip-us.apache.org/repos/asf/cassandra/blob/91564aba/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java index 6912f85..e60bf36 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java @@ -17,6 +17,8 @@ */ package org.apache.cassandra.cql3.validation.operations; +import java.io.IOException; +import java.nio.ByteBuffer; import java.util.Collection; import java.util.Collections; import java.util.UUID; @@ -32,6 +34,7 @@ import org.apache.cassandra.db.Mutation; import org.apache.cassandra.db.partitions.Partition; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.exceptions.SyntaxException; +import org.apache.cassandra.io.util.DataOutputBuffer; import org.apache.cassandra.schema.SchemaKeyspace; import org.apache.cassandra.triggers.ITrigger; import org.apache.cassandra.utils.ByteBufferUtil; @@ -121,6 +124,8 @@ public class CreateTest extends CQLTester execute("INSERT INTO %s (a, b, c) VALUES (1, 18, P1Y3MT2H10M)"); execute("INSERT INTO %s (a, b, c) VALUES (1, 19, P0000-00-00T30:20:00)"); execute("INSERT INTO %s (a, b, c) VALUES (1, 20, P0001-03-00T02:10:00)"); + execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 1, 21, duration(12, 10, 0)); + execute("INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 1, 22, duration(-12, -10, 0)); assertRows(execute("SELECT * FROM %s"), row(1, 1, Duration.newInstance(14, 0, 0)), @@ -142,7 +147,9 @@ public class CreateTest extends CQLTester row(1, 17, Duration.newInstance(0, 14, 0)), row(1, 18, Duration.newInstance(15, 0, 130 * NANOS_PER_MINUTE)), row(1, 19, Duration.newInstance(0, 0, 30 * NANOS_PER_HOUR + 20 * NANOS_PER_MINUTE)), - row(1, 20, Duration.newInstance(15, 0, 130 * NANOS_PER_MINUTE))); + row(1, 20, Duration.newInstance(15, 0, 130 * NANOS_PER_MINUTE)), + row(1, 21, Duration.newInstance(12, 10, 0)), + row(1, 22, Duration.newInstance(-12, -10, 0))); assertInvalidMessage("Slice restriction are not supported on duration columns", "SELECT * FROM %s WHERE c > 1y ALLOW FILTERING"); @@ -157,6 +164,12 @@ public class CreateTest extends CQLTester assertInvalidMessage("Invalid duration. The total number of days must be less or equal to 2147483647", "INSERT INTO %s (a, b, c) VALUES (1, 2, " + Long.MAX_VALUE + "d)"); + assertInvalidMessage("The duration months, days and nanoseconds must be all of the same sign (2, -2, 0)", + "INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 2, 1, duration(2, -2, 0)); + + assertInvalidMessage("The duration months, days and nanoseconds must be all of the same sign (-2, 0, 2000000)", + "INSERT INTO %s (a, b, c) VALUES (?, ?, ?)", 2, 1, duration(-2, 0, 2000000)); + // Test with duration column name createTable("CREATE TABLE %s (a text PRIMARY KEY, duration duration);"); @@ -216,6 +229,17 @@ public class CreateTest extends CQLTester "CREATE TABLE %s(pk int, m frozen<map<text, list<tuple<int, duration>>>>, v int, PRIMARY KEY (pk, m))"); } + private ByteBuffer duration(int months, int days, long nanoseconds) throws IOException + { + try(DataOutputBuffer output = new DataOutputBuffer()) + { + output.writeVInt(months); + output.writeVInt(days); + output.writeVInt(nanoseconds); + return output.buffer(); + } + } + /** * Creation and basic operations on a static table, * migrated from cql_tests.py:TestCQL.static_cf_test()
