This is an automated email from the ASF dual-hosted git repository. xiong pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push: new b8ffcce8ec [CALCITE-5780] Simplify '1 > x OR 1 <= x OR x IS NULL' to TRUE b8ffcce8ec is described below commit b8ffcce8ecbfe7222c814b887c4c2dc1647853f3 Author: Runkang He <hrun...@gmail.com> AuthorDate: Thu Jun 15 08:34:58 2023 +0800 [CALCITE-5780] Simplify '1 > x OR 1 <= x OR x IS NULL' to TRUE --- .../java/org/apache/calcite/rex/RexSimplify.java | 11 ++-- .../org/apache/calcite/rex/RexProgramTest.java | 64 +++++++++++++++++++++- core/src/test/resources/sql/conditions.iq | 28 ++++++++++ 3 files changed, 96 insertions(+), 7 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 9068726a49..ef10a271e5 100644 --- a/core/src/main/java/org/apache/calcite/rex/RexSimplify.java +++ b/core/src/main/java/org/apache/calcite/rex/RexSimplify.java @@ -1887,11 +1887,10 @@ public class RexSimplify { case GREATER_THAN: case GREATER_THAN_OR_EQUAL: final RexCall call = (RexCall) predicate; - if (call.operands.get(0).equals(ref) - && call.operands.get(1) instanceof RexLiteral) { - final RexLiteral literal = (RexLiteral) call.operands.get(1); - final C c1 = literal.getValueAs(clazz); - assert c1 != null : "value must not be null in " + literal; + final Comparison comparison = Comparison.of(call); + if (comparison != null && comparison.ref.equals(ref)) { + final C c1 = comparison.literal.getValueAs(clazz); + assert c1 != null : "value must not be null in " + comparison.literal; switch (predicate.getKind()) { case NOT_EQUALS: // We want to intersect result with the range set of everything but @@ -1906,7 +1905,7 @@ public class RexSimplify { result = RangeSets.minus(result, pointRange); break; default: - final Range<C> r1 = range(predicate.getKind(), c1); + final Range<C> r1 = range(comparison.kind, c1); if (result.encloses(r1)) { // Given these predicates, term is always satisfied. // e.g. r0 is "$0 < 10", r1 is "$0 < 5" 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 e2f7562462..9af7b8e299 100644 --- a/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java +++ b/core/src/test/java/org/apache/calcite/rex/RexProgramTest.java @@ -1145,7 +1145,7 @@ class RexProgramTest extends RexProgramTestBase { checkSimplifyFilter( and(gt(literal(1), aRef), gt(literal(5), aRef)), RelOptPredicateList.EMPTY, - "<(?0.a, 1)"); + ">(1, ?0.a)"); // condition "1 > a && a > 5" yields false checkSimplifyFilter( @@ -1604,6 +1604,68 @@ class RexProgramTest extends RexProgramTestBase { "true"); } + /** Unit test for + * <a href="https://issues.apache.org/jira/browse/CALCITE-5780">[CALCITE-5780] + * Simplify '1 > x OR 1 <= x OR x IS NULL' to TRUE</a>. */ + @Test void testSimplifyOrTermsWithReverseOrderComparison() { + final RelDataType intType = typeFactory.createSqlType(SqlTypeName.INTEGER); + final RelDataType rowType = typeFactory.builder() + .add("a", intType).nullable(true) + .build(); + + final RexDynamicParam range = rexBuilder.makeDynamicParam(rowType, 0); + final RexNode aRef = rexBuilder.makeFieldAccess(range, 0); + + // "1 > a or 1 <= a or a is null" ==> "true" + checkSimplifyFilter( + or(gt(literal(1), aRef), + le(literal(1), aRef), + isNull(aRef)), + "true"); + + // "1 <= a or 1 > a or a is null" ==> "true" + checkSimplifyFilter( + or(le(literal(1), aRef), + gt(literal(1), aRef), + isNull(aRef)), + "true"); + + // "a is null or 1 > a or 1 <= a" ==> "true" + checkSimplifyFilter( + or(isNull(aRef), + gt(literal(1), aRef), + le(literal(1), aRef)), + "true"); + + // "2 > a or 0 < a or a is null" ==> "true" + checkSimplifyFilter( + or(gt(literal(2), aRef), + lt(literal(0), aRef), + isNull(aRef)), + "true"); + + // "1 > a or a >= 1 or a is null" ==> "true" + checkSimplifyFilter( + or(gt(literal(1), aRef), + ge(aRef, literal(1)), + isNull(aRef)), + "true"); + + // "1 <= a or a < 1 or a is null" ==> "true" + checkSimplifyFilter( + or(le(literal(1), aRef), + lt(aRef, literal(1)), + isNull(aRef)), + "true"); + + // "a >= 1 or 1 > a or a is null" ==> "true" + checkSimplifyFilter( + or(ge(aRef, literal(1)), + gt(literal(1), aRef), + isNull(aRef)), + "true"); + } + @Test void testSimplifyRange() { final RexNode aRef = input(tInt(), 0); // ((0 < a and a <= 10) or a >= 15) and a <> 6 and a <> 12 diff --git a/core/src/test/resources/sql/conditions.iq b/core/src/test/resources/sql/conditions.iq index 1ef97e206a..a5bf3d29d2 100644 --- a/core/src/test/resources/sql/conditions.iq +++ b/core/src/test/resources/sql/conditions.iq @@ -490,5 +490,33 @@ where emp.empno = 7902; !ok +# Test case for [CALCITE-5780] Simplify '1 > x OR 1 <= x OR x IS NULL' to TRUE +select * +from "scott".emp +where 5 < deptno OR 5 >= deptno OR deptno IS NULL; ++-------+--------+-----------+------+------------+---------+---------+--------+ +| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | ++-------+--------+-----------+------+------------+---------+---------+--------+ +| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800.00 | | 20 | +| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 | 30 | +| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 | 30 | +| 7566 | JONES | MANAGER | 7839 | 1981-02-04 | 2975.00 | | 20 | +| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 | 30 | +| 7698 | BLAKE | MANAGER | 7839 | 1981-01-05 | 2850.00 | | 30 | +| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | | 10 | +| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | | 20 | +| 7839 | KING | PRESIDENT | | 1981-11-17 | 5000.00 | | 10 | +| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 | 30 | +| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100.00 | | 20 | +| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950.00 | | 30 | +| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | | 20 | +| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | | 10 | ++-------+--------+-----------+------+------------+---------+---------+--------+ +(14 rows) + +!ok + +EnumerableTableScan(table=[[scott, EMP]]) +!plan # End conditions.iq