diff --git a/CHANGES.txt b/CHANGES.txt index 6a825a4ebe..15e5001159 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -55,6 +55,7 @@ Merged from 3.0: * NullPointerExpception when reading/compacting table (CASSANDRA-11988) * Fix problem with undeleteable rows on upgrade to new sstable format (CASSANDRA-12144) Merged from 2.2: + * Fix INSERT JSON, fromJson() support of smallint, tinyint types (CASSANDRA-12371) * Release sstables of failed stream sessions only when outgoing transfers are finished (CASSANDRA-11345) * Wait for tracing events before returning response and query at same consistency level client side (CASSANDRA-11465) * cqlsh copyutil should get host metadata by connected address (CASSANDRA-11979) diff --git a/src/java/org/apache/cassandra/db/marshal/ByteType.java b/src/java/org/apache/cassandra/db/marshal/ByteType.java index 14699cd829..6bcf7cbe8b 100644 --- a/src/java/org/apache/cassandra/db/marshal/ByteType.java +++ b/src/java/org/apache/cassandra/db/marshal/ByteType.java @@ -63,22 +63,11 @@ public class ByteType extends AbstractType public Term fromJSONObject(Object parsed) throws MarshalException { - try - { - if (parsed instanceof String) - return new Constants.Value(fromString((String) parsed)); + if (parsed instanceof String || parsed instanceof Number) + return new Constants.Value(fromString(String.valueOf(parsed))); - Number parsedNumber = (Number) parsed; - if (!(parsedNumber instanceof Byte)) - throw new MarshalException(String.format("Expected a byte value, but got a %s: %s", parsed.getClass().getSimpleName(), parsed)); - - return new Constants.Value(getSerializer().serialize(parsedNumber.byteValue())); - } - catch (ClassCastException exc) - { - throw new MarshalException(String.format( - "Expected a byte value, but got a %s: %s", parsed.getClass().getSimpleName(), parsed)); - } + throw new MarshalException(String.format( + "Expected a byte value, but got a %s: %s", parsed.getClass().getSimpleName(), parsed)); } @Override diff --git a/src/java/org/apache/cassandra/db/marshal/ShortType.java b/src/java/org/apache/cassandra/db/marshal/ShortType.java index 15618b8978..482fd810b7 100644 --- a/src/java/org/apache/cassandra/db/marshal/ShortType.java +++ b/src/java/org/apache/cassandra/db/marshal/ShortType.java @@ -67,22 +67,11 @@ public class ShortType extends AbstractType public Term fromJSONObject(Object parsed) throws MarshalException { - try - { - if (parsed instanceof String) - return new Constants.Value(fromString((String) parsed)); + if (parsed instanceof String || parsed instanceof Number) + return new Constants.Value(fromString(String.valueOf(parsed))); - Number parsedNumber = (Number) parsed; - if (!(parsedNumber instanceof Short)) - throw new MarshalException(String.format("Expected a short value, but got a %s: %s", parsed.getClass().getSimpleName(), parsed)); - - return new Constants.Value(getSerializer().serialize(parsedNumber.shortValue())); - } - catch (ClassCastException exc) - { - throw new MarshalException(String.format( - "Expected a short value, but got a %s: %s", parsed.getClass().getSimpleName(), parsed)); - } + throw new MarshalException(String.format( + "Expected a short value, but got a %s: %s", parsed.getClass().getSimpleName(), parsed)); } @Override diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/JsonTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/JsonTest.java index a14e4a59ac..e930a9ecd5 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/JsonTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/JsonTest.java @@ -65,10 +65,12 @@ public class JsonTest extends CQLTester "floatval float, " + "inetval inet, " + "intval int, " + + "smallintval smallint, " + "textval text, " + "timeval time, " + "timestampval timestamp, " + "timeuuidval timeuuid, " + + "tinyintval tinyint, " + "uuidval uuid," + "varcharval varchar, " + "varintval varint, " + @@ -268,6 +270,48 @@ public class JsonTest extends CQLTester assertInvalidMessage("Expected an int value, but got a", "INSERT INTO %s (k, intval) VALUES (?, fromJson(?))", 0, "true"); + // ================ smallint ================ + execute("INSERT INTO %s (k, smallintval) VALUES (?, fromJson(?))", 0, "32767"); + assertRows(execute("SELECT k, smallintval FROM %s WHERE k = ?", 0), row(0, (short) 32767)); + + // strings are also accepted + execute("INSERT INTO %s (k, smallintval) VALUES (?, fromJson(?))", 0, "\"32767\""); + assertRows(execute("SELECT k, smallintval FROM %s WHERE k = ?", 0), row(0, (short) 32767)); + + // smallint overflow (Short.MAX_VALUE + 1) + assertInvalidMessage("Unable to make short from", + "INSERT INTO %s (k, smallintval) VALUES (?, fromJson(?))", 0, "32768"); + + assertInvalidMessage("Unable to make short from", + "INSERT INTO %s (k, smallintval) VALUES (?, fromJson(?))", 0, "123.456"); + + assertInvalidMessage("Unable to make short from", + "INSERT INTO %s (k, smallintval) VALUES (?, fromJson(?))", 0, "\"xyzz\""); + + assertInvalidMessage("Expected a short value, but got a Boolean", + "INSERT INTO %s (k, smallintval) VALUES (?, fromJson(?))", 0, "true"); + + // ================ tinyint ================ + execute("INSERT INTO %s (k, tinyintval) VALUES (?, fromJson(?))", 0, "127"); + assertRows(execute("SELECT k, tinyintval FROM %s WHERE k = ?", 0), row(0, (byte) 127)); + + // strings are also accepted + execute("INSERT INTO %s (k, tinyintval) VALUES (?, fromJson(?))", 0, "\"127\""); + assertRows(execute("SELECT k, tinyintval FROM %s WHERE k = ?", 0), row(0, (byte) 127)); + + // tinyint overflow (Byte.MAX_VALUE + 1) + assertInvalidMessage("Unable to make byte from", + "INSERT INTO %s (k, tinyintval) VALUES (?, fromJson(?))", 0, "128"); + + assertInvalidMessage("Unable to make byte from", + "INSERT INTO %s (k, tinyintval) VALUES (?, fromJson(?))", 0, "123.456"); + + assertInvalidMessage("Unable to make byte from", + "INSERT INTO %s (k, tinyintval) VALUES (?, fromJson(?))", 0, "\"xyzz\""); + + assertInvalidMessage("Expected a byte value, but got a Boolean", + "INSERT INTO %s (k, tinyintval) VALUES (?, fromJson(?))", 0, "true"); + // ================ text (varchar) ================ execute("INSERT INTO %s (k, textval) VALUES (?, fromJson(?))", 0, "\"\""); assertRows(execute("SELECT k, textval FROM %s WHERE k = ?", 0), row(0, "")); @@ -503,10 +547,12 @@ public class JsonTest extends CQLTester "floatval float, " + "inetval inet, " + "intval int, " + + "smallintval smallint, " + "textval text, " + "timeval time, " + "timestampval timestamp, " + "timeuuidval timeuuid, " + + "tinyintval tinyint, " + "uuidval uuid," + "varcharval varchar, " + "varintval varint, " + @@ -600,6 +646,26 @@ public class JsonTest extends CQLTester execute("INSERT INTO %s (k, intval) VALUES (?, ?)", 0, -123123); assertRows(execute("SELECT k, toJson(intval) FROM %s WHERE k = ?", 0), row(0, "-123123")); + // ================ smallint ================ + execute("INSERT INTO %s (k, smallintval) VALUES (?, ?)", 0, (short) 32767); + assertRows(execute("SELECT k, toJson(smallintval) FROM %s WHERE k = ?", 0), row(0, "32767")); + + execute("INSERT INTO %s (k, smallintval) VALUES (?, ?)", 0, (short) 0); + assertRows(execute("SELECT k, toJson(smallintval) FROM %s WHERE k = ?", 0), row(0, "0")); + + execute("INSERT INTO %s (k, smallintval) VALUES (?, ?)", 0, (short) -32768); + assertRows(execute("SELECT k, toJson(smallintval) FROM %s WHERE k = ?", 0), row(0, "-32768")); + + // ================ tinyint ================ + execute("INSERT INTO %s (k, tinyintval) VALUES (?, ?)", 0, (byte) 127); + assertRows(execute("SELECT k, toJson(tinyintval) FROM %s WHERE k = ?", 0), row(0, "127")); + + execute("INSERT INTO %s (k, tinyintval) VALUES (?, ?)", 0, (byte) 0); + assertRows(execute("SELECT k, toJson(tinyintval) FROM %s WHERE k = ?", 0), row(0, "0")); + + execute("INSERT INTO %s (k, tinyintval) VALUES (?, ?)", 0, (byte) -128); + assertRows(execute("SELECT k, toJson(tinyintval) FROM %s WHERE k = ?", 0), row(0, "-128")); + // ================ text (varchar) ================ execute("INSERT INTO %s (k, textval) VALUES (?, ?)", 0, ""); assertRows(execute("SELECT k, toJson(textval) FROM %s WHERE k = ?", 0), row(0, "\"\"")); @@ -915,6 +981,8 @@ public class JsonTest extends CQLTester "intmap map, " + "bigintmap map, " + "varintmap map, " + + "smallintmap map, " + + "tinyintmap map, " + "booleanmap map, " + "floatmap map, " + "doublemap map, " + @@ -939,6 +1007,14 @@ public class JsonTest extends CQLTester execute("INSERT INTO %s JSON ?", "{\"k\": 0, \"varintmap\": {\"0\": true, \"1\": false}}"); assertRows(execute("SELECT JSON k, varintmap FROM %s"), row("{\"k\": 0, \"varintmap\": {\"0\": true, \"1\": false}}")); + // smallint keys + execute("INSERT INTO %s JSON ?", "{\"k\": 0, \"smallintmap\": {\"0\": true, \"1\": false}}"); + assertRows(execute("SELECT JSON k, smallintmap FROM %s"), row("{\"k\": 0, \"smallintmap\": {\"0\": true, \"1\": false}}")); + + // tinyint keys + execute("INSERT INTO %s JSON ?", "{\"k\": 0, \"tinyintmap\": {\"0\": true, \"1\": false}}"); + assertRows(execute("SELECT JSON k, tinyintmap FROM %s"), row("{\"k\": 0, \"tinyintmap\": {\"0\": true, \"1\": false}}")); + // boolean keys execute("INSERT INTO %s JSON ?", "{\"k\": 0, \"booleanmap\": {\"true\": true, \"false\": false}}"); assertRows(execute("SELECT JSON k, booleanmap FROM %s"), row("{\"k\": 0, \"booleanmap\": {\"false\": false, \"true\": true}}"));