This is an automated email from the ASF dual-hosted git repository.

mbudiu pushed a commit to branch issue2067
in repository https://gitbox.apache.org/repos/asf/calcite.git

commit 7d2574225a5a81d73a1c88ea7c0e1dfb372cc198
Author: Mihai Budiu <[email protected]>
AuthorDate: Thu Feb 1 10:39:07 2024 -0800

    Druid does not support literals in scientific notation
    
    Signed-off-by: Mihai Budiu <[email protected]>
---
 .../java/org/apache/calcite/rex/RexLiteral.java     | 21 ++++++---------------
 .../calcite/adapter/druid/DruidExpressions.java     |  6 +++++-
 .../org/apache/calcite/test/DruidAdapter2IT.java    |  2 +-
 .../org/apache/calcite/test/DruidAdapterIT.java     |  2 +-
 4 files changed, 13 insertions(+), 18 deletions(-)

diff --git a/core/src/main/java/org/apache/calcite/rex/RexLiteral.java 
b/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
index 5eb37687a0..69453ea22f 100644
--- a/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
+++ b/core/src/main/java/org/apache/calcite/rex/RexLiteral.java
@@ -55,6 +55,7 @@ import org.locationtech.jts.geom.Geometry;
 
 import java.io.PrintWriter;
 import java.math.BigDecimal;
+import java.math.MathContext;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 import java.text.SimpleDateFormat;
@@ -1115,21 +1116,11 @@ public class RexLiteral extends RexNode {
           return clazz.cast(d);
         } else if (clazz == Float.class) {
           return clazz.cast(d.floatValue());
-        }
-      } else {
-        BigDecimal bd = (BigDecimal) value;
-        if (clazz == Long.class) {
-          return clazz.cast(bd.longValue());
-        } else if (clazz == Integer.class) {
-          return clazz.cast(bd.intValue());
-        } else if (clazz == Short.class) {
-          return clazz.cast(bd.shortValue());
-        } else if (clazz == Byte.class) {
-          return clazz.cast(bd.byteValue());
-        } else if (clazz == Double.class) {
-          return clazz.cast(bd.doubleValue());
-        } else if (clazz == Float.class) {
-          return clazz.cast(bd.floatValue());
+        } else if (clazz == BigDecimal.class) {
+          // This particular conversion is lossy, since in general BigDecimal 
cannot
+          // represent accurately FP values.  However, this is the best we can 
do.
+          // This conversion used to be in RexBuilder, used when creating a 
RexLiteral.
+          return clazz.cast(new BigDecimal(d, 
MathContext.DECIMAL64).stripTrailingZeros());
         }
       }
       break;
diff --git 
a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidExpressions.java 
b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidExpressions.java
index 73045d208c..3cb6bc67da 100644
--- a/druid/src/main/java/org/apache/calcite/adapter/druid/DruidExpressions.java
+++ b/druid/src/main/java/org/apache/calcite/adapter/druid/DruidExpressions.java
@@ -33,6 +33,7 @@ import com.google.common.primitives.Chars;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -136,8 +137,11 @@ public class DruidExpressions {
         // deal with this for now
         return null;
       } else if (SqlTypeName.NUMERIC_TYPES.contains(sqlTypeName)) {
+        // This conversion is lossy for Double values.
+        // However, Druid does not support floating point literal values
+        // if they are formatted using scientific notation.
         return DruidExpressions.numberLiteral(
-            requireNonNull((Number) RexLiteral.value(rexNode)));
+            requireNonNull((RexLiteral) 
rexNode).getValueAs(BigDecimal.class)));
       } else if (SqlTypeFamily.INTERVAL_DAY_TIME == sqlTypeName.getFamily()) {
         // Calcite represents DAY-TIME intervals in milliseconds.
         final long milliseconds =
diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java 
b/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java
index 97cfafe68e..a44add8094 100644
--- a/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java
+++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapter2IT.java
@@ -3306,7 +3306,7 @@ public class DruidAdapter2IT {
         .explainContains("PLAN=EnumerableInterpreter\n"
             + "  DruidQuery(table=[[foodmart, foodmart]], 
intervals=[[1900-01-09T00:00:00"
             + ".000Z/2992-01-10T00:00:00.000Z]], filter=[AND(>(SIN($91), 
0.9129452507276277E0), >"
-            + "(COS($90), 0.40808206181339196E0), =(FLOOR(TAN($91)), 2), 
<(ABS(-(TAN($91), /(SIN"
+            + "(COS($90), 0.40808206181339196E0), =(FLOOR(TAN($91)), 2.0E0), 
<(ABS(-(TAN($91), /(SIN"
             + "($91), COS($91)))), 1.0E-6))], groups=[{}], aggs=[[COUNT()]])");
   }
 
diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java 
b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
index ca303fdfeb..9e140f3293 100644
--- a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
+++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
@@ -3957,7 +3957,7 @@ public class DruidAdapterIT {
         .explainContains("PLAN=EnumerableInterpreter\n"
             + "  DruidQuery(table=[[foodmart, foodmart]], "
             + 
"intervals=[[1900-01-09T00:00:00.000Z/2992-01-10T00:00:00.000Z]], "
-            + "filter=[AND(>(SIN($91), 0.9129452507276277E0), >(COS($90), 
0.40808206181339196E0), =(FLOOR(TAN($91)), 2), "
+            + "filter=[AND(>(SIN($91), 0.9129452507276277E0), >(COS($90), 
0.40808206181339196E0), =(FLOOR(TAN($91)), 2.0E0), "
             + "<(ABS(-(TAN($91), /(SIN($91), COS($91)))), 1.0E-6))], "
             + "groups=[{}], aggs=[[COUNT()]])");
   }

Reply via email to