org.eigenbase.rel.rules
Class ConvertMultiJoinRule

java.lang.Object
  extended by org.eigenbase.relopt.RelOptRule
      extended by org.eigenbase.rel.rules.ConvertMultiJoinRule

public class ConvertMultiJoinRule
extends RelOptRule

Rule to flatten a tree of JoinRels into a single MultiJoinRel with N inputs. An input is not flattened if the input is a null generating input in an outer join, i.e., either input in a full outer join, the right hand side of a left outer join, or the left hand side of a right outer join.

Join conditions are also pulled up from the inputs into the topmost MultiJoinRel, unless the input corresponds to a null generating input in an outer join,

Outer join information is also stored in the MultiJoinRel. A boolean flag indicates if the join is a full outer join, and in the case of left and right outer joins, the join type and outer join conditions are stored in arrays in the MultiJoinRel. This outer join information is associated with the null generating input in the outer join. So, in the case of a a left outer join between A and B, the information is associated with B, not A.

Here are examples of the MultiJoinRels constructed after this rule has been applied on following join trees.

 A JOIN B -> MJ(A, B)
 A JOIN B JOIN C -> MJ(A, B, C)
 A LEFTOUTER B -> MJ(A, B), left outer join on input#1
 A RIGHTOUTER B -> MJ(A, B), right outer join on input#0
 A FULLOUTER B -> MJ[full](A, B)
 A LEFTOUTER (B JOIN C) -> MJ(A, MJ(B, C))), left outer join on input#1 in
 the outermost MultiJoinRel
 (A JOIN B) LEFTOUTER C -> MJ(A, B, C), left outer join on input#2
 A LEFTOUTER (B FULLOUTER C) -> MJ(A, MJ[full](B, C)), left outer join on
      input#1 in the outermost MultiJoinRel
 (A LEFTOUTER B) FULLOUTER (C RIGHTOUTER D) ->
      MJ[full](MJ(A, B), MJ(C, D)), left outer join on input #1 in the first
      inner MultiJoinRel and right outer join on input#0 in the second inner
      MultiJoinRel
 

Version:
$Id: //open/dev/farrago/src/org/eigenbase/rel/rules/ConvertMultiJoinRule.java#17 $
Author:
Zelaine Fong

Nested Class Summary
private  class ConvertMultiJoinRule.InputReferenceCounter
          Visitor that keeps a reference count of the inputs used by an expression.
 
Field Summary
static ConvertMultiJoinRule instance
           
 
Fields inherited from class org.eigenbase.relopt.RelOptRule
ANY, description, operands
 
Constructor Summary
private ConvertMultiJoinRule()
          Creates a ConvertMultiJoinRule.
 
Method Summary
private  void addOnJoinFieldRefCounts(RelNode[] multiJoinInputs, int nTotalFields, RexNode joinCondition, List<int[]> origJoinFieldRefCounts, Map<Integer,int[]> newJoinFieldRefCountsMap)
          Adds on to the existing join condition reference counts the references from the new join condition.
private  boolean canCombine(RelNode input, boolean nullGenerating)
           
private  RelNode[] combineInputs(JoinRel join, RelNode left, RelNode right, List<BitSet> projFieldsList, List<int[]> joinFieldRefCountsList)
          Combines the inputs into a JoinRel into an array of inputs.
private  RexNode combineJoinFilters(JoinRel joinRel, RelNode left, RelNode right)
          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
private  RexNode[] combineOuterJoins(JoinRel joinRel, RelNode[] combinedInputs, RelNode left, RelNode right, RexNode[] combinedConds, JoinRelType[] joinTypes)
          Combines the outer join conditions and join types from the left and right join inputs.
private  RexNode combinePostJoinFilters(JoinRel joinRel, RelNode left, RelNode right)
          Combines the post-join filters from the left and right inputs (if they are MultiJoinRels) into a single AND'd filter.
private  void copyOuterJoinInfo(MultiJoinRel multiJoinRel, RexNode[] destConds, JoinRelType[] destJoinTypes, int destPos, int adjustmentAmount, RelDataTypeField[] srcFields, RelDataTypeField[] destFields)
          Copies outer join data from a source MultiJoinRel to a new set of arrays.
 void onMatch(RelOptRuleCall call)
          Receives notification about a rule match.
private  RexNode shiftRightFilter(JoinRel joinRel, RelNode left, MultiJoinRel right, RexNode rightFilter)
          Shifts a filter originating from the right child of the JoinRel to the right, to reflect the filter now being applied on the resulting MultiJoinRel.
 
Methods inherited from class org.eigenbase.relopt.RelOptRule
convert, equals, equals, getOperand, getOperands, getOutConvention, getOutTrait, hashCode, matches, mergeTraitsAndConvert, mergeTraitsAndConvert, toString
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

instance

public static final ConvertMultiJoinRule instance
Constructor Detail

ConvertMultiJoinRule

private ConvertMultiJoinRule()
Creates a ConvertMultiJoinRule.

Method Detail

onMatch

public void onMatch(RelOptRuleCall call)
Description copied from class: RelOptRule
Receives notification about a rule match. At the time that this method is called, call.rels holds the set of relational expressions which match the operands to the rule; call.rels[0] is the root expression.

Typically a rule would check that the nodes are valid matches, creates a new expression, then calls back RelOptRuleCall.transformTo(org.eigenbase.rel.RelNode) to register the expression.

Specified by:
onMatch in class RelOptRule
Parameters:
call - Rule call
See Also:
RelOptRule.matches(RelOptRuleCall)

combineInputs

private RelNode[] combineInputs(JoinRel join,
                                RelNode left,
                                RelNode right,
                                List<BitSet> projFieldsList,
                                List<int[]> joinFieldRefCountsList)
Combines the inputs into a JoinRel into an array of inputs.

Parameters:
join - original join
left - left input into join
right - right input into join
projFieldsList - returns a list of the new combined projection fields
joinFieldRefCountsList - returns a list of the new combined join field reference counts
Returns:
combined left and right inputs in an array

combineOuterJoins

private RexNode[] combineOuterJoins(JoinRel joinRel,
                                    RelNode[] combinedInputs,
                                    RelNode left,
                                    RelNode right,
                                    RexNode[] combinedConds,
                                    JoinRelType[] joinTypes)
Combines the outer join conditions and join types from the left and right join inputs. If the join itself is either a left or right outer join, then the join condition corresponding to the join is also set in the position corresponding to the null-generating input into the join. The join type is also set.

Parameters:
joinRel - join rel
combinedInputs - the combined inputs to the join
left - left child of the joinrel
right - right child of the joinrel
combinedConds - the array containing the combined join conditions
joinTypes - the array containing the combined join types
Returns:
combined join filters AND'd together

copyOuterJoinInfo

private void copyOuterJoinInfo(MultiJoinRel multiJoinRel,
                               RexNode[] destConds,
                               JoinRelType[] destJoinTypes,
                               int destPos,
                               int adjustmentAmount,
                               RelDataTypeField[] srcFields,
                               RelDataTypeField[] destFields)
Copies outer join data from a source MultiJoinRel to a new set of arrays. Also adjusts the conditions to reflect the new position of an input if that input ends up being shifted to the right.

Parameters:
multiJoinRel - the source MultiJoinRel
destConds - the array where the join conditions will be copied
destJoinTypes - the array where the join types will be copied
destPos - starting position in the array where the copying starts
adjustmentAmount - if > 0, the amount the RexInputRefs in the join conditions need to be adjusted by
srcFields - the source fields that the original join conditions are referencing
destFields - the destination fields that the new join conditions will be referencing

combineJoinFilters

private RexNode combineJoinFilters(JoinRel joinRel,
                                   RelNode left,
                                   RelNode right)
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

Parameters:
joinRel - join rel
left - left child of the joinrel
right - right child of the joinrel
Returns:
combined join filters AND'd together

canCombine

private boolean canCombine(RelNode input,
                           boolean nullGenerating)
Parameters:
input - input into a join
nullGenerating - true if the input is null generating
Returns:
true if the input can be combined into a parent MultiJoinRel

shiftRightFilter

private RexNode shiftRightFilter(JoinRel joinRel,
                                 RelNode left,
                                 MultiJoinRel right,
                                 RexNode rightFilter)
Shifts a filter originating from the right child of the JoinRel to the right, to reflect the filter now being applied on the resulting MultiJoinRel.

Parameters:
joinRel - the original JoinRel
left - the left child of the JoinRel
right - the right child of the JoinRel
rightFilter - the filter originating from the right child
Returns:
the adjusted right filter

addOnJoinFieldRefCounts

private void addOnJoinFieldRefCounts(RelNode[] multiJoinInputs,
                                     int nTotalFields,
                                     RexNode joinCondition,
                                     List<int[]> origJoinFieldRefCounts,
                                     Map<Integer,int[]> newJoinFieldRefCountsMap)
Adds on to the existing join condition reference counts the references from the new join condition.

Parameters:
multiJoinInputs - inputs into the new MultiJoinRel
nTotalFields - total number of fields in the MultiJoinRel
joinCondition - the new join condition
origJoinFieldRefCounts - existing join condition reference counts
newJoinFieldRefCountsMap - map containing the new join condition reference counts, indexed by input #

combinePostJoinFilters

private RexNode combinePostJoinFilters(JoinRel joinRel,
                                       RelNode left,
                                       RelNode right)
Combines the post-join filters from the left and right inputs (if they are MultiJoinRels) into a single AND'd filter.

Parameters:
joinRel - the original JoinRel
left - left child of the JoinRel
right - right child of the JoinRel
Returns:
combined post-join filters AND'd together