This is an automated email from the ASF dual-hosted git repository.

chunwei 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 ad8cf7e  [CALCITE-3845] CASE WHEN expression with nullability CAST is 
considered as reduced wrongly in ReduceExpressionsRule
ad8cf7e is described below

commit ad8cf7e0e96137c40103e0e83539b59e43513b17
Author: Chunwei Lei <chunwei.l...@gmail.com>
AuthorDate: Fri Mar 6 15:29:27 2020 +0800

    [CALCITE-3845] CASE WHEN expression with nullability CAST is considered as 
reduced wrongly in ReduceExpressionsRule
---
 .../calcite/rel/rules/ReduceExpressionsRule.java   |  7 ++++
 .../org/apache/calcite/test/RelOptRulesTest.java   | 46 ++++++++++++++++++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml    | 14 +++++++
 3 files changed, 67 insertions(+)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java 
b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
index 602e955..2fd890d 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
@@ -304,6 +304,8 @@ public abstract class ReduceExpressionsRule extends 
RelOptRule
           Lists.newArrayList(project.getProjects());
       if (reduceExpressions(project, expList, predicates, false,
           matchNullability)) {
+        assert !project.getProjects().equals(expList)
+            : "Reduced expressions should be different from original 
expressions";
         call.transformTo(
             call.builder()
                 .push(project.getInput())
@@ -610,6 +612,7 @@ public abstract class ReduceExpressionsRule extends 
RelOptRule
       boolean matchNullability) {
     final RelOptCluster cluster = rel.getCluster();
     final RexBuilder rexBuilder = cluster.getRexBuilder();
+    final List<RexNode> originExpList = Lists.newArrayList(expList);
     final RexExecutor executor =
         Util.first(cluster.getPlanner().getExecutor(), RexUtil.EXECUTOR);
     final RexSimplify simplify =
@@ -631,6 +634,10 @@ public abstract class ReduceExpressionsRule extends 
RelOptRule
       }
     }
 
+    if (reduced && simplified) {
+      return !originExpList.equals(expList);
+    }
+
     return reduced || simplified;
   }
 
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java 
b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
index 728e1fc..2a083f3 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -128,6 +128,7 @@ import org.apache.calcite.rel.rules.UnionToDistinctRule;
 import org.apache.calcite.rel.rules.ValuesReduceRule;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexNode;
@@ -3480,6 +3481,51 @@ public class RelOptRulesTest extends RelOptTestBase {
     sql(sql).with(program).check();
   }
 
+  @Test public void testReduceCaseWhenWithCast() {
+    final RelBuilder relBuilder = 
RelBuilder.create(RelBuilderTest.config().build());
+    final RexBuilder rexBuilder = relBuilder.getRexBuilder();
+    final RelDataType type = 
rexBuilder.getTypeFactory().createSqlType(SqlTypeName.BIGINT);
+
+    RelNode left = relBuilder
+        .values(new String[]{"x", "y"}, 1, 2).build();
+    RexNode ref = rexBuilder.makeInputRef(left, 0);
+    RexNode literal1 = rexBuilder.makeLiteral(1, type, false);
+    RexNode literal2 = rexBuilder.makeLiteral(2, type, false);
+    RexNode literal3 = rexBuilder.makeLiteral(3, type, false);
+
+    // CASE WHEN x % 2 = 1 THEN x < 2
+    //      WHEN x % 3 = 2 THEN x < 1
+    //      ELSE x < 3
+    final RexNode caseRexNode = rexBuilder.makeCall(SqlStdOperatorTable.CASE,
+        rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
+            rexBuilder.makeCall(SqlStdOperatorTable.MOD, ref, literal2), 
literal1),
+        rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, ref, literal2),
+        rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
+            rexBuilder.makeCall(SqlStdOperatorTable.MOD, ref, literal3), 
literal2),
+        rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, ref, literal1),
+        rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, ref, literal3));
+
+    final RexNode castNode = rexBuilder.makeCast(rexBuilder.getTypeFactory().
+        createTypeWithNullability(caseRexNode.getType(), true), caseRexNode);
+    final RelNode root = relBuilder
+        .push(left)
+        .project(castNode)
+        .build();
+
+    HepProgramBuilder builder = new HepProgramBuilder();
+    builder.addRuleClass(ReduceExpressionsRule.class);
+
+    HepPlanner hepPlanner = new HepPlanner(builder.build());
+    hepPlanner.addRule(ReduceExpressionsRule.PROJECT_INSTANCE);
+    hepPlanner.setRoot(root);
+
+    RelNode output = hepPlanner.findBestExp();
+    final String planAfter = NL + RelOptUtil.toString(output);
+    final DiffRepository diffRepos = getDiffRepos();
+    diffRepos.assertEquals("planAfter", "${planAfter}", planAfter);
+    SqlToRelTestBase.assertValid(output);
+  }
+
   private void basePushAggThroughUnion() throws Exception {
     HepProgram program = new HepProgramBuilder()
         .addRuleInstance(ProjectSetOpTransposeRule.INSTANCE)
diff --git 
a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml 
b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index bd22930..9d04144 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -8067,6 +8067,20 @@ LogicalTableModify(table=[[CATALOG, SALES, DEPT]], 
operation=[INSERT], flattened
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testReduceCaseWhenWithCast">
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalProject($f0=[CAST(CASE(=(MOD($0, 2:BIGINT), 1), <($0, 2:BIGINT), 
=(MOD($0, 3:BIGINT), 2), <($0, 1:BIGINT), <($0, 3:BIGINT))):BOOLEAN])
+  LogicalValues(tuples=[[{ 1, 2 }]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalProject($f0=[CAST(CASE(=(MOD($0, 2:BIGINT), 1), <($0, 2:BIGINT), 
=(MOD($0, 3:BIGINT), 2), <($0, 1:BIGINT), <($0, 3:BIGINT))):BOOLEAN])
+  LogicalValues(tuples=[[{ 1, 2 }]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testReduceConstants3">
         <Resource name="sql">
             <![CDATA[select e.mgr is not distinct from f.mgr from emp e join 
emp f on (e.mgr=f.mgr) where e.mgr is null]]>

Reply via email to