Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,15 @@ public static Expression convert(Expression operand, Type fromType,
}
}
}
if (toType == Number.class
&& (fromType == Object.class || fromType == String.class)) {
// E.g. from "Object" to "Number".
// Generate "x == null ? null : SqlFunctions.toBigDecimal(x)".
return Expressions.condition(
Expressions.equal(operand, RexImpTable.NULL_EXPR),
RexImpTable.NULL_EXPR,
Expressions.call(SqlFunctions.class, "toBigDecimal", operand));
}
if (toPrimitive != null) {
if (fromPrimitive != null) {
// E.g. from "float" to "double"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,29 @@
*/
public final class EnumUtilsTest {

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-6284">[CALCITE-6284]
* Invalid conversion triggers ClassCastException</a>. */
@Test void testObjectToNumberConvert() {
// Object x;
final ParameterExpression objectVariable =
Expressions.parameter(0, Object.class, "x");
final Expression objectToNumber =
EnumUtils.convert(objectVariable, Number.class);
assertThat(Expressions.toString(objectToNumber),
is("x == null ? (java.math.BigDecimal) null"
+ " : org.apache.calcite.runtime.SqlFunctions.toBigDecimal(x)"));

// String s;
final ParameterExpression stringVariable =
Expressions.parameter(0, String.class, "s");
final Expression stringToNumber =
EnumUtils.convert(stringVariable, Number.class);
assertThat(Expressions.toString(stringToNumber),
is("s == null ? (java.math.BigDecimal) null"
+ " : org.apache.calcite.runtime.SqlFunctions.toBigDecimal(s)"));
}

@Test void testDateTypeToInnerTypeConvert() {
// java.sql.Date x;
final ParameterExpression date =
Expand Down
18 changes: 18 additions & 0 deletions core/src/test/java/org/apache/calcite/test/JdbcTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9695,6 +9695,24 @@ void checkCalciteSchemaGetSubSchemaMap(boolean cache) {
}
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-6284">[CALCITE-6284]
* Invalid conversion triggers ClassCastException</a>. */
@Test void bindStringParameter() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bug report is about the message produced when the conversion FAILS.
What happens if you pass a non-numeric string?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing that out. The original test only covered the success path. I added bindInvalidStringParameter() and improved the error message:
Before: NumberFormatException with null message.
After: NumberFormatException: Invalid value for BigDecimal: "abc".

for (SqlTypeName tpe : SqlTypeName.INT_TYPES) {
final String sql =
"with cte as (select cast(100 as " + tpe.getName() + ") as empid)"
+ "select * from cte where empid = ?";

CalciteAssert.hr()
.query(sql)
.consumesPreparedStatement(p -> {
p.setString(1, "100");
})
.returnsUnordered("EMPID=100");
}
}

@Test void bindShortParameter() {
for (SqlTypeName tpe : SqlTypeName.INT_TYPES) {
final String sql =
Expand Down
Loading