Java Code Examples for org.apache.calcite.tools.RelBuilder#intersect()

The following examples show how to use org.apache.calcite.tools.RelBuilder#intersect() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: UnionMergeRule.java    From Bats with Apache License 2.0 4 votes vote down vote up
public void onMatch(RelOptRuleCall call) {
  final SetOp topOp = call.rel(0);
  @SuppressWarnings("unchecked") final Class<? extends SetOp> setOpClass =
      (Class) operands.get(0).getMatchedClass();

  // For Union and Intersect, we want to combine the set-op that's in the
  // second input first.
  //
  // For example, we reduce
  //    Union(Union(a, b), Union(c, d))
  // to
  //    Union(Union(a, b), c, d)
  // in preference to
  //    Union(a, b, Union(c, d))
  //
  // But for Minus, we can only reduce the left input. It is not valid to
  // reduce
  //    Minus(a, Minus(b, c))
  // to
  //    Minus(a, b, c)
  //
  // Hence, that's why the rule pattern matches on generic RelNodes rather
  // than explicit sub-classes of SetOp.  By doing so, and firing this rule
  // in a bottom-up order, it allows us to only specify a single
  // pattern for this rule.
  final SetOp bottomOp;
  if (setOpClass.isInstance(call.rel(2))
      && !Minus.class.isAssignableFrom(setOpClass)) {
    bottomOp = call.rel(2);
  } else if (setOpClass.isInstance(call.rel(1))) {
    bottomOp = call.rel(1);
  } else {
    return;
  }

  // Can only combine (1) if all operators are ALL,
  // or (2) top operator is DISTINCT (i.e. not ALL).
  // In case (2), all operators become DISTINCT.
  if (topOp.all && !bottomOp.all) {
    return;
  }

  // Combine the inputs from the bottom set-op with the other inputs from
  // the top set-op.
  final RelBuilder relBuilder = call.builder();
  if (setOpClass.isInstance(call.rel(2))
      && !Minus.class.isAssignableFrom(setOpClass)) {
    relBuilder.push(topOp.getInput(0));
    relBuilder.pushAll(bottomOp.getInputs());
    // topOp.getInputs().size() may be more than 2
    for (int index = 2; index < topOp.getInputs().size(); index++) {
      relBuilder.push(topOp.getInput(index));
    }
  } else {
    relBuilder.pushAll(bottomOp.getInputs());
    relBuilder.pushAll(Util.skip(topOp.getInputs()));
  }
  int n = bottomOp.getInputs().size()
      + topOp.getInputs().size()
      - 1;
  if (topOp instanceof Union) {
    relBuilder.union(topOp.all, n);
  } else if (topOp instanceof Intersect) {
    relBuilder.intersect(topOp.all, n);
  } else if (topOp instanceof Minus) {
    relBuilder.minus(topOp.all, n);
  }
  call.transformTo(relBuilder.build());
}
 
Example 2
Source File: UnionMergeRule.java    From calcite with Apache License 2.0 4 votes vote down vote up
public void onMatch(RelOptRuleCall call) {
  final SetOp topOp = call.rel(0);
  @SuppressWarnings("unchecked") final Class<? extends SetOp> setOpClass =
      (Class) operands.get(0).getMatchedClass();

  // For Union and Intersect, we want to combine the set-op that's in the
  // second input first.
  //
  // For example, we reduce
  //    Union(Union(a, b), Union(c, d))
  // to
  //    Union(Union(a, b), c, d)
  // in preference to
  //    Union(a, b, Union(c, d))
  //
  // But for Minus, we can only reduce the left input. It is not valid to
  // reduce
  //    Minus(a, Minus(b, c))
  // to
  //    Minus(a, b, c)
  //
  // Hence, that's why the rule pattern matches on generic RelNodes rather
  // than explicit sub-classes of SetOp.  By doing so, and firing this rule
  // in a bottom-up order, it allows us to only specify a single
  // pattern for this rule.
  final SetOp bottomOp;
  if (setOpClass.isInstance(call.rel(2))
      && !Minus.class.isAssignableFrom(setOpClass)) {
    bottomOp = call.rel(2);
  } else if (setOpClass.isInstance(call.rel(1))) {
    bottomOp = call.rel(1);
  } else {
    return;
  }

  // Can only combine (1) if all operators are ALL,
  // or (2) top operator is DISTINCT (i.e. not ALL).
  // In case (2), all operators become DISTINCT.
  if (topOp.all && !bottomOp.all) {
    return;
  }

  // Combine the inputs from the bottom set-op with the other inputs from
  // the top set-op.
  final RelBuilder relBuilder = call.builder();
  if (setOpClass.isInstance(call.rel(2))
      && !Minus.class.isAssignableFrom(setOpClass)) {
    relBuilder.push(topOp.getInput(0));
    relBuilder.pushAll(bottomOp.getInputs());
    // topOp.getInputs().size() may be more than 2
    for (int index = 2; index < topOp.getInputs().size(); index++) {
      relBuilder.push(topOp.getInput(index));
    }
  } else {
    relBuilder.pushAll(bottomOp.getInputs());
    relBuilder.pushAll(Util.skip(topOp.getInputs()));
  }
  int n = bottomOp.getInputs().size()
      + topOp.getInputs().size()
      - 1;
  if (topOp instanceof Union) {
    relBuilder.union(topOp.all, n);
  } else if (topOp instanceof Intersect) {
    relBuilder.intersect(topOp.all, n);
  } else if (topOp instanceof Minus) {
    relBuilder.minus(topOp.all, n);
  }
  call.transformTo(relBuilder.build());
}