use of org.apache.calcite.rel.core.Union in project calcite by apache.
the class JoinUnionTransposeRule method onMatch.
public void onMatch(RelOptRuleCall call) {
final Join join = call.rel(0);
final Union unionRel;
RelNode otherInput;
boolean unionOnLeft;
if (call.rel(1) instanceof Union) {
unionRel = call.rel(1);
otherInput = call.rel(2);
unionOnLeft = true;
} else {
otherInput = call.rel(1);
unionRel = call.rel(2);
unionOnLeft = false;
}
if (!unionRel.all) {
return;
}
if (!join.getVariablesSet().isEmpty()) {
return;
}
// in one or both branches of the union)
if (unionOnLeft) {
if (join.getJoinType().generatesNullsOnLeft()) {
return;
}
} else {
if (join.getJoinType().generatesNullsOnRight()) {
return;
}
}
List<RelNode> newUnionInputs = new ArrayList<RelNode>();
for (RelNode input : unionRel.getInputs()) {
RelNode joinLeft;
RelNode joinRight;
if (unionOnLeft) {
joinLeft = input;
joinRight = otherInput;
} else {
joinLeft = otherInput;
joinRight = input;
}
newUnionInputs.add(join.copy(join.getTraitSet(), join.getCondition(), joinLeft, joinRight, join.getJoinType(), join.isSemiJoinDone()));
}
final SetOp newUnionRel = unionRel.copy(unionRel.getTraitSet(), newUnionInputs, true);
call.transformTo(newUnionRel);
}
use of org.apache.calcite.rel.core.Union in project calcite by apache.
the class AggregateUnionTransposeRule method onMatch.
public void onMatch(RelOptRuleCall call) {
Aggregate aggRel = call.rel(0);
Union union = call.rel(1);
if (!union.all) {
// which yields 25 (incorrect).
return;
}
int groupCount = aggRel.getGroupSet().cardinality();
List<AggregateCall> transformedAggCalls = transformAggCalls(aggRel.copy(aggRel.getTraitSet(), aggRel.getInput(), false, aggRel.getGroupSet(), null, aggRel.getAggCallList()), groupCount, aggRel.getAggCallList());
if (transformedAggCalls == null) {
// which we can't handle
return;
}
// create corresponding aggregates on top of each union child
final RelBuilder relBuilder = call.builder();
int transformCount = 0;
final RelMetadataQuery mq = call.getMetadataQuery();
for (RelNode input : union.getInputs()) {
boolean alreadyUnique = RelMdUtil.areColumnsDefinitelyUnique(mq, input, aggRel.getGroupSet());
relBuilder.push(input);
if (!alreadyUnique) {
++transformCount;
relBuilder.aggregate(relBuilder.groupKey(aggRel.getGroupSet(), null), aggRel.getAggCallList());
}
}
if (transformCount == 0) {
// planners would succumb)
return;
}
// create a new union whose children are the aggregates created above
relBuilder.union(true, union.getInputs().size());
relBuilder.aggregate(relBuilder.groupKey(aggRel.getGroupSet(), aggRel.getGroupSets()), transformedAggCalls);
call.transformTo(relBuilder.build());
}
use of org.apache.calcite.rel.core.Union in project calcite by apache.
the class UnionEliminatorRule method onMatch.
// ~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
Union union = call.rel(0);
if (union.getInputs().size() != 1) {
return;
}
if (!union.all) {
return;
}
// REVIEW jvs 14-Mar-2006: why don't we need to register
// the equivalence here like we do in AggregateRemoveRule?
call.transformTo(union.getInputs().get(0));
}
use of org.apache.calcite.rel.core.Union in project calcite by apache.
the class UnionMergeRule method onMatch.
// ~ Methods ----------------------------------------------------------------
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;
}
// 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());
}
use of org.apache.calcite.rel.core.Union in project calcite by apache.
the class UnionToDistinctRule method onMatch.
// ~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
final Union union = call.rel(0);
if (union.all) {
// nothing to do
return;
}
final RelBuilder relBuilder = call.builder();
relBuilder.pushAll(union.getInputs());
relBuilder.union(true, union.getInputs().size());
relBuilder.distinct();
call.transformTo(relBuilder.build());
}
Aggregations