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

michaelsmith pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit 62bf60994211731d8e1b5b7edba517972e2fbbca
Author: Steve Carlin <[email protected]>
AuthorDate: Fri Sep 5 13:09:01 2025 -0700

    IMPALA-14414: Calcite planner: Added new code to handle nan/inf
    
    The current code works for NaN and Inf, but it breaks when upgrading
    to v1.40.  This commit changes the code to handle these when we do
    the upgrade to 1.40 and adds a basic test into the calcite.test to ensure
    that when the upgrade happens, it does not break.
    
    Change-Id: I8593a4942a2fe785a0c77134b78a9d97257225fc
    Reviewed-on: http://gerrit.cloudera.org:8080/23561
    Reviewed-by: Impala Public Jenkins <[email protected]>
    Tested-by: Impala Public Jenkins <[email protected]>
---
 .../calcite/functions/RexLiteralConverter.java     | 46 +++++++++++++++++++---
 .../queries/QueryTest/calcite.test                 |  7 ++++
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git 
a/java/calcite-planner/src/main/java/org/apache/impala/calcite/functions/RexLiteralConverter.java
 
b/java/calcite-planner/src/main/java/org/apache/impala/calcite/functions/RexLiteralConverter.java
index b1a03c2bd..1b768c1ca 100644
--- 
a/java/calcite-planner/src/main/java/org/apache/impala/calcite/functions/RexLiteralConverter.java
+++ 
b/java/calcite-planner/src/main/java/org/apache/impala/calcite/functions/RexLiteralConverter.java
@@ -35,6 +35,7 @@ import org.apache.impala.catalog.Function;
 import org.apache.impala.catalog.PrimitiveType;
 import org.apache.impala.catalog.ScalarType;
 import org.apache.impala.catalog.Type;
+import org.apache.impala.common.AnalysisException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -56,16 +57,39 @@ public class RexLiteralConverter {
       return NumericLiteral.create(
           new BigDecimal(rexLiteral.getValueAs(Long.class)), Type.BIGINT);
     }
-    switch (rexLiteral.getTypeName()) {
-      case NULL:
-        Type type = ImpalaTypeConverter.createImpalaType(rexLiteral.getType());
-        return new AnalyzedNullLiteral(type);
+
+    if (rexLiteral.isNull()) {
+      Type type = ImpalaTypeConverter.createImpalaType(rexLiteral.getType());
+      return new AnalyzedNullLiteral(type);
+    }
+
+    switch (rexLiteral.getType().getSqlTypeName()) {
       case BOOLEAN:
         Expr boolExpr = new BoolLiteral((Boolean) 
rexLiteral.getValueAs(Boolean.class));
         return boolExpr;
+      case DOUBLE:
+        Double d = rexLiteral.getValueAs(Double.class);
+        // NumericLiteral will throw an exception if it is a Nan or Inf, so 
create
+        // a cast around it.
+        if (!NumericLiteral.isImpalaDouble(d)) {
+          return createCastNanOrInf(d, Type.DOUBLE);
+        }
+        return NumericLiteral.create(rexLiteral.getValueAs(BigDecimal.class),
+            Type.DOUBLE);
+      case FLOAT:
+        Float f = rexLiteral.getValueAs(Float.class);
+        // NumericLiteral will throw an exception if it is a Nan or Inf, so 
create
+        // a cast around it.
+        if (!NumericLiteral.isImpalaDouble(f)) {
+          return createCastNanOrInf(f, Type.FLOAT);
+        }
+        return NumericLiteral.create(rexLiteral.getValueAs(BigDecimal.class),
+            Type.FLOAT);
+      case TINYINT:
+      case SMALLINT:
+      case INTEGER:
       case BIGINT:
       case DECIMAL:
-      case DOUBLE:
         Expr numericExpr = 
NumericLiteral.create(rexLiteral.getValueAs(BigDecimal.class),
             ImpalaTypeConverter.createImpalaType(rexLiteral.getType()));
         return numericExpr;
@@ -108,4 +132,16 @@ public class RexLiteralConverter {
     Function castFunc = FunctionResolver.getExactFunction("casttotimestamp", 
typeNames);
     return new AnalyzedFunctionCallExpr(castFunc, argList, Type.TIMESTAMP);
   }
+
+  private static Expr createCastNanOrInf(Object o, Type t) {
+    List<RelDataType> typeNames =
+        ImmutableList.of(ImpalaTypeConverter.getRelDataType(Type.STRING));
+    String nanOrInf = o.toString();
+    List<Expr> argList =
+        Lists.newArrayList(new StringLiteral(nanOrInf, Type.STRING, false));
+    Preconditions.checkState(t.equals(Type.DOUBLE) || t.equals(Type.FLOAT));
+    String fnName = t.equals(Type.DOUBLE) ? "casttodouble" : "casttofloat";
+    Function castFunc = FunctionResolver.getExactFunction(fnName, typeNames);
+    return new AnalyzedFunctionCallExpr(castFunc, argList, t);
+  }
 }
diff --git a/testdata/workloads/functional-query/queries/QueryTest/calcite.test 
b/testdata/workloads/functional-query/queries/QueryTest/calcite.test
index a514be751..db57ca70c 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/calcite.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/calcite.test
@@ -1121,3 +1121,10 @@ int
 ---- RUNTIME_PROFILE
 row_regex: .*PlannerType: CalcitePlanner.*
 ====
+---- QUERY
+select cast('nan' as double), cast('inf' as float);
+---- RESULTS
+NaN,Inf
+---- TYPES
+DOUBLE, FLOAT
+====

Reply via email to