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
  /**
   * Generates specific XML (sometimes called 'attribute-oriented XML'). Like this:
   *
   * <pre>
   * &lt;Join condition="EMP.DEPTNO = DEPT.DEPTNO"&gt;
   *   &lt;Project expr1="x + y" expr2="42"&gt;
   *   &lt;TableAccess table="SALES.EMPS"&gt;
   * &lt;/Join&gt;
   * </pre>
   *
   * @param rel Relational expression
   * @param terms Names of the attributes of the plan
   * @param values Values of the attributes of the plan
   */
  private void explainSpecific(RelNode rel, String[] terms, Object[] values) {
    RelNode[] inputs = rel.getInputs();
    RexNode[] children = rel.getChildExps();
    assert terms.length == (inputs.length + children.length + values.length)
        : "terms.length="
            + terms.length
            + " inputs.length="
            + inputs.length
            + " children.length="
            + children.length
            + " values.length="
            + values.length;
    String tagName = rel.getRelTypeName();
    xmlOutput.beginBeginTag(tagName);
    xmlOutput.attribute("id", rel.getId() + "");

    int j = 0;
    for (int i = 0; i < children.length; i++) {
      RexNode child = children[i];
      xmlOutput.attribute(terms[inputs.length + j++], child.toString());
    }
    for (int i = 0; i < values.length; i++) {
      Object value = values[i];
      if (value != null) {
        xmlOutput.attribute(terms[inputs.length + j++], value.toString());
      }
    }
    xmlOutput.endBeginTag(tagName);
    level++;
    for (int i = 0; i < inputs.length; i++) {
      RelNode child = inputs[i];
      child.explain(this);
    }
    level--;
  }
Beispiel #3
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;
  }
 // Ditto for getNonCumulativeCost
 public RelOptCost getCumulativeCost(RelNode rel) {
   RelOptCost cost = RelMetadataQuery.getNonCumulativeCost(rel);
   List<RelNode> inputs = rel.getInputs();
   for (RelNode input : inputs) {
     cost = cost.plus(RelMetadataQuery.getCumulativeCost(input));
   }
   return cost;
 }
Beispiel #5
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 #6
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;
     }
   }
 }
  // Catch-all rule when none of the others apply.
  public Double getPercentageOriginalRows(RelNode rel) {
    if (rel.getInputs().size() > 1) {
      // No generic formula available for multiple inputs.
      return null;
    }

    if (rel.getInputs().size() == 0) {
      // Assume no filtering happening at leaf.
      return 1.0;
    }

    RelNode child = rel.getInputs().get(0);

    Double childPercentage = RelMetadataQuery.getPercentageOriginalRows(child);
    if (childPercentage == null) {
      return null;
    }

    // Compute product of percentage filtering from this rel (assuming any
    // filtering is the effect of single-table filters) with the percentage
    // filtering performed by the child.
    Double relPercentage =
        quotientForPercentage(
            RelMetadataQuery.getRowCount(rel), RelMetadataQuery.getRowCount(child));
    if (relPercentage == null) {
      return null;
    }
    double percent = relPercentage * childPercentage;

    // this check is needed in cases where this method is called on a
    // physical rel
    if ((percent < 0.0) || (percent > 1.0)) {
      return null;
    }
    return relPercentage * childPercentage;
  }
Beispiel #8
0
  /**
   * Generates generic XML (sometimes called 'element-oriented XML'). Like this:
   *
   * <blockquote>
   *
   * <code>
   * &lt;RelNode id="1" type="Join"&gt;<br/>
   * &nbsp;&nbsp;&lt;Property name="condition"&gt;EMP.DEPTNO =
   * DEPT.DEPTNO&lt;/Property&gt;<br/>
   * &nbsp;&nbsp;&lt;Inputs&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&lt;RelNode id="2" type="Project"&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Property name="expr1"&gt;x +
   * y&lt;/Property&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Property
   * name="expr2"&gt;45&lt;/Property&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&lt;/RelNode&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&lt;RelNode id="3" type="TableAccess"&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Property
   * name="table"&gt;SALES.EMP&lt;/Property&gt;<br/>
   * &nbsp;&nbsp;&nbsp;&nbsp;&lt;/RelNode&gt;<br/>
   * &nbsp;&nbsp;&lt;/Inputs&gt;<br/>
   * &lt;/RelNode&gt;<br/>
   * </code>
   *
   * </blockquote>
   *
   * @param rel Relational expression
   * @param terms Names of the attributes of the plan
   * @param values Values of the attributes of the plan
   */
  private void explainGeneric(RelNode rel, String[] terms, Object[] values) {
    RelNode[] inputs = rel.getInputs();
    RexNode[] children = rel.getChildExps();
    assert terms.length == (inputs.length + children.length + values.length)
        : "terms.length="
            + terms.length
            + " inputs.length="
            + inputs.length
            + " children.length="
            + children.length
            + " values.length="
            + values.length;
    String relType = rel.getRelTypeName();
    xmlOutput.beginBeginTag("RelNode");
    xmlOutput.attribute("type", relType);

    // xmlOutput.attribute("id", rel.getId() + "");
    xmlOutput.endBeginTag("RelNode");

    int j = 0;
    for (int i = 0; i < children.length; i++) {
      RexNode child = children[i];
      xmlOutput.beginBeginTag("Property");
      xmlOutput.attribute("name", terms[inputs.length + j++]);
      xmlOutput.endBeginTag("Property");
      xmlOutput.cdata(child.toString());
      xmlOutput.endTag("Property");
    }
    for (int i = 0; i < values.length; i++) {
      Object value = values[i];
      if (value != null) {
        xmlOutput.beginBeginTag("Property");
        xmlOutput.attribute("name", terms[inputs.length + j++]);
        xmlOutput.endBeginTag("Property");
        xmlOutput.cdata(value.toString());
        xmlOutput.endTag("Property");
      }
    }
    xmlOutput.beginTag("Inputs", null);
    level++;
    for (int i = 0; i < inputs.length; i++) {
      RelNode child = inputs[i];
      child.explain(this);
    }
    level--;
    xmlOutput.endTag("Inputs");
    xmlOutput.endTag("RelNode");
  }
Beispiel #9
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);
      }
    }
  protected void explain_(RelNode rel, List<Pair<String, Object>> values) {
    final Map<String, Object> map = jsonBuilder.map();

    map.put("id", null); // ensure that id is the first attribute
    map.put("relOp", relJson.classToTypeName(rel.getClass()));
    for (Pair<String, Object> value : values) {
      if (value.right instanceof RelNode) {
        continue;
      }
      put(map, value.left, value.right);
    }
    // omit 'inputs: ["3"]' if "3" is the preceding rel
    final List<Object> list = explainInputs(rel.getInputs());
    if (list.size() != 1 || !list.get(0).equals(previousId)) {
      map.put("inputs", list);
    }

    final String id = Integer.toString(relIdMap.size());
    relIdMap.put(rel, id);
    map.put("id", id);

    relList.add(map);
    previousId = id;
  }