You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by bl...@apache.org on 2018/03/14 09:32:08 UTC

[2/4] cassandra git commit: Fix Loss of digits when doing CAST from varint/bigint to decimal

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....@gmail.com>
Authored: Wed Feb 14 12:29:17 2018 +0100
Committer: Benjamin Lerer <b....@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-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org