Class JoinToMultiJoinRule


  • public class JoinToMultiJoinRule
    extends RelOptRule
    Planner rule to flatten a tree of LogicalJoins into a single MultiJoin 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 MultiJoin, unless the input corresponds to a null generating input in an outer join,

    Outer join information is also stored in the MultiJoin. 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 MultiJoin. 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 MultiJoins 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 LEFT JOIN B → MJ(A, B), left outer join on input#1
    • A RIGHT JOIN B → MJ(A, B), right outer join on input#0
    • A FULL JOIN B → MJ[full](A, B)
    • A LEFT JOIN (B JOIN C) → MJ(A, MJ(B, C))), left outer join on input#1 in the outermost MultiJoin
    • (A JOIN B) LEFT JOIN C → MJ(A, B, C), left outer join on input#2
    • (A LEFT JOIN B) JOIN C → MJ(MJ(A, B), C), left outer join on input#1 of the inner MultiJoin TODO
    • A LEFT JOIN (B FULL JOIN C) → MJ(A, MJ[full](B, C)), left outer join on input#1 in the outermost MultiJoin
    • (A LEFT JOIN B) FULL JOIN (C RIGHT JOIN D) → MJ[full](MJ(A, B), MJ(C, D)), left outer join on input #1 in the first inner MultiJoin and right outer join on input#0 in the second inner MultiJoin

    The constructor is parameterized to allow any sub-class of Join, not just LogicalJoin.

    See Also:
    FilterMultiJoinMergeRule, ProjectMultiJoinMergeRule
    • Constructor Detail

      • JoinToMultiJoinRule

        @Deprecated
        public JoinToMultiJoinRule​(java.lang.Class<? extends Join> clazz)
        Deprecated.
      • JoinToMultiJoinRule

        public JoinToMultiJoinRule​(java.lang.Class<? extends Join> clazz,
                                   RelBuilderFactory relBuilderFactory)
        Creates a JoinToMultiJoinRule.
    • Method Detail

      • matches

        public boolean matches​(RelOptRuleCall call)
        Description copied from class: RelOptRule
        Returns whether this rule could possibly match the given operands.

        This method is an opportunity to apply side-conditions to a rule. The RelOptPlanner calls this method after matching all operands of the rule, and before calling RelOptRule.onMatch(RelOptRuleCall).

        In implementations of RelOptPlanner which may queue up a matched RelOptRuleCall for a long time before calling RelOptRule.onMatch(RelOptRuleCall), this method is beneficial because it allows the planner to discard rules earlier in the process.

        The default implementation of this method returns true. It is acceptable for any implementation of this method to give a false positives, that is, to say that the rule matches the operands but have RelOptRule.onMatch(RelOptRuleCall) subsequently not generate any successors.

        The following script is useful to identify rules which commonly produce no successors. You should override this method for these rules:

        awk '
         /Apply rule/ {rule=$4; ruleCount[rule]++;}
         /generated 0 successors/ {ruleMiss[rule]++;}
         END {
           printf "%-30s %s %s\n", "Rule", "Fire", "Miss";
           for (i in ruleCount) {
             printf "%-30s %5d %5d\n", i, ruleCount[i], ruleMiss[i];
           }
         } ' FarragoTrace.log
        Overrides:
        matches in class RelOptRule
        Parameters:
        call - Rule call which has been determined to match all operands of this rule
        Returns:
        whether this RelOptRule matches a given RelOptRuleCall
      • combineInputs

        private java.util.List<RelNode> combineInputs​(Join join,
                                                      RelNode left,
                                                      RelNode right,
                                                      java.util.List<ImmutableBitSet> projFieldsList,
                                                      java.util.List<int[]> joinFieldRefCountsList)
        Combines the inputs into a LogicalJoin 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 void combineOuterJoins​(Join joinRel,
                                       java.util.List<RelNode> combinedInputs,
                                       RelNode left,
                                       RelNode right,
                                       java.util.List<Pair<JoinRelType,​RexNode>> joinSpecs)
        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
        joinSpecs - the list where the join types and conditions will be copied
      • copyOuterJoinInfo

        private void copyOuterJoinInfo​(MultiJoin multiJoin,
                                       java.util.List<Pair<JoinRelType,​RexNode>> destJoinSpecs,
                                       int adjustmentAmount,
                                       java.util.List<RelDataTypeField> srcFields,
                                       java.util.List<RelDataTypeField> destFields)
        Copies outer join data from a source MultiJoin 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:
        multiJoin - the source MultiJoin
        destJoinSpecs - the list where the join types and conditions will be copied
        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
      • combineJoinFilters

        private java.util.List<RexNode> combineJoinFilters​(Join 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 join
        right - right child of the join
        Returns:
        combined join filters AND-ed together
      • canCombine

        private boolean canCombine​(RelNode input,
                                   boolean nullGenerating)
        Returns whether an input can be merged into a given relational expression without changing semantics.
        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 MultiJoin
      • shiftRightFilter

        private RexNode shiftRightFilter​(Join joinRel,
                                         RelNode left,
                                         MultiJoin right,
                                         RexNode rightFilter)
        Shifts a filter originating from the right child of the LogicalJoin to the right, to reflect the filter now being applied on the resulting MultiJoin.
        Parameters:
        joinRel - the original LogicalJoin
        left - the left child of the LogicalJoin
        right - the right child of the LogicalJoin
        rightFilter - the filter originating from the right child
        Returns:
        the adjusted right filter
      • addOnJoinFieldRefCounts

        private com.google.common.collect.ImmutableMap<java.lang.Integer,​ImmutableIntList> addOnJoinFieldRefCounts​(java.util.List<RelNode> multiJoinInputs,
                                                                                                                         int nTotalFields,
                                                                                                                         RexNode joinCondition,
                                                                                                                         java.util.List<int[]> origJoinFieldRefCounts)
        Adds on to the existing join condition reference counts the references from the new join condition.
        Parameters:
        multiJoinInputs - inputs into the new MultiJoin
        nTotalFields - total number of fields in the MultiJoin
        joinCondition - the new join condition
        origJoinFieldRefCounts - existing join condition reference counts
        Returns:
        Map containing the new join condition
      • combinePostJoinFilters

        private java.util.List<RexNode> combinePostJoinFilters​(Join 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 LogicalJoin
        left - left child of the LogicalJoin
        right - right child of the LogicalJoin
        Returns:
        combined post-join filters AND'd together