This is an automated email from the ASF dual-hosted git repository. xiong pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push: new 4a6e222 [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 4a6e222 is described below commit 4a6e2228c2e2ccf46acb31a0342a1b7d4563e2f6 Author: NobiGo <nobigo...@gmail.com> AuthorDate: Fri Jan 21 19:05:22 2022 +0800 [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 --- .../java/org/apache/calcite/rex/RexSimplify.java | 4 +- .../org/apache/calcite/rex/RexProgramTest.java | 76 ++++++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java index 96338ab..7c0aa6b 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java +++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java @@ -865,7 +865,7 @@ public class RexSimplify { } private @Nullable RexNode simplifyIsPredicate(SqlKind kind, RexNode a) { - if (!RexUtil.isReferenceOrAccess(a, true)) { + if (!(RexUtil.isReferenceOrAccess(a, true) || RexUtil.isDeterministic(a))) { return null; } @@ -2664,7 +2664,7 @@ public class RexSimplify { 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()); diff --git a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java index 9edb64a..691c954 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java +++ b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java @@ -2157,6 +2157,82 @@ class RexProgramTest extends RexProgramTestBase { 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>. */