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 <[email protected]>
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]]>