Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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 @@ -5050,11 +5050,27 @@ protected Expression valueExpression(RexToLixTranslator.Result left,
Expressions.condition(right.isNullVariable, BOXED_TRUE_EXPR, BOXED_FALSE_EXPR),
Expressions.condition(right.isNullVariable, BOXED_FALSE_EXPR,
Expressions.condition(
Expressions.call(BuiltInMethod.OBJECTS_EQUAL.method,
left.valueVariable, right.valueVariable),
equalExpression(left.valueVariable, right.valueVariable),
BOXED_TRUE_EXPR, BOXED_FALSE_EXPR)));
}

/** Returns an expression that compares two non-null values for
* equality.
*
* <p>{@link BigDecimal#equals} is sensitive to scale (for example,
* {@code 1.10} is not equal to {@code 1.1}), so {@code BigDecimal} values
* are compared using {@link SqlFunctions#eq(BigDecimal, BigDecimal)}, as
* the {@code =} operator compares them. Other values are compared using
* {@link java.util.Objects#equals}. */
private static Expression equalExpression(Expression left,
Expression right) {
if (left.getType() == BigDecimal.class
&& right.getType() == BigDecimal.class) {
return Expressions.call(BuiltInMethod.EQ_DECIMAL.method, left, right);
}
return Expressions.call(BuiltInMethod.OBJECTS_EQUAL.method, left, right);
}

@Override Expression implementSafe(final RexToLixTranslator translator,
final RexCall call, final List<Expression> argValueList) {
throw new IllegalStateException("This implementSafe should not be called,"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ public enum BuiltInMethod {
Comparable.class),
LT(SqlFunctions.class, "lt", boolean.class, boolean.class),
GT(SqlFunctions.class, "gt", boolean.class, boolean.class),
EQ_DECIMAL(SqlFunctions.class, "eq", BigDecimal.class, BigDecimal.class),
BIT_AND(SqlFunctions.class, "bitAnd", long.class, long.class),
BITCOUNT(SqlFunctions.class, "bitCount", BigDecimal.class),
BIT_OR(SqlFunctions.class, "bitOr", long.class, long.class),
Expand Down
32 changes: 32 additions & 0 deletions core/src/test/java/org/apache/calcite/test/RelBuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4908,6 +4908,38 @@ private static RelBuilder assertSize(RelBuilder b,
}
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-7826">[CALCITE-7826]
* IS NOT DISTINCT FROM gives wrong result in Enumerable convention when
* applied to DECIMAL values of different scales</a>. */
@Test void testIsNotDistinctFromDecimal() throws Exception {
// Equivalent SQL:
// SELECT a, b, a = b AS eq, a IS NOT DISTINCT FROM b AS indf,
// a IS DISTINCT FROM b AS idf
// FROM (VALUES (1.10, 1.1)) AS t (a, b)
// but SqlToRelConverter and RelBuilder.isNotDistinctFrom expand IS [NOT]
// DISTINCT FROM, so we call the operators directly. "a" has type
// DECIMAL(3, 2) and "b" has type DECIMAL(2, 1).
final RelBuilder b = RelBuilder.create(config().build());
final RelNode root =
b.values(new String[] {"a", "b"},
new BigDecimal("1.10"), new BigDecimal("1.1"))
.project(b.field("a"), b.field("b"),
b.alias(b.equals(b.field("a"), b.field("b")), "eq"),
b.alias(
b.call(SqlStdOperatorTable.IS_NOT_DISTINCT_FROM,
b.field("a"), b.field("b")), "indf"),
b.alias(
b.call(SqlStdOperatorTable.IS_DISTINCT_FROM,
b.field("a"), b.field("b")), "idf"))
.build();
try (PreparedStatement preparedStatement = RelRunners.run(root)) {
String s = CalciteAssert.toString(preparedStatement.executeQuery());
final String result = "a=1.10; b=1.1; eq=true; indf=true; idf=false\n";
assertThat(s, is(result));
}
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-1595">[CALCITE-1595]
* RelBuilder.call throws NullPointerException if argument types are
Expand Down
Loading