18 package org.apache.calcite.rel.rules;
20 import static org.apache.calcite.plan.RelOptUtil.conjunctions;
22 import com.google.common.collect.ImmutableList;
23 import com.google.common.collect.Sets;
26 import org.apache.calcite.plan.RelOptRuleCall;
27 import org.apache.calcite.plan.RelOptUtil;
28 import org.apache.calcite.rel.RelNode;
29 import org.apache.calcite.rel.core.Filter;
30 import org.apache.calcite.rel.core.Join;
31 import org.apache.calcite.rel.core.JoinRelType;
32 import org.apache.calcite.rel.type.RelDataType;
33 import org.apache.calcite.rex.RexBuilder;
34 import org.apache.calcite.rex.RexNode;
35 import org.apache.calcite.rex.RexUtil;
36 import org.apache.calcite.tools.RelBuilder;
37 import org.apache.calcite.tools.RelBuilderFactory;
38 import org.apache.calcite.util.ImmutableBitSet;
40 import java.util.ArrayList;
41 import java.util.List;
45 RelBuilderFactory relBuilderFactory,
48 super(smart, relBuilderFactory, predicate);
56 public void onMatch(RelOptRuleCall call) {
57 Filter filter = call.rel(0);
58 Join
join = call.rel(1);
72 List<RexNode> filtersToBePushedDown =
new ArrayList<>();
73 List<RexNode> filtersAboveRemained =
74 filter != null ? conjunctions(filter.getCondition()) :
new ArrayList<>();
76 for (RexNode each_filter : conjunctions(filter.getCondition())) {
77 ImmutableBitSet filterRefs = RelOptUtil.InputFinder.bits(each_filter);
78 if (filterRefs.cardinality() == 1) {
79 Integer ref_index = filterRefs.toList().
get(0);
81 if (ref_index >= cand.input_start && ref_index < cand.input_next) {
82 filtersToBePushedDown.add(each_filter);
83 filtersAboveRemained.remove(each_filter);
89 final List<RexNode> joinFilters = RelOptUtil.conjunctions(join.getCondition());
90 final List<RexNode> origJoinFilters = ImmutableList.copyOf(joinFilters);
96 if (filter == null && joinFilters.isEmpty()) {
100 final List<RexNode> aboveFilters = filtersAboveRemained;
101 final ImmutableList<RexNode> origAboveFilters = ImmutableList.copyOf(aboveFilters);
104 JoinRelType joinType = join.getJoinType();
105 if (
smart && !origAboveFilters.isEmpty() && join.getJoinType() != JoinRelType.INNER) {
106 joinType = RelOptUtil.simplifyJoin(
join, origAboveFilters, joinType);
109 final List<RexNode> leftFilters =
new ArrayList<>();
110 final List<RexNode> rightFilters =
new ArrayList<>();
121 boolean filterPushed =
false;
122 if (RelOptUtil.classifyFilters(join,
123 filtersToBePushedDown,
125 !(join.analyzeCondition().nonEquiConditions.isEmpty()),
126 !joinType.generatesNullsOnLeft(),
127 !joinType.generatesNullsOnRight(),
134 validateJoinFilters(aboveFilters, joinFilters, join, joinType);
137 if (leftFilters.isEmpty() && rightFilters.isEmpty()
138 && joinFilters.size() == origJoinFilters.size()) {
139 if (Sets.newHashSet(joinFilters).equals(Sets.newHashSet(origJoinFilters))) {
140 filterPushed =
false;
147 if (RelOptUtil.classifyFilters(join,
151 !joinType.generatesNullsOnLeft(),
152 !joinType.generatesNullsOnRight(),
161 if ((!filterPushed && joinType == join.getJoinType())
162 || (joinFilters.isEmpty() && leftFilters.isEmpty()
163 && rightFilters.isEmpty())) {
169 final RexBuilder rexBuilder = join.getCluster().getRexBuilder();
170 final RelBuilder relBuilder = call.builder();
171 final RelNode leftRel = relBuilder.push(join.getLeft()).filter(leftFilters).build();
172 final RelNode rightRel =
173 relBuilder.push(join.getRight()).filter(rightFilters).build();
177 final ImmutableList<RelDataType> fieldTypes =
178 ImmutableList.<RelDataType>builder()
179 .addAll(RelOptUtil.getFieldTypeList(leftRel.getRowType()))
180 .addAll(RelOptUtil.getFieldTypeList(rightRel.getRowType()))
182 final RexNode joinFilter = RexUtil.composeConjunction(
183 rexBuilder, RexUtil.fixUp(rexBuilder, joinFilters, fieldTypes),
false);
187 if (joinFilter.isAlwaysTrue() && leftFilters.isEmpty() && rightFilters.isEmpty()
188 && joinType == join.getJoinType()) {
192 RelNode newJoinRel = join.copy(join.getTraitSet(),
197 join.isSemiJoinDone());
198 call.getPlanner().onCopy(join, newJoinRel);
199 if (!leftFilters.isEmpty()) {
200 call.getPlanner().onCopy(filter, leftRel);
202 if (!rightFilters.isEmpty()) {
203 call.getPlanner().onCopy(filter, rightRel);
206 relBuilder.push(newJoinRel);
210 relBuilder.convert(join.getRowType(),
false);
213 relBuilder.filter(RexUtil.fixUp(rexBuilder,
215 RelOptUtil.getFieldTypeList(relBuilder.peek().getRowType())));
217 call.transformTo(relBuilder.build());
DynamicFilterJoinRule(boolean smart, RelBuilderFactory relBuilderFactory, Predicate predicate, final List< HeavyDBParserOptions.FilterPushDownInfo > filter_push_down_info)
final List< HeavyDBParserOptions.FilterPushDownInfo > filter_push_down_info
void performSelectivePushDown(RelOptRuleCall call, Filter filter, Join join)
void onMatch(RelOptRuleCall call)