You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by mi...@apache.org on 2025/11/05 22:43:06 UTC
(impala) 01/04: IMPALA-14414: Calcite planner: Added new code to handle nan/inf
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 <sc...@cloudera.com>
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 <im...@cloudera.com>
Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
.../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
+====