Skip to content

Commit

Permalink
[CALCITE-4988] ((A IS NOT NULL OR B) AND A IS NOT NULL) can't be simp…
Browse files Browse the repository at this point in the history
…lify to (A IS NOT NULL) When A is deterministic
  • Loading branch information
NobiGo authored and liyafan82 committed Mar 4, 2022
1 parent 07edf27 commit 4c73e85
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 2 deletions.
4 changes: 2 additions & 2 deletions core/src/main/java/org/apache/calcite/rex/RexSimplify.java
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ private RexNode simplifyIs(RexCall call, RexUnknownAs unknownAs) {
}

private @Nullable RexNode simplifyIsPredicate(SqlKind kind, RexNode a) {
if (!RexUtil.isReferenceOrAccess(a, true)) {
if (!(RexUtil.isReferenceOrAccess(a, true) || RexUtil.isDeterministic(a))) {
return null;
}

Expand Down Expand Up @@ -2664,7 +2664,7 @@ private IsPredicate(RexNode ref, SqlKind kind) {
case IS_NULL:
case IS_NOT_NULL:
RexNode pA = ((RexCall) e).getOperands().get(0);
if (!RexUtil.isReferenceOrAccess(pA, true)) {
if (!(RexUtil.isReferenceOrAccess(pA, true) || RexUtil.isDeterministic(pA))) {
return null;
}
return new IsPredicate(pA, e.getKind());
Expand Down
76 changes: 76 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 @@ -2157,6 +2157,82 @@ trueLiteral, literal(1),
checkSimplify(isNotNull(cast(i2, intType)), "true");
}

/**
* Unit test for
* <a href="https://issues.apache.org/jira/browse/CALCITE-4988">[CALCITE-4988]
* ((A IS NOT NULL OR B) AND A IS NOT NULL) can't be simplify to (A IS NOT NULL)
* When A is deterministic</a>. */
@Test void testSimplifyIsNotNullWithDeterministic() {
// "(A IS NOT NULL OR B) AND A IS NOT NULL" when A is deterministic
// ==>
// "A IS NOT NULL"
SqlOperator dc = getDeterministicOperator();
checkSimplify2(
and(or(isNotNull(rexBuilder.makeCall(dc)), gt(vInt(2), literal(2))),
isNotNull(rexBuilder.makeCall(dc))),
"AND(OR(IS NOT NULL(DC()), >(?0.int2, 2)), IS NOT NULL(DC()))",
"IS NOT NULL(DC())");
}

@Test void testSimplifyIsNotNullWithDeterministic2() {
// "(A IS NOT NULL AND B) OR A IS NULL" when A is deterministic
// ==>
// "A IS NULL OR B"
SqlOperator dc = getDeterministicOperator();
checkSimplify(
or(and(isNotNull(rexBuilder.makeCall(dc)), gt(vInt(2), literal(2))),
isNull(rexBuilder.makeCall(dc))),
"OR(IS NULL(DC()), >(?0.int2, 2))");
}

@Test void testSimplifyIsNotNullWithNoDeterministic() {
// "(A IS NOT NULL OR B) AND A IS NOT NULL" when A is not deterministic
// ==>
// "(A IS NOT NULL OR B) AND A IS NOT NULL"
SqlOperator ndc = getNoDeterministicOperator();
checkSimplifyUnchanged(
and(or(isNotNull(rexBuilder.makeCall(ndc)), gt(vInt(2), literal(2))),
isNotNull(rexBuilder.makeCall(ndc))));
}

@Test void testSimplifyIsNotNullWithNoDeterministic2() {
// "(A IS NOT NULL AND B) OR A IS NOT NULL" when A is not deterministic
// ==>
// "(A IS NOT NULL AND B) OR A IS NOT NULL"
SqlOperator ndc = getNoDeterministicOperator();
checkSimplifyUnchanged(
and(or(isNotNull(rexBuilder.makeCall(ndc)), gt(vInt(2), literal(2))),
isNotNull(rexBuilder.makeCall(ndc))));
}

private SqlOperator getDeterministicOperator() {
return new SqlSpecialOperator(
"DC",
SqlKind.OTHER_FUNCTION,
0,
false,
ReturnTypes.BOOLEAN_FORCE_NULLABLE,
null, null) {
@Override public boolean isDeterministic() {
return true;
}
};
}

private SqlOperator getNoDeterministicOperator() {
return new SqlSpecialOperator(
"NDC",
SqlKind.OTHER_FUNCTION,
0,
false,
ReturnTypes.BOOLEAN_FORCE_NULLABLE,
null, null) {
@Override public boolean isDeterministic() {
return false;
}
};
}

/** Unit test for
* <a href="https://issues.apache.org/jira/browse/CALCITE-2929">[CALCITE-2929]
* Simplification of IS NULL checks are incorrectly assuming that CAST-s are possible</a>. */
Expand Down

0 comments on commit 4c73e85

Please sign in to comment.