Skip to content
Merged
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
39 changes: 38 additions & 1 deletion core/src/main/java/org/apache/calcite/rex/RexSimplify.java
Original file line number Diff line number Diff line change
Expand Up @@ -1560,18 +1560,55 @@ private <C extends Comparable<C>> RexNode simplifyAnd2ForUnknownAsFalse(
return RexUtil.composeConjunction(rexBuilder, terms);
}

private RexNode simplifyNotEqual(RexNode e) {
final Comparison comparison = Comparison.of(e);
if (comparison == null) {
return e;
}

for (RexNode node: predicates.pulledUpPredicates) {
final Comparison predicate = Comparison.of(node);
if (predicate == null
|| predicate.kind != SqlKind.EQUALS
|| !predicate.ref.equals(comparison.ref)) {
continue;
}

// Given x=5, x!=5 can be simplified to 'null and x is null' and x!=3 can
// be simplified to 'null or x is not null'.
RexNode simplified;
if (predicate.literal.equals(comparison.literal)) {
simplified = rexBuilder.makeCall(SqlStdOperatorTable.AND,
rexBuilder.makeNullLiteral(e.getType()),
rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, comparison.ref));
} else {
simplified = rexBuilder.makeCall(SqlStdOperatorTable.OR,
rexBuilder.makeNullLiteral(e.getType()),
rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, comparison.ref));
}
return simplify(simplified);
}

return e;
}

private <C extends Comparable<C>> RexNode simplifyUsingPredicates(RexNode e,
Class<C> clazz) {
if (predicates.pulledUpPredicates.isEmpty()) {
return e;
}

if (e.getKind() == SqlKind.NOT_EQUALS) {
return simplifyNotEqual(e);
}

final Comparison comparison = Comparison.of(e);
// Check for comparison with null values
if (comparison == null
|| comparison.kind == SqlKind.NOT_EQUALS
|| comparison.literal.getValue() == null) {
return e;
}

final C v0 = comparison.literal.getValueAs(clazz);
final Range<C> range = range(comparison.kind, v0);
final Range<C> range2 =
Expand Down
14 changes: 14 additions & 0 deletions core/src/test/java/org/apache/calcite/rex/RexProgramTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2551,6 +2551,20 @@ private static String getString(ImmutableMap<RexNode, RexNode> map) {
checkSimplifyFilter(gt(ref, literal(9)), relOptPredicateList, "false");
}

@Test public void testSimplifyNotEqual() {
RexNode ref = input(tInt(), 0);
RelOptPredicateList relOptPredicateList = RelOptPredicateList.of(rexBuilder,
ImmutableList.of(eq(ref, literal(9))));
checkSimplifyFilter(ne(ref, literal(9)), relOptPredicateList, "false");
checkSimplifyFilter(ne(ref, literal(5)), relOptPredicateList, "true");

ref = input(tInt(true), 0);
checkSimplifyFilter(ne(ref, literal(9)), relOptPredicateList,
"AND(null, IS NULL($0))");
checkSimplifyFilter(ne(ref, literal(5)), relOptPredicateList,
"OR(null, IS NOT NULL($0))");
}

@Test public void testSimplifyNonDeterministicFunction() {
final SqlOperator ndc = new SqlSpecialOperator(
"NDC",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,7 @@ private static void checkNoMaterialize_(String materialize, String query,
SqlStdOperatorTable.AND,
i0_eq_0,
i1_eq_1)));
checkSatisfiable(e6, "AND(=($0, 0), OR(<>($0, 0), <>($1, 1)))");
checkSatisfiable(e6, "AND(=($0, 0), <>($1, 1))");

// "$0 = 0 AND ($1 = 1 AND NOT ($0 = 0))" is not satisfiable.
final RexNode e7 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ where case when (sal = 1000) then
<Resource name="planAfter">
<![CDATA[
LogicalProject(SAL=[$5])
LogicalFilter(condition=[OR(=($5, 1000), AND(=($5, 2000), <>($5, 1000)))])
LogicalFilter(condition=[OR(=($5, 1000), =($5, 2000))])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
</Resource>
Expand Down