Fix Loss of digits when doing CAST from varint/bigint to decimal patch by Benjamin Lerer; reviewed by Andrés de la Peña for CASSANDRA-14170
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/3fa7c089 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/3fa7c089 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/3fa7c089 Branch: refs/heads/trunk Commit: 3fa7c0894449b5c6033a6c4f47ec3292d07268b8 Parents: 171222c Author: Benjamin Lerer <b.le...@gmail.com> Authored: Wed Feb 14 12:29:17 2018 +0100 Committer: Benjamin Lerer <b.le...@gmail.com> Committed: Wed Mar 14 10:27:56 2018 +0100 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cassandra/cql3/functions/CastFcts.java | 19 ++++++++++++++++- .../cassandra/cql3/functions/CastFctsTest.java | 22 ++++++++++++++------ 3 files changed, 35 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/3fa7c089/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 684f2a6..c2b907e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.11.3 + * Fix Loss of digits when doing CAST from varint/bigint to decimal (CASSANDRA-14170) * RateBasedBackPressure unnecessarily invokes a lock on the Guava RateLimiter (CASSANDRA-14163) * Fix wildcard GROUP BY queries (CASSANDRA-14209) Merged from 3.0: http://git-wip-us.apache.org/repos/asf/cassandra/blob/3fa7c089/src/java/org/apache/cassandra/cql3/functions/CastFcts.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/functions/CastFcts.java b/src/java/org/apache/cassandra/cql3/functions/CastFcts.java index 9e5c729..9f825ee 100644 --- a/src/java/org/apache/cassandra/cql3/functions/CastFcts.java +++ b/src/java/org/apache/cassandra/cql3/functions/CastFcts.java @@ -79,7 +79,7 @@ public final class CastFcts addFunctionIfNeeded(functions, inputType, LongType.instance, Number::longValue); addFunctionIfNeeded(functions, inputType, FloatType.instance, Number::floatValue); addFunctionIfNeeded(functions, inputType, DoubleType.instance, Number::doubleValue); - addFunctionIfNeeded(functions, inputType, DecimalType.instance, p -> BigDecimal.valueOf(p.doubleValue())); + addFunctionIfNeeded(functions, inputType, DecimalType.instance, getDecimalConversionFunction(inputType)); addFunctionIfNeeded(functions, inputType, IntegerType.instance, p -> BigInteger.valueOf(p.longValue())); functions.add(CastAsTextFunction.create(inputType, AsciiType.instance)); functions.add(CastAsTextFunction.create(inputType, UTF8Type.instance)); @@ -113,6 +113,23 @@ public final class CastFcts } /** + * Returns the conversion function to convert the specified type into a Decimal type + * + * @param inputType the input type + * @return the conversion function to convert the specified type into a Decimal type + */ + private static <I extends Number> java.util.function.Function<I, BigDecimal> getDecimalConversionFunction(AbstractType<? extends Number> inputType) + { + if (inputType == FloatType.instance || inputType == DoubleType.instance) + return p -> BigDecimal.valueOf(p.doubleValue()); + + if (inputType == IntegerType.instance) + return p -> new BigDecimal((BigInteger) p); + + return p -> BigDecimal.valueOf(p.longValue()); + } + + /** * Creates the name of the cast function use to cast to the specified type. * * @param outputType the output type http://git-wip-us.apache.org/repos/asf/cassandra/blob/3fa7c089/test/unit/org/apache/cassandra/cql3/functions/CastFctsTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/functions/CastFctsTest.java b/test/unit/org/apache/cassandra/cql3/functions/CastFctsTest.java index 9b4b570..2ffd8b4 100644 --- a/test/unit/org/apache/cassandra/cql3/functions/CastFctsTest.java +++ b/test/unit/org/apache/cassandra/cql3/functions/CastFctsTest.java @@ -153,14 +153,14 @@ public class CastFctsTest extends CQLTester "CAST(g AS decimal), " + "CAST(h AS decimal), " + "CAST(i AS decimal) FROM %s"), - row(BigDecimal.valueOf(1.0), - BigDecimal.valueOf(2.0), - BigDecimal.valueOf(3.0), - BigDecimal.valueOf(4.0), + row(BigDecimal.valueOf(1), + BigDecimal.valueOf(2), + BigDecimal.valueOf(3), + BigDecimal.valueOf(4), BigDecimal.valueOf(5.2F), BigDecimal.valueOf(6.3), BigDecimal.valueOf(6.3), - BigDecimal.valueOf(4.0), + BigDecimal.valueOf(4), null)); assertRows(execute("SELECT CAST(a AS ascii), " + @@ -203,6 +203,16 @@ public class CastFctsTest extends CQLTester } @Test + public void testNoLossOfPrecisionForCastToDecimal() throws Throwable + { + createTable("CREATE TABLE %s (k int PRIMARY KEY, bigint_clmn bigint, varint_clmn varint)"); + execute("INSERT INTO %s(k, bigint_clmn, varint_clmn) VALUES(2, 9223372036854775807, 1234567890123456789)"); + + assertRows(execute("SELECT CAST(bigint_clmn AS decimal), CAST(varint_clmn AS decimal) FROM %s"), + row(BigDecimal.valueOf(9223372036854775807L), BigDecimal.valueOf(1234567890123456789L))); + } + + @Test public void testTimeCastsInSelectionClause() throws Throwable { createTable("CREATE TABLE %s (a timeuuid primary key, b timestamp, c date, d time)"); @@ -309,6 +319,6 @@ public class CastFctsTest extends CQLTester "CAST(b AS decimal), " + "CAST(b AS ascii), " + "CAST(b AS text) FROM %s"), - row((byte) 2, (short) 2, 2, 2L, 2.0F, 2.0, BigDecimal.valueOf(2.0), "2", "2")); + row((byte) 2, (short) 2, 2, 2L, 2.0F, 2.0, BigDecimal.valueOf(2), "2", "2")); } } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org