Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CALCITE-3845] CASE WHEN expression with nullability CAST is considered as reduced wrongly in ReduceExpressionsRule #1848

Merged
merged 1 commit into from Mar 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -302,6 +302,8 @@ public ProjectReduceExpressionsRule(Class<? extends Project> projectClass,
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())
Expand Down Expand Up @@ -608,6 +610,7 @@ protected static boolean reduceExpressions(RelNode rel, List<RexNode> expList,
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 =
Expand All @@ -629,6 +632,10 @@ protected static boolean reduceExpressions(RelNode rel, List<RexNode> expList,
}
}

if (reduced && simplified) {
return !originExpList.equals(expList);
}

return reduced || simplified;
}

Expand Down
46 changes: 46 additions & 0 deletions core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
Expand Up @@ -128,6 +128,7 @@
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;
Expand Down Expand Up @@ -3480,6 +3481,51 @@ private void checkReduceNullableToNotNull(ReduceExpressionsRule rule) {
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));
Comment on lines +3499 to +3506
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks way too verbose :-/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish I can provide a more simple case, but I cannot. Because CASE WHEN will be changed to OR in many cases and thus it will not reproduce the issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is signal to noise ratio leaves much to be desired here.
The dance of rexBuilder.makeCall(SqlStdOperatorTable repeats again and again :(


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)
Expand Down
Expand Up @@ -8066,6 +8066,20 @@ LogicalTableModify(table=[[CATALOG, SALES, DEPT]], operation=[INSERT], flattened
LogicalTableModify(table=[[CATALOG, SALES, DEPT]], operation=[INSERT], flattened=[false])
LogicalCalc(expr#0..8=[{inputs}], expr#9=[CAST($t2):VARCHAR(10) NOT NULL], DEPTNO=[$t0], NAME=[$t9])
LogicalTableScan(table=[[CATALOG, SALES, EMPNULLABLES]])
]]>
</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>
Expand Down