/** * 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; }
public void onMatch(RelOptRuleCall call) { assert matches(call); final JoinRel join = (JoinRel) call.rels[0]; final List<Integer> leftKeys = new ArrayList<Integer>(); final List<Integer> rightKeys = new ArrayList<Integer>(); RelNode right = join.getRight(); final RelNode left = join.getLeft(); RexNode remainingCondition = RelOptUtil.splitJoinCondition(left, right, join.getCondition(), leftKeys, rightKeys); assert leftKeys.size() == rightKeys.size(); final List<CorrelatorRel.Correlation> correlationList = new ArrayList<CorrelatorRel.Correlation>(); if (leftKeys.size() > 0) { final RelOptCluster cluster = join.getCluster(); final RexBuilder rexBuilder = cluster.getRexBuilder(); int k = 0; RexNode condition = null; for (Integer leftKey : leftKeys) { Integer rightKey = rightKeys.get(k++); final String dyn_inIdStr = cluster.getQuery().createCorrel(); final int dyn_inId = RelOptQuery.getCorrelOrdinal(dyn_inIdStr); // Create correlation to say 'each row, set variable #id // to the value of column #leftKey'. correlationList.add(new CorrelatorRel.Correlation(dyn_inId, leftKey)); condition = RelOptUtil.andJoinFilters( rexBuilder, condition, rexBuilder.makeCall( SqlStdOperatorTable.equalsOperator, rexBuilder.makeInputRef( right.getRowType().getFieldList().get(rightKey).getType(), rightKey), rexBuilder.makeCorrel( left.getRowType().getFieldList().get(leftKey).getType(), dyn_inIdStr))); } right = CalcRel.createFilter(right, condition); } RelNode newRel = new CorrelatorRel( join.getCluster(), left, right, remainingCondition, correlationList, join.getJoinType()); call.transformTo(newRel); }
/** * Combines the post-join filters from the left and right inputs (if they are MultiJoinRels) into * a single AND'd filter. * * @param joinRel the original JoinRel * @param left left child of the JoinRel * @param right right child of the JoinRel * @return combined post-join filters AND'd together */ private RexNode combinePostJoinFilters(JoinRel joinRel, RelNode left, RelNode right) { RexNode rightPostJoinFilter = null; if (right instanceof MultiJoinRel) { rightPostJoinFilter = shiftRightFilter( joinRel, left, (MultiJoinRel) right, ((MultiJoinRel) right).getPostJoinFilter()); } RexNode leftPostJoinFilter = null; if (left instanceof MultiJoinRel) { leftPostJoinFilter = ((MultiJoinRel) left).getPostJoinFilter(); } if ((leftPostJoinFilter == null) && (rightPostJoinFilter == null)) { return null; } else { return RelOptUtil.andJoinFilters( joinRel.getCluster().getRexBuilder(), leftPostJoinFilter, rightPostJoinFilter); } }