maytasm commented on a change in pull request #9773: URL: https://github.com/apache/druid/pull/9773#discussion_r421920290
########## File path: sql/src/main/java/org/apache/druid/sql/calcite/rule/FilterJoinExcludePushToChildRule.java ########## @@ -0,0 +1,277 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.druid.sql.calcite.rule; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Sets; +import org.apache.calcite.adapter.enumerable.EnumerableConvention; +import org.apache.calcite.plan.RelOptRule; +import org.apache.calcite.plan.RelOptRuleCall; +import org.apache.calcite.plan.RelOptRuleOperand; +import org.apache.calcite.plan.RelOptUtil; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.core.Filter; +import org.apache.calcite.rel.core.Join; +import org.apache.calcite.rel.core.JoinRelType; +import org.apache.calcite.rel.core.RelFactories; +import org.apache.calcite.rel.rules.FilterJoinRule; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rex.RexBuilder; +import org.apache.calcite.rex.RexCall; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexUtil; +import org.apache.calcite.tools.RelBuilder; +import org.apache.calcite.tools.RelBuilderFactory; + +import java.util.ArrayList; +import java.util.List; + +import static org.apache.calcite.plan.RelOptUtil.conjunctions; + +public abstract class FilterJoinExcludePushToChildRule extends FilterJoinRule +{ + /** Copied from {@link FilterJoinRule#NOT_ENUMERABLE} */ + private static final Predicate NOT_ENUMERABLE = (join, joinType, exp) -> + join.getConvention() != EnumerableConvention.INSTANCE; + + /** + * Rule that pushes predicates from a Filter into the Join below them. + * Similar to {@link FilterJoinRule#FILTER_ON_JOIN} but does not push predicate to the child + */ + public static final FilterJoinRule FILTER_ON_JOIN_EXCLUDE_PUSH_TO_CHILD = + new FilterIntoJoinExcludePushToChildRule(RelFactories.LOGICAL_BUILDER, NOT_ENUMERABLE); + + FilterJoinExcludePushToChildRule(RelOptRuleOperand operand, + String id, + boolean smart, + RelBuilderFactory relBuilderFactory, + Predicate predicate) { + super(operand, id, smart, relBuilderFactory, predicate); + } + + /** + * Rule that tries to push filter expressions into a join + * condition. Exlucde pushing into the inputs (child) of the join. + */ + public static class FilterIntoJoinExcludePushToChildRule extends FilterJoinExcludePushToChildRule + { + public FilterIntoJoinExcludePushToChildRule(RelBuilderFactory relBuilderFactory, Predicate predicate) { + super( + operand(Filter.class, + operand(Join.class, RelOptRule.any())), + "FilterJoinExcludePushToChildRule:filter", true, relBuilderFactory, + predicate); + } + + @Override + public void onMatch(RelOptRuleCall call) { + Filter filter = call.rel(0); + Join join = call.rel(1); + perform(call, filter, join); + } + } + + /** + * Copied from {@link FilterJoinRule#perform} + * The difference is that this method will not not push filters to the children in classifyFilters + */ + @Override + protected void perform(RelOptRuleCall call, Filter filter, + Join join) { + final List<RexNode> joinFilters = + RelOptUtil.conjunctions(join.getCondition()); + final List<RexNode> origJoinFilters = ImmutableList.copyOf(joinFilters); + // If there is only the joinRel, + // make sure it does not match a cartesian product joinRel + // (with "true" condition), otherwise this rule will be applied + // again on the new cartesian product joinRel. + if (filter == null && joinFilters.isEmpty()) { + return; + } + + final List<RexNode> aboveFilters = + filter != null + ? getConjunctions(filter) + : new ArrayList<>(); + final ImmutableList<RexNode> origAboveFilters = + ImmutableList.copyOf(aboveFilters); + + // Simplify Outer Joins + JoinRelType joinType = join.getJoinType(); + if (!origAboveFilters.isEmpty() && join.getJoinType() != JoinRelType.INNER) { + joinType = RelOptUtil.simplifyJoin(join, origAboveFilters, joinType); + } + + final List<RexNode> leftFilters = new ArrayList<>(); Review comment: These left right thing is not needed. But I copied this whole code from Calcite and made minimum change (which is just the classifyFilters method). Hence, keeping these variables here as I don't want to refactor Calcite stuff more than needed. ---------------------------------------------------------------- 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. For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
