Skip to content

Commit c0ead01

Browse files
committed
Cast decimal with NUMBER_TO_STRING function
Signed-off-by: Yuanchun Shen <yuanchu@amazon.com>
1 parent 136535e commit c0ead01

2 files changed

Lines changed: 12 additions & 14 deletions

File tree

core/src/main/java/org/opensearch/sql/calcite/ExtendedRexBuilder.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,28 +105,29 @@ public RexNode makeCast(
105105
boolean safe,
106106
RexLiteral format) {
107107
final SqlTypeName sqlType = type.getSqlTypeName();
108+
RelDataType sourceType = exp.getType();
108109
// Calcite bug which doesn't consider to cast literal to boolean
109110
if (exp instanceof RexLiteral && sqlType == SqlTypeName.BOOLEAN) {
110111
if (exp.equals(makeLiteral("1", typeFactory.createSqlType(SqlTypeName.CHAR, 1)))) {
111112
return makeLiteral(true, type);
112113
} else if (exp.equals(makeLiteral("0", typeFactory.createSqlType(SqlTypeName.CHAR, 1)))) {
113114
return makeLiteral(false, type);
114-
} else if (SqlTypeUtil.isExactNumeric(exp.getType())) {
115+
} else if (SqlTypeUtil.isExactNumeric(sourceType)) {
115116
return makeCall(
116117
type,
117118
SqlStdOperatorTable.NOT_EQUALS,
118-
ImmutableList.of(exp, makeZeroLiteral(exp.getType())));
119+
ImmutableList.of(exp, makeZeroLiteral(sourceType)));
119120
// TODO https://github.com/opensearch-project/sql/issues/3443
120121
// Current, we align the behaviour of Spark and Postgres, to align with OpenSearch V2,
121122
// enable following commented codes.
122123
// } else {
123124
// return makeCall(type,
124125
// SqlStdOperatorTable.NOT_EQUALS,
125-
// ImmutableList.of(exp, makeZeroLiteral(exp.getType())));
126+
// ImmutableList.of(exp, makeZeroLiteral(sourceType)));
126127
}
127128
} else if (OpenSearchTypeFactory.isUserDefinedType(type)) {
128129
var udt = ((AbstractExprRelDataType<?>) type).getUdt();
129-
var argExprType = OpenSearchTypeFactory.convertRelDataTypeToExprType(exp.getType());
130+
var argExprType = OpenSearchTypeFactory.convertRelDataTypeToExprType(sourceType);
130131
return switch (udt) {
131132
case EXPR_DATE -> makeCall(type, PPLBuiltinOperators.DATE, List.of(exp));
132133
case EXPR_TIME -> makeCall(type, PPLBuiltinOperators.TIME, List.of(exp));
@@ -150,9 +151,10 @@ public RexNode makeCast(
150151
String.format(Locale.ROOT, "Cannot cast from %s to %s", argExprType, udt.name()));
151152
};
152153
}
153-
// Use a custom operator when casting an approximate numeric (e.g. double) to a character type.
154-
// This patch is necessary because Calcite's built-in CAST converts 0.0 to 0E0 as string.
155-
else if (SqlTypeUtil.isApproximateNumeric(exp.getType()) && SqlTypeUtil.isCharacter(type)) {
154+
// Use a custom operator when casting floating point or decimal number to a character type.
155+
// This patch is necessary because in Calcite, 0.0F is cast to 0E0, decimal 0.x to x
156+
else if ((SqlTypeUtil.isApproximateNumeric(sourceType) || SqlTypeUtil.isDecimal(sourceType))
157+
&& SqlTypeUtil.isCharacter(type)) {
156158
// NUMBER_TO_STRING uses java's built-in method to get the string representation of a number
157159
return makeCall(type, PPLBuiltinOperators.NUMBER_TO_STRING, List.of(exp));
158160
}

core/src/main/java/org/opensearch/sql/expression/function/udf/math/NumberToStringFunction.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@
66
package org.opensearch.sql.expression.function.udf.math;
77

88
import java.util.List;
9-
import java.util.Objects;
109
import org.apache.calcite.adapter.enumerable.NotNullImplementor;
1110
import org.apache.calcite.adapter.enumerable.NullPolicy;
1211
import org.apache.calcite.adapter.enumerable.RexToLixTranslator;
1312
import org.apache.calcite.linq4j.tree.Expression;
1413
import org.apache.calcite.linq4j.tree.Expressions;
15-
import org.apache.calcite.linq4j.tree.Primitive;
1614
import org.apache.calcite.rex.RexCall;
1715
import org.apache.calcite.sql.type.SqlReturnTypeInference;
1816
import org.opensearch.sql.calcite.utils.PPLOperandTypes;
@@ -23,8 +21,8 @@
2321
/**
2422
* A custom implementation of number to string cast.
2523
*
26-
* <p>This operator is necessary because Calcite's built-in CAST converts 0.0 to 0E0 when casting it
27-
* to string.
24+
* <p>This operator is necessary because Calcite's built-in CAST converts floating point 0.0 to 0E0,
25+
* and converts decimal 0.123 to .123 when casting them to string.
2826
*/
2927
public class NumberToStringFunction extends ImplementorUDF {
3028
public NumberToStringFunction() {
@@ -47,9 +45,7 @@ public static class NumberToStringImplementor implements NotNullImplementor {
4745
public Expression implement(
4846
RexToLixTranslator translator, RexCall call, List<Expression> translatedOperands) {
4947
Expression operand = translatedOperands.get(0);
50-
Primitive primitive = Primitive.of(operand.getType());
51-
Objects.requireNonNull(primitive);
52-
return Expressions.call(primitive.getBoxClass(), "toString", operand);
48+
return Expressions.call(Expressions.box(operand), "toString");
5349
}
5450
}
5551
}

0 commit comments

Comments
 (0)