suibianwanwank commented on code in PR #4195:
URL: https://github.com/apache/calcite/pull/4195#discussion_r1954776134
##########
core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java:
##########
@@ -910,16 +910,50 @@ private static void matchJoin(SubQueryRemoveRule rule,
RelOptRuleCall call) {
final RelOptUtil.Logic logic =
LogicVisitor.find(RelOptUtil.Logic.TRUE,
ImmutableList.of(join.getCondition()), e);
- builder.push(join.getLeft());
- builder.push(join.getRight());
- final int fieldCount = join.getRowType().getFieldCount();
- final Set<CorrelationId> variablesSet =
- RelOptUtil.getVariablesUsed(e.rel);
- final RexNode target =
- rule.apply(e, variablesSet, logic, builder, 2, fieldCount, 0);
- final RexShuttle shuttle = new ReplaceSubQueryShuttle(e, target);
- builder.join(join.getJoinType(), shuttle.apply(join.getCondition()));
- builder.project(fields(builder, join.getRowType().getFieldCount()));
+
+ ImmutableBitSet inputSet = RelOptUtil.InputFinder.bits(e.getOperands(),
null);
+ int nFieldsLeft = join.getLeft().getRowType().getFieldCount();
+ int nFieldsRight = join.getRight().getRowType().getFieldCount();
+
+ if (inputSet.intersects(ImmutableBitSet.range(0, nFieldsLeft))
Review Comment:
The original rewrite could not support inputRef on either side of a join.
##########
core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java:
##########
@@ -9116,6 +9116,32 @@ public interface Config extends RelRule.Config {
.check();
}
+ /**
+ * Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6824">[CALCITE-6824]
+ * JOIN_SUB_QUERY_TO_CORRELATE rule produces an incorrect plan
+ * when operands are not empty</a>. */
+ @Test void testJoinSubQueryRemoveRule() {
+ final String sql = "SELECT empno FROM emp JOIN dept on "
+ + "emp.deptno not in (SELECT deptno FROM dept)";
+ sql(sql)
+ .withRule(CoreRules.JOIN_SUB_QUERY_TO_CORRELATE)
+ .check();
+ }
+
+ /**
+ * Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6824">[CALCITE-6824]
+ * JOIN_SUB_QUERY_TO_CORRELATE rule produces an incorrect plan
+ * when operands are not empty</a>. */
+ @Test void testJoinSubQueryRemoveRule1() {
Review Comment:
These two tests throw assert exceptions before this PR.
##########
core/src/main/java/org/apache/calcite/rel/rules/SubQueryRemoveRule.java:
##########
@@ -910,16 +910,50 @@ private static void matchJoin(SubQueryRemoveRule rule,
RelOptRuleCall call) {
final RelOptUtil.Logic logic =
LogicVisitor.find(RelOptUtil.Logic.TRUE,
ImmutableList.of(join.getCondition()), e);
- builder.push(join.getLeft());
- builder.push(join.getRight());
- final int fieldCount = join.getRowType().getFieldCount();
- final Set<CorrelationId> variablesSet =
- RelOptUtil.getVariablesUsed(e.rel);
- final RexNode target =
- rule.apply(e, variablesSet, logic, builder, 2, fieldCount, 0);
- final RexShuttle shuttle = new ReplaceSubQueryShuttle(e, target);
- builder.join(join.getJoinType(), shuttle.apply(join.getCondition()));
- builder.project(fields(builder, join.getRowType().getFieldCount()));
+
+ ImmutableBitSet inputSet = RelOptUtil.InputFinder.bits(e.getOperands(),
null);
+ int nFieldsLeft = join.getLeft().getRowType().getFieldCount();
+ int nFieldsRight = join.getRight().getRowType().getFieldCount();
+
+ if (inputSet.intersects(ImmutableBitSet.range(0, nFieldsLeft))
+ && inputSet.intersects(ImmutableBitSet.range(nFieldsLeft, nFieldsLeft
+ nFieldsRight))) {
+ return;
+ }
+
+ if (inputSet.intersects(ImmutableBitSet.range(0, nFieldsLeft))) {
+ builder.push(join.getLeft());
+
+ final Set<CorrelationId> variablesSet =
+ RelOptUtil.getVariablesUsed(e.rel);
+ final RexNode target =
+ rule.apply(e, variablesSet, logic, builder, 1, nFieldsLeft, 0);
+ final RexShuttle shuttle = new ReplaceSubQueryShuttle(e, target);
+
+ RexNode newCond =
+ shuttle.apply(
+ RexUtil.shift(join.getCondition(), nFieldsLeft,
+ builder.fields().size() - nFieldsLeft));
+ builder.push(join.getRight())
+ .join(join.getJoinType(), newCond);
+
+ final int nFields = builder.fields().size();
+ ImmutableList<RexNode> fields =
+ builder.fields(ImmutableBitSet.range(0, nFieldsLeft)
+ .union(ImmutableBitSet.range(nFields - nFieldsRight, nFields)));
+ builder.project(fields);
+ } else {
+ builder.push(join.getLeft()).push(join.getRight());
+
+ final Set<CorrelationId> variablesSet =
+ RelOptUtil.getVariablesUsed(e.rel);
+ final RexNode target =
+ rule.apply(e, variablesSet, logic, builder, 2,
join.getRowType().getFieldCount(), 0);
+ final RexShuttle shuttle = new ReplaceSubQueryShuttle(e, target);
Review Comment:
If inputRef is on the right side of the join, or constants. Follow the
original processing.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]