Beispiel #1
0
  /**
   * Combines the inputs into a JoinRel into an array of inputs.
   *
   * @param join original join
   * @param left left input into join
   * @param right right input into join
   * @param projFieldsList returns a list of the new combined projection fields
   * @param joinFieldRefCountsList returns a list of the new combined join field reference counts
   * @return combined left and right inputs in an array
   */
  private RelNode[] combineInputs(
      JoinRel join,
      RelNode left,
      RelNode right,
      List<BitSet> projFieldsList,
      List<int[]> joinFieldRefCountsList) {
    // leave the null generating sides of an outer join intact; don't
    // pull up those children inputs into the array we're constructing
    int nInputs;
    int nInputsOnLeft;
    MultiJoinRel leftMultiJoin = null;
    JoinRelType joinType = join.getJoinType();
    boolean combineLeft = canCombine(left, joinType.generatesNullsOnLeft());
    if (combineLeft) {
      leftMultiJoin = (MultiJoinRel) left;
      nInputs = left.getInputs().length;
      nInputsOnLeft = nInputs;
    } else {
      nInputs = 1;
      nInputsOnLeft = 1;
    }
    MultiJoinRel rightMultiJoin = null;
    boolean combineRight = canCombine(right, joinType.generatesNullsOnRight());
    if (combineRight) {
      rightMultiJoin = (MultiJoinRel) right;
      nInputs += right.getInputs().length;
    } else {
      nInputs += 1;
    }

    RelNode[] newInputs = new RelNode[nInputs];
    int i = 0;
    if (combineLeft) {
      for (; i < left.getInputs().length; i++) {
        newInputs[i] = leftMultiJoin.getInput(i);
        projFieldsList.add(((MultiJoinRel) left).getProjFields()[i]);
        joinFieldRefCountsList.add(((MultiJoinRel) left).getJoinFieldRefCountsMap().get(i));
      }
    } else {
      newInputs[0] = left;
      i = 1;
      projFieldsList.add(null);
      joinFieldRefCountsList.add(new int[left.getRowType().getFieldCount()]);
    }
    if (combineRight) {
      for (; i < nInputs; i++) {
        newInputs[i] = rightMultiJoin.getInput(i - nInputsOnLeft);
        projFieldsList.add(((MultiJoinRel) right).getProjFields()[i - nInputsOnLeft]);
        joinFieldRefCountsList.add(
            ((MultiJoinRel) right).getJoinFieldRefCountsMap().get(i - nInputsOnLeft));
      }
    } else {
      newInputs[i] = right;
      projFieldsList.add(null);
      joinFieldRefCountsList.add(new int[right.getRowType().getFieldCount()]);
    }

    return newInputs;
  }
Beispiel #2
0
  /**
   * 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.
   *
   * @param joinRel join rel
   * @param combinedInputs the combined inputs to the join
   * @param left left child of the joinrel
   * @param right right child of the joinrel
   * @param combinedConds the array containing the combined join conditions
   * @param joinTypes the array containing the combined join types
   * @return combined join filters AND'd together
   */
  private RexNode[] combineOuterJoins(
      JoinRel joinRel,
      RelNode[] combinedInputs,
      RelNode left,
      RelNode right,
      RexNode[] combinedConds,
      JoinRelType[] joinTypes) {
    JoinRelType joinType = joinRel.getJoinType();
    int nCombinedInputs = combinedInputs.length;
    boolean leftCombined = canCombine(left, joinType.generatesNullsOnLeft());
    boolean rightCombined = canCombine(right, joinType.generatesNullsOnRight());
    if (joinType == JoinRelType.LEFT) {
      if (leftCombined) {
        copyOuterJoinInfo((MultiJoinRel) left, combinedConds, joinTypes, 0, 0, null, null);
      } else {
        joinTypes[0] = JoinRelType.INNER;
      }
      combinedConds[nCombinedInputs - 1] = joinRel.getCondition();
      joinTypes[nCombinedInputs - 1] = joinType;
    } else if (joinType == JoinRelType.RIGHT) {
      if (rightCombined) {
        copyOuterJoinInfo(
            (MultiJoinRel) right,
            combinedConds,
            joinTypes,
            1,
            left.getRowType().getFieldCount(),
            right.getRowType().getFields(),
            joinRel.getRowType().getFields());
      } else {
        joinTypes[nCombinedInputs - 1] = JoinRelType.INNER;
      }
      combinedConds[0] = joinRel.getCondition();
      joinTypes[0] = joinType;
    } else {
      int nInputsLeft;
      if (leftCombined) {
        nInputsLeft = left.getInputs().length;
        copyOuterJoinInfo((MultiJoinRel) left, combinedConds, joinTypes, 0, 0, null, null);
      } else {
        nInputsLeft = 1;
        joinTypes[0] = JoinRelType.INNER;
      }
      if (rightCombined) {
        copyOuterJoinInfo(
            (MultiJoinRel) right,
            combinedConds,
            joinTypes,
            nInputsLeft,
            left.getRowType().getFieldCount(),
            right.getRowType().getFields(),
            joinRel.getRowType().getFields());
      } else {
        joinTypes[nInputsLeft] = JoinRelType.INNER;
      }
    }

    return combinedConds;
  }
Beispiel #3
0
 /**
  * Returns the index of the first field in <code>rel</code> which comes from its <code>ordinal
  * </code>th input.
  *
  * <p>For example, if rel joins T0(A,B,C) to T1(D,E), then countFields(0,rel) yields 0, and
  * countFields(1,rel) yields 3.
  */
 private int computeFieldOffset(RelNode rel, int ordinal) {
   if (ordinal == 0) {
     // short-circuit for the common case
     return 0;
   }
   int fieldOffset = 0;
   final List<RelNode> inputs = rel.getInputs();
   for (int i = 0; i < ordinal; i++) {
     RelNode input = inputs.get(i);
     fieldOffset += input.getRowType().getFieldList().size();
   }
   return fieldOffset;
 }
Beispiel #4
0
 /**
  * Returns the variable which, in the generated program, will hold the current row of a given
  * relational expression. This method is only applicable if the relational expression is the
  * current one or an input; if it is an ancestor, there is no current value, and this method
  * returns null.
  */
 public Variable findInputVariable(RelNode rel) {
   while (true) {
     JavaFrame frame = (JavaFrame) mapRel2Frame.get(rel);
     if ((frame != null) && frame.hasVariable()) {
       return frame.getVariable();
     }
     List<RelNode> inputs = rel.getInputs();
     if (inputs.size() == 1) {
       rel = inputs.get(0);
     } else {
       return null;
     }
   }
 }
Beispiel #5
0
    private JavaFrame findFrame() {
      RelNode previous = rel;
      while (true) {
        JavaFrame frame = (JavaFrame) mapRel2Frame.get(previous);
        if (frame.bind != null) {
          tracer.log(
              Level.FINE,
              "Bind " + rel.toString() + " to " + previous.toString() + "(" + frame.bind + ")");
          return frame;
        }

        // go deeper
        List<RelNode> inputs = previous.getInputs();
        assert (inputs.size() == 1) : "input is not bound";
        previous = inputs.get(0);
      }
    }