Repository: calcite Updated Branches: refs/heads/master 453e928b6 -> 06c18ca74
[CALCITE-2007] Fix RexSimplify behavior when literals come first. It would incorrectly simplify "1 < x AND x < 3" to "x < 3". Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/06c18ca7 Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/06c18ca7 Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/06c18ca7 Branch: refs/heads/master Commit: 06c18ca74df2d4bf20a5dccef11d424ab28c97d7 Parents: 453e928 Author: Gian Merlino <[email protected]> Authored: Wed Oct 11 16:55:01 2017 -0700 Committer: Gian Merlino <[email protected]> Committed: Wed Oct 11 20:53:42 2017 -0700 ---------------------------------------------------------------------- .../org/apache/calcite/rex/RexSimplify.java | 50 ++++++++++++++++---- .../org/apache/calcite/test/RexProgramTest.java | 24 ++++++++++ 2 files changed, 64 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/06c18ca7/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 f826c77..464d28f 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java +++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java @@ -1125,12 +1125,9 @@ public class RexSimplify { if (removeUpperBound) { ImmutableList.Builder<RexNode> newBounds = ImmutableList.builder(); for (RexNode e : p.right) { - switch (e.getKind()) { - case LESS_THAN: - case LESS_THAN_OR_EQUAL: + if (isUpperBound(e)) { Collections.replaceAll(terms, e, rexBuilder.makeLiteral(true)); - break; - default: + } else { newBounds.add(e); } } @@ -1140,12 +1137,9 @@ public class RexSimplify { } else if (removeLowerBound) { ImmutableList.Builder<RexNode> newBounds = ImmutableList.builder(); for (RexNode e : p.right) { - switch (e.getKind()) { - case GREATER_THAN: - case GREATER_THAN_OR_EQUAL: + if (isLowerBound(e)) { Collections.replaceAll(terms, e, rexBuilder.makeLiteral(true)); - break; - default: + } else { newBounds.add(e); } } @@ -1218,6 +1212,42 @@ public class RexSimplify { return null; } } + + private static boolean isUpperBound(final RexNode e) { + final List<RexNode> operands; + switch (e.getKind()) { + case LESS_THAN: + case LESS_THAN_OR_EQUAL: + operands = ((RexCall) e).getOperands(); + return RexUtil.isReferenceOrAccess(operands.get(0), true) + && operands.get(1).isA(SqlKind.LITERAL); + case GREATER_THAN: + case GREATER_THAN_OR_EQUAL: + operands = ((RexCall) e).getOperands(); + return RexUtil.isReferenceOrAccess(operands.get(1), true) + && operands.get(0).isA(SqlKind.LITERAL); + default: + return false; + } + } + + private static boolean isLowerBound(final RexNode e) { + final List<RexNode> operands; + switch (e.getKind()) { + case LESS_THAN: + case LESS_THAN_OR_EQUAL: + operands = ((RexCall) e).getOperands(); + return RexUtil.isReferenceOrAccess(operands.get(1), true) + && operands.get(0).isA(SqlKind.LITERAL); + case GREATER_THAN: + case GREATER_THAN_OR_EQUAL: + operands = ((RexCall) e).getOperands(); + return RexUtil.isReferenceOrAccess(operands.get(0), true) + && operands.get(1).isA(SqlKind.LITERAL); + default: + return false; + } + } } // End RexSimplify.java http://git-wip-us.apache.org/repos/asf/calcite/blob/06c18ca7/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 d42cfbb..6cc4e44 100644 --- a/core/src/test/java/org/apache/calcite/test/RexProgramTest.java +++ b/core/src/test/java/org/apache/calcite/test/RexProgramTest.java @@ -1329,6 +1329,30 @@ public class RexProgramTest { // condition with null value for range checkSimplifyFilter(and(gt(aRef, unknownLiteral), ge(bRef, literal1)), "false"); + // condition "1 < a && 5 < x" yields "5 < x" + checkSimplifyFilter( + and(lt(literal1, aRef), lt(literal5, aRef)), + RelOptPredicateList.EMPTY, + "<(5, ?0.a)"); + + // condition "1 < a && a < 5" is unchanged + checkSimplifyFilter( + and(lt(literal1, aRef), lt(aRef, literal5)), + RelOptPredicateList.EMPTY, + "AND(<(1, ?0.a), <(?0.a, 5))"); + + // condition "1 > a && 5 > x" yields "1 > a" + checkSimplifyFilter( + and(gt(literal1, aRef), gt(literal5, aRef)), + RelOptPredicateList.EMPTY, + ">(1, ?0.a)"); + + // condition "1 > a && a > 5" yields false + checkSimplifyFilter( + and(gt(literal1, aRef), gt(aRef, literal5)), + RelOptPredicateList.EMPTY, + "false"); + // range with no predicates; // condition "a > 1 && a < 10 && a < 5" yields "a < 1 && a < 5" checkSimplifyFilter(
