Search in sources :

Example 1 with SetOp

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);
}
Also used : SetOp(org.apache.calcite.rel.core.SetOp) RelNode(org.apache.calcite.rel.RelNode) ArrayList(java.util.ArrayList) Join(org.apache.calcite.rel.core.Join) Union(org.apache.calcite.rel.core.Union)

Example 2 with SetOp

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);
}
Also used : SetOp(org.apache.calcite.rel.core.SetOp) RelBuilder(org.apache.calcite.tools.RelBuilder) RelOptUtil(org.apache.calcite.plan.RelOptUtil) ArrayList(java.util.ArrayList) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) Filter(org.apache.calcite.rel.core.Filter) RexBuilder(org.apache.calcite.rex.RexBuilder) RexNode(org.apache.calcite.rex.RexNode)

Example 3 with SetOp

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);
}
Also used : Project(org.apache.calcite.rel.core.Project) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) SetOp(org.apache.calcite.rel.core.SetOp) RelNode(org.apache.calcite.rel.RelNode) ArrayList(java.util.ArrayList) LogicalProject(org.apache.calcite.rel.logical.LogicalProject)

Example 4 with SetOp

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());
}
Also used : SetOp(org.apache.calcite.rel.core.SetOp) LogicalIntersect(org.apache.calcite.rel.logical.LogicalIntersect) Intersect(org.apache.calcite.rel.core.Intersect) RelBuilder(org.apache.calcite.tools.RelBuilder) Union(org.apache.calcite.rel.core.Union) LogicalUnion(org.apache.calcite.rel.logical.LogicalUnion) Minus(org.apache.calcite.rel.core.Minus) LogicalMinus(org.apache.calcite.rel.logical.LogicalMinus)

Example 5 with SetOp

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;
}
Also used : SetOp(org.apache.calcite.rel.core.SetOp) HiveParserASTNode(org.apache.flink.table.planner.delegation.hive.copy.HiveParserASTNode) ArrayList(java.util.ArrayList) ColumnInfo(org.apache.hadoop.hive.ql.exec.ColumnInfo) RelDataType(org.apache.calcite.rel.type.RelDataType) TypeInfo(org.apache.hadoop.hive.serde2.typeinfo.TypeInfo) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) HiveParserRowResolver(org.apache.flink.table.planner.delegation.hive.copy.HiveParserRowResolver) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) HiveParserBaseSemanticAnalyzer.buildHiveToCalciteColumnMap(org.apache.flink.table.planner.delegation.hive.copy.HiveParserBaseSemanticAnalyzer.buildHiveToCalciteColumnMap) AbstractMap(java.util.AbstractMap) HiveParserBaseSemanticAnalyzer.buildHiveColNameToInputPosMap(org.apache.flink.table.planner.delegation.hive.copy.HiveParserBaseSemanticAnalyzer.buildHiveColNameToInputPosMap) SemanticException(org.apache.hadoop.hive.ql.parse.SemanticException) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

SetOp (org.apache.calcite.rel.core.SetOp)6 ArrayList (java.util.ArrayList)5 RelNode (org.apache.calcite.rel.RelNode)5 Union (org.apache.calcite.rel.core.Union)3 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)3 RexNode (org.apache.calcite.rex.RexNode)3 RelBuilder (org.apache.calcite.tools.RelBuilder)3 RelOptUtil (org.apache.calcite.plan.RelOptUtil)2 Filter (org.apache.calcite.rel.core.Filter)2 RexBuilder (org.apache.calcite.rex.RexBuilder)2 ImmutableList (com.google.common.collect.ImmutableList)1 AbstractMap (java.util.AbstractMap)1 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 RelOptPredicateList (org.apache.calcite.plan.RelOptPredicateList)1 Intersect (org.apache.calcite.rel.core.Intersect)1 Join (org.apache.calcite.rel.core.Join)1 Minus (org.apache.calcite.rel.core.Minus)1 Project (org.apache.calcite.rel.core.Project)1