Repository: calcite Updated Branches: refs/heads/master af3e35d64 -> 141781bf4
[CALCITE-2327] Avoid simplification of x AND NOT(x) to false for nullable x x AND NOT(x) ==> FALSE AND x IS NULL closes #707 Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/141781bf Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/141781bf Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/141781bf Branch: refs/heads/master Commit: 141781bf4d591d973812c73ea9f03d715b5406cb Parents: af3e35d Author: Vladimir Sitnikov <[email protected]> Authored: Tue Aug 28 10:36:40 2018 +0300 Committer: Vladimir Sitnikov <[email protected]> Committed: Tue Aug 28 11:42:40 2018 +0300 ---------------------------------------------------------------------- .../org/apache/calcite/rex/RexSimplify.java | 22 +++++++++++++++++++- .../org/apache/calcite/test/RexProgramTest.java | 4 +--- 2 files changed, 22 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/141781bf/core/src/main/java/org/apache/calcite/rex/RexSimplify.java ---------------------------------------------------------------------- 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 7aaf141..1274391 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java +++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java @@ -718,11 +718,31 @@ public class RexSimplify { // Example #1. x AND y AND z AND NOT (x AND y) - not satisfiable // Example #2. x AND y AND NOT (x AND y) - not satisfiable // Example #3. x AND y AND NOT (x AND y AND z) - may be satisfiable + RexNode bestNotDisjunction = null; for (RexNode notDisjunction : notTerms) { final List<RexNode> terms2 = RelOptUtil.conjunctions(notDisjunction); - if (terms.containsAll(terms2)) { + if (!terms.containsAll(terms2)) { + // may be satisfiable ==> check other terms + continue; + } + if (!notDisjunction.getType().isNullable()) { + // x is NOT nullable, then x AND NOT(x) ==> FALSE return rexBuilder.makeLiteral(false); } + // x AND NOT(x) is UNKNOWN for NULL input + // So we search for the shortest notDisjunction then convert + // original expression to NULL and x IS NULL + if (bestNotDisjunction == null + || bestNotDisjunction.toString().length() > notDisjunction.toString().length()) { + bestNotDisjunction = notDisjunction; + } + } + if (bestNotDisjunction != null) { + // NULL AND (x IS NULL) + return rexBuilder.makeCall(SqlStdOperatorTable.AND, + rexBuilder.makeNullLiteral(bestNotDisjunction.getType()), + simplifyIs( + (RexCall) rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, bestNotDisjunction))); } // Add the NOT disjunctions back in. for (RexNode notDisjunction : notTerms) { http://git-wip-us.apache.org/repos/asf/calcite/blob/141781bf/core/src/test/java/org/apache/calcite/test/RexProgramTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java index 9a8c27d..990afb6 100644 --- a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java +++ b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java @@ -56,7 +56,6 @@ import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import java.math.BigDecimal; @@ -1543,7 +1542,6 @@ public class RexProgramTest extends RexProgramBuilderBase { "false"); } - @Ignore @Test public void testSimplifyAnd3() { final RelDataType boolType = typeFactory.createSqlType(SqlTypeName.BOOLEAN); final RelDataType rowType = typeFactory.builder() @@ -1557,7 +1555,7 @@ public class RexProgramTest extends RexProgramBuilderBase { checkSimplify2( and(aRef, not(aRef)), - "a is null and null", + "AND(null, IS NULL(?0.a))", "false"); }
