|
16 | 16 | */ |
17 | 17 | package org.apache.calcite.adapter.enumerable; |
18 | 18 |
|
| 19 | +import java.util.function.Predicate; |
| 20 | + |
| 21 | +import org.apache.calcite.adapter.jdbc.JdbcConvention; |
19 | 22 | import org.apache.calcite.plan.RelOptCluster; |
20 | 23 | import org.apache.calcite.plan.RelOptRuleCall; |
21 | 24 | import org.apache.calcite.plan.RelRule; |
| 25 | +import org.apache.calcite.plan.RelTrait; |
22 | 26 | import org.apache.calcite.rel.RelNode; |
23 | 27 | import org.apache.calcite.rel.core.CorrelationId; |
24 | 28 | import org.apache.calcite.rel.core.Join; |
@@ -80,10 +84,45 @@ public EnumerableBatchNestedLoopJoinRule(RelBuilderFactory relBuilderFactory, |
80 | 84 | @Override public boolean matches(RelOptRuleCall call) { |
81 | 85 | Join join = call.rel(0); |
82 | 86 | JoinRelType joinType = join.getJoinType(); |
83 | | - return joinType == JoinRelType.INNER |
| 87 | + return (joinType == JoinRelType.INNER |
84 | 88 | || joinType == JoinRelType.LEFT |
85 | 89 | || joinType == JoinRelType.ANTI |
86 | | - || joinType == JoinRelType.SEMI; |
| 90 | + || joinType == JoinRelType.SEMI ) |
| 91 | + && !allLeafsMatch(join, new HasSingleJdbcSource()); |
| 92 | + } |
| 93 | + |
| 94 | + private static class HasSingleJdbcSource implements Predicate<RelNode> { |
| 95 | + private JdbcConvention convention = null; |
| 96 | + @Override |
| 97 | + public boolean test(RelNode node) { |
| 98 | + for (RelTrait trait : node.getTraitSet()) { |
| 99 | + if (trait instanceof JdbcConvention) { |
| 100 | + JdbcConvention otherConvention = (JdbcConvention) trait; |
| 101 | + // The first leaf in the tree sets the convention |
| 102 | + if (convention == null) { |
| 103 | + convention = otherConvention; |
| 104 | + return true; |
| 105 | + } |
| 106 | + // All other leafs must match the stored convention |
| 107 | + return convention == otherConvention; |
| 108 | + } |
| 109 | + } |
| 110 | + return false; |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + private boolean allLeafsMatch(RelNode node, HasSingleJdbcSource predicate) { |
| 115 | + List<RelNode> inputs = node.getInputs(); |
| 116 | + if ( inputs.isEmpty()) { |
| 117 | + return predicate.test(node); |
| 118 | + } else { |
| 119 | + for ( RelNode input : inputs) { |
| 120 | + if ( !allLeafsMatch(input.stripped(), predicate)) { |
| 121 | + return false; |
| 122 | + } |
| 123 | + } |
| 124 | + } |
| 125 | + return true; |
87 | 126 | } |
88 | 127 |
|
89 | 128 | @Override public void onMatch(RelOptRuleCall call) { |
|
0 commit comments