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()]])"); }
