use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.SetOp 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.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.SetOp in project calcite by apache.
the class FilterSetOpTransposeRule method onMatch.
// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
public void onMatch(RelOptRuleCall call) {
Filter filterRel = call.rel(0);
SetOp setOp = call.rel(1);
RexNode condition = filterRel.getCondition();
// create filters on top of each setop child, modifying the filter
// condition to reference each setop child
RexBuilder rexBuilder = filterRel.getCluster().getRexBuilder();
final RelBuilder relBuilder = call.builder();
List<RelDataTypeField> origFields = setOp.getRowType().getFieldList();
int[] adjustments = new int[origFields.size()];
final List<RelNode> newSetOpInputs = new ArrayList<>();
for (RelNode input : setOp.getInputs()) {
RexNode newCondition = condition.accept(new RelOptUtil.RexInputConverter(rexBuilder, origFields, input.getRowType().getFieldList(), adjustments));
newSetOpInputs.add(relBuilder.push(input).filter(newCondition).build());
}
// create a new setop whose children are the filters created above
SetOp newSetOp = setOp.copy(setOp.getTraitSet(), newSetOpInputs);
call.transformTo(newSetOp);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.SetOp in project calcite by apache.
the class ProjectSetOpTransposeRule method onMatch.
// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
public void onMatch(RelOptRuleCall call) {
LogicalProject origProj = call.rel(0);
SetOp setOp = call.rel(1);
// cannot push project past a distinct
if (!setOp.all) {
return;
}
// locate all fields referenced in the projection
PushProjector pushProject = new PushProjector(origProj, null, setOp, preserveExprCondition, call.builder());
pushProject.locateAllRefs();
List<RelNode> newSetOpInputs = new ArrayList<>();
int[] adjustments = pushProject.getAdjustments();
// and it is the only operator this rule currently acts on
for (RelNode input : setOp.getInputs()) {
// be lazy: produce two ProjectRels, and let another rule
// merge them (could probably just clone origProj instead?)
Project p = pushProject.createProjectRefsAndExprs(input, true, false);
newSetOpInputs.add(pushProject.createNewProject(p, adjustments));
}
// create a new setop whose children are the ProjectRels created above
SetOp newSetOp = setOp.copy(setOp.getTraitSet(), newSetOpInputs);
call.transformTo(newSetOp);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.SetOp 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.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.core.SetOp in project flink by apache.
the class HiveParserCalcitePlanner method genSetOpLogicalPlan.
@SuppressWarnings("nls")
private RelNode genSetOpLogicalPlan(HiveParserQBExpr.Opcode opcode, String alias, String leftalias, RelNode leftRel, String rightalias, RelNode rightRel) throws SemanticException {
// 1. Get Row Resolvers, Column map for original left and right input of SetOp Rel
HiveParserRowResolver leftRR = relToRowResolver.get(leftRel);
HiveParserRowResolver rightRR = relToRowResolver.get(rightRel);
HashMap<String, ColumnInfo> leftMap = leftRR.getFieldMap(leftalias);
HashMap<String, ColumnInfo> rightMap = rightRR.getFieldMap(rightalias);
// 2. Validate that SetOp is feasible according to Hive (by using type info from RR)
if (leftMap.size() != rightMap.size()) {
throw new SemanticException("Schema of both sides of union should match.");
}
// 3. construct SetOp Output RR using original left & right Input
HiveParserRowResolver setOpOutRR = new HiveParserRowResolver();
Iterator<Map.Entry<String, ColumnInfo>> lIter = leftMap.entrySet().iterator();
Iterator<Map.Entry<String, ColumnInfo>> rIter = rightMap.entrySet().iterator();
while (lIter.hasNext()) {
Map.Entry<String, ColumnInfo> lEntry = lIter.next();
Map.Entry<String, ColumnInfo> rEntry = rIter.next();
ColumnInfo lInfo = lEntry.getValue();
ColumnInfo rInfo = rEntry.getValue();
String field = lEntry.getKey();
// try widening conversion, otherwise fail union
TypeInfo commonTypeInfo = FunctionRegistry.getCommonClassForUnionAll(lInfo.getType(), rInfo.getType());
if (commonTypeInfo == null) {
HiveParserASTNode tabRef = getQB().getAliases().isEmpty() ? null : getQB().getParseInfo().getSrcForAlias(getQB().getAliases().get(0));
throw new SemanticException(generateErrorMessage(tabRef, "Schema of both sides of setop should match: Column " + field + " is of type " + lInfo.getType().getTypeName() + " on first table and type " + rInfo.getType().getTypeName() + " on second table"));
}
ColumnInfo setOpColInfo = new ColumnInfo(lInfo);
setOpColInfo.setType(commonTypeInfo);
setOpOutRR.put(alias, field, setOpColInfo);
}
// 4. Determine which columns requires cast on left/right input (Calcite requires exact
// types on both sides of SetOp)
boolean leftNeedsTypeCast = false;
boolean rightNeedsTypeCast = false;
List<RexNode> leftProjs = new ArrayList<>();
List<RexNode> rightProjs = new ArrayList<>();
List<RelDataTypeField> leftFields = leftRel.getRowType().getFieldList();
List<RelDataTypeField> rightFields = rightRel.getRowType().getFieldList();
for (int i = 0; i < leftFields.size(); i++) {
RelDataType leftFieldType = leftFields.get(i).getType();
RelDataType rightFieldType = rightFields.get(i).getType();
if (!leftFieldType.equals(rightFieldType)) {
RelDataType unionFieldType = HiveParserUtils.toRelDataType(setOpOutRR.getColumnInfos().get(i).getType(), cluster.getTypeFactory());
if (!unionFieldType.equals(leftFieldType)) {
leftNeedsTypeCast = true;
}
leftProjs.add(cluster.getRexBuilder().ensureType(unionFieldType, cluster.getRexBuilder().makeInputRef(leftFieldType, i), true));
if (!unionFieldType.equals(rightFieldType)) {
rightNeedsTypeCast = true;
}
rightProjs.add(cluster.getRexBuilder().ensureType(unionFieldType, cluster.getRexBuilder().makeInputRef(rightFieldType, i), true));
} else {
leftProjs.add(cluster.getRexBuilder().ensureType(leftFieldType, cluster.getRexBuilder().makeInputRef(leftFieldType, i), true));
rightProjs.add(cluster.getRexBuilder().ensureType(rightFieldType, cluster.getRexBuilder().makeInputRef(rightFieldType, i), true));
}
}
// parity
if (leftNeedsTypeCast) {
leftRel = LogicalProject.create(leftRel, Collections.emptyList(), leftProjs, leftRel.getRowType().getFieldNames());
}
if (rightNeedsTypeCast) {
rightRel = LogicalProject.create(rightRel, Collections.emptyList(), rightProjs, rightRel.getRowType().getFieldNames());
}
// 6. Construct SetOp Rel
List<RelNode> leftAndRight = Arrays.asList(leftRel, rightRel);
SetOp setOpRel;
switch(opcode) {
case UNION:
setOpRel = LogicalUnion.create(leftAndRight, true);
break;
case INTERSECT:
setOpRel = LogicalIntersect.create(leftAndRight, false);
break;
case INTERSECTALL:
setOpRel = LogicalIntersect.create(leftAndRight, true);
break;
case EXCEPT:
setOpRel = LogicalMinus.create(leftAndRight, false);
break;
case EXCEPTALL:
setOpRel = LogicalMinus.create(leftAndRight, true);
break;
default:
throw new SemanticException("Unsupported set operator " + opcode.toString());
}
relToRowResolver.put(setOpRel, setOpOutRR);
relToHiveColNameCalcitePosMap.put(setOpRel, buildHiveToCalciteColumnMap(setOpOutRR));
return setOpRel;
}
Aggregations