protected void perform()

in src/query/src/main/java/org/apache/kylin/query/optrule/OlapFilterJoinRule.java [173:271]


        protected void perform() {
            List<RexNode> joinFilters = RelOptUtil.conjunctions(topJoinRel.getCondition());
            // only match cross join and not-null filter
            if (!joinFilters.isEmpty() || filterRel == null) {
                return;
            }

            List<RexNode> aboveFilters = RelOptUtil.conjunctions(filterRel.getCondition());
            // replace filters with pattern cast(col1 as ...) = col2 with col1 = col2
            // to make such filters to be able to be pushed down to join conditions
            aboveFilters = aboveFilters.stream().map(RexUtils::stripOffCastInColumnEqualPredicate)
                    .collect(Collectors.toList());

            JoinRelType joinType = topJoinRel.getJoinType();
            List<RexNode> leftFilters = new ArrayList<>();
            List<RexNode> rightFilters = new ArrayList<>();
            boolean filterPushed = pushDownFilter(aboveFilters, leftFilters, rightFilters, joinFilters);

            // if nothing actually got pushed and there is nothing leftover, then this rule is a no-op
            if ((!filterPushed && joinType == topJoinRel.getJoinType())
                    || (joinFilters.isEmpty() && leftFilters.isEmpty() && rightFilters.isEmpty())) {
                return;
            }

            // try transpose relNodes of joinRel to make as many relNodes be rewritten to inner join node as possible
            boolean isNeedProject = false;
            if (needTranspose && bottomJoin instanceof Join
                    && RelOptUtil.conjunctions(((Join) bottomJoin).getCondition()).isEmpty() && joinFilters.size() > 1
                    && !(relA instanceof Aggregate)) {
                final int originFilterSize = joinFilters.size();
                final Join originTopJoin = topJoinRel.copy(topJoinRel.getTraitSet(), topJoinRel.getInputs());

                Filter newFilter = (Filter) transposeJoinRel();
                // retry to push down new filters
                List<RexNode> newLeftFilters = Lists.newArrayList();
                List<RexNode> newRightFilters = Lists.newArrayList();
                List<RexNode> newJoinFilters = Lists.newArrayList();
                List<RexNode> newAboveFilter = RelOptUtil.conjunctions(newFilter.getCondition());
                pushDownFilter(newAboveFilter, newLeftFilters, newRightFilters, newJoinFilters);
                if (newJoinFilters.size() < originFilterSize) {
                    filterRel = newFilter;
                    leftFilters = newLeftFilters;
                    rightFilters = newRightFilters;
                    joinFilters = newJoinFilters;
                    aboveFilters = newAboveFilter;
                    isNeedProject = true;
                } else {
                    topJoinRel = originTopJoin;
                }
            }

            // create Filters on top of the children if any filters were pushed to them
            final RexBuilder rexBuilder = topJoinRel.getCluster().getRexBuilder();
            final RelNode leftRel = relBuilder.push(topJoinRel.getLeft()).filter(leftFilters).build();
            final RelNode rightRel = relBuilder.push(topJoinRel.getRight()).filter(rightFilters).build();

            // create the new join node referencing the new children and
            // containing its new join filters (if there are any)
            final ImmutableList<RelDataType> fieldTypes = ImmutableList.<RelDataType> builder()
                    .addAll(RelOptUtil.getFieldTypeList(leftRel.getRowType()))
                    .addAll(RelOptUtil.getFieldTypeList(rightRel.getRowType())).build();
            final RexNode joinFilter = RexUtil.composeConjunction(rexBuilder,
                    RexUtil.fixUp(rexBuilder, joinFilters, fieldTypes), false);

            // If nothing actually got pushed and there is nothing leftover,
            // then this rule is a no-op
            if (joinFilter.isAlwaysTrue() && leftFilters.isEmpty() && rightFilters.isEmpty()
                    && joinType == topJoinRel.getJoinType()) {
                return;
            }

            RelNode newJoinRel = topJoinRel.copy(topJoinRel.getTraitSet(), joinFilter, leftRel, rightRel, joinType,
                    topJoinRel.isSemiJoinDone());
            call.getPlanner().onCopy(topJoinRel, newJoinRel);
            if (!leftFilters.isEmpty()) {
                call.getPlanner().onCopy(filterRel, leftRel);
            }
            if (!rightFilters.isEmpty()) {
                call.getPlanner().onCopy(filterRel, rightRel);
            }

            relBuilder.push(newJoinRel);
            // Create a project on top of the join if some of the columns have become
            // NOT NULL due to the join-type getting stricter.
            relBuilder.convert(topJoinRel.getRowType(), false);
            // create a FilterRel on top of the join if needed
            relBuilder.filter(RexUtil.fixUp(rexBuilder, aboveFilters,
                    RelOptUtil.getFieldTypeList(relBuilder.peek().getRowType())));
            if (isNeedProject) {
                final int aCount = relA.getRowType().getFieldCount();
                final int bCount = relB.getRowType().getFieldCount();
                final int cCount = relC.getRowType().getFieldCount();
                final Mappings.TargetMapping originJoinFieldsToNew = Mappings.createShiftMapping(
                        aCount + bCount + cCount, 0, 0, cCount, cCount + aCount, cCount, bCount, cCount,
                        cCount + bCount, aCount);
                relBuilder.project(relBuilder.fields(originJoinFieldsToNew));
            }
            call.transformTo(relBuilder.build());
        }