/** * Combines the join filters from the left and right inputs (if they are MultiJoinRels) with the * join filter in the joinrel into a single AND'd join filter, unless the inputs correspond to * null generating inputs in an outer join * * @param joinRel join rel * @param left left child of the joinrel * @param right right child of the joinrel * @return combined join filters AND'd together */ private RexNode combineJoinFilters(JoinRel joinRel, RelNode left, RelNode right) { RexBuilder rexBuilder = joinRel.getCluster().getRexBuilder(); JoinRelType joinType = joinRel.getJoinType(); // first need to adjust the RexInputs of the right child, since // those need to shift over to the right RexNode rightFilter = null; if (canCombine(right, joinType.generatesNullsOnRight())) { MultiJoinRel multiJoin = (MultiJoinRel) right; rightFilter = shiftRightFilter(joinRel, left, multiJoin, multiJoin.getJoinFilter()); } // AND the join condition if this isn't a left or right outer join; // in those cases, the outer join condition is already tracked // separately RexNode newFilter = null; if ((joinType != JoinRelType.LEFT) && (joinType != JoinRelType.RIGHT)) { newFilter = joinRel.getCondition(); } if (canCombine(left, joinType.generatesNullsOnLeft())) { RexNode leftFilter = ((MultiJoinRel) left).getJoinFilter(); newFilter = RelOptUtil.andJoinFilters(rexBuilder, newFilter, leftFilter); } newFilter = RelOptUtil.andJoinFilters(rexBuilder, newFilter, rightFilter); return newFilter; }
// implement RelOptRule public void onMatch(RelOptRuleCall call) { FilterRel filterRel = call.rel(0); MultiJoinRel multiJoinRel = call.rel(1); MultiJoinRel newMultiJoinRel = new MultiJoinRel( multiJoinRel.getCluster(), multiJoinRel.getInputs(), multiJoinRel.getJoinFilter(), multiJoinRel.getRowType(), multiJoinRel.isFullOuterJoin(), multiJoinRel.getOuterJoinConditions(), multiJoinRel.getJoinTypes(), multiJoinRel.getProjFields(), multiJoinRel.getJoinFieldRefCountsMap(), filterRel.getCondition()); call.transformTo(newMultiJoinRel); }