mirror of
https://github.com/apache/impala.git
synced 2025-12-19 18:12:08 -05:00
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 <impala-public-jenkins@cloudera.com> Tested-by: Impala Public Jenkins <impala-public-jenkins@cloudera.com>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
====
|
||||
|
||||
Reference in New Issue
Block a user