Search in sources :

Example 11 with ImmutableIntList

use of org.apache.calcite.util.ImmutableIntList in project calcite by apache.

the class SemiJoinJoinTransposeRule method onMatch.

// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
public void onMatch(RelOptRuleCall call) {
    SemiJoin semiJoin = call.rel(0);
    final Join join = call.rel(1);
    if (join instanceof SemiJoin) {
        return;
    }
    final ImmutableIntList leftKeys = semiJoin.getLeftKeys();
    final ImmutableIntList rightKeys = semiJoin.getRightKeys();
    // X is the left child of the join below the semi-join
    // Y is the right child of the join below the semi-join
    // Z is the right child of the semi-join
    int nFieldsX = join.getLeft().getRowType().getFieldList().size();
    int nFieldsY = join.getRight().getRowType().getFieldList().size();
    int nFieldsZ = semiJoin.getRight().getRowType().getFieldList().size();
    int nTotalFields = nFieldsX + nFieldsY + nFieldsZ;
    List<RelDataTypeField> fields = new ArrayList<RelDataTypeField>();
    // create a list of fields for the full join result; note that
    // we can't simply use the fields from the semi-join because the
    // row-type of a semi-join only includes the left hand side fields
    List<RelDataTypeField> joinFields = semiJoin.getRowType().getFieldList();
    for (int i = 0; i < (nFieldsX + nFieldsY); i++) {
        fields.add(joinFields.get(i));
    }
    joinFields = semiJoin.getRight().getRowType().getFieldList();
    for (int i = 0; i < nFieldsZ; i++) {
        fields.add(joinFields.get(i));
    }
    // determine which operands below the semi-join are the actual
    // Rels that participate in the semi-join
    int nKeysFromX = 0;
    for (int leftKey : leftKeys) {
        if (leftKey < nFieldsX) {
            nKeysFromX++;
        }
    }
    // otherwise, a semi-join wouldn't have been created
    assert (nKeysFromX == 0) || (nKeysFromX == leftKeys.size());
    // need to convert the semi-join condition and possibly the keys
    RexNode newSemiJoinFilter;
    List<Integer> newLeftKeys;
    int[] adjustments = new int[nTotalFields];
    if (nKeysFromX > 0) {
        // (X, Y, Z) --> (X, Z, Y)
        // semiJoin(X, Z)
        // pass 0 as Y's adjustment because there shouldn't be any
        // references to Y in the semi-join filter
        setJoinAdjustments(adjustments, nFieldsX, nFieldsY, nFieldsZ, 0, -nFieldsY);
        newSemiJoinFilter = semiJoin.getCondition().accept(new RelOptUtil.RexInputConverter(semiJoin.getCluster().getRexBuilder(), fields, adjustments));
        newLeftKeys = leftKeys;
    } else {
        // (X, Y, Z) --> (X, Y, Z)
        // semiJoin(Y, Z)
        setJoinAdjustments(adjustments, nFieldsX, nFieldsY, nFieldsZ, -nFieldsX, -nFieldsX);
        newSemiJoinFilter = semiJoin.getCondition().accept(new RelOptUtil.RexInputConverter(semiJoin.getCluster().getRexBuilder(), fields, adjustments));
        newLeftKeys = RelOptUtil.adjustKeys(leftKeys, -nFieldsX);
    }
    // create the new join
    RelNode leftSemiJoinOp;
    if (nKeysFromX > 0) {
        leftSemiJoinOp = join.getLeft();
    } else {
        leftSemiJoinOp = join.getRight();
    }
    SemiJoin newSemiJoin = SemiJoin.create(leftSemiJoinOp, semiJoin.getRight(), newSemiJoinFilter, ImmutableIntList.copyOf(newLeftKeys), rightKeys);
    RelNode leftJoinRel;
    RelNode rightJoinRel;
    if (nKeysFromX > 0) {
        leftJoinRel = newSemiJoin;
        rightJoinRel = join.getRight();
    } else {
        leftJoinRel = join.getLeft();
        rightJoinRel = newSemiJoin;
    }
    RelNode newJoinRel = join.copy(join.getTraitSet(), join.getCondition(), leftJoinRel, rightJoinRel, join.getJoinType(), join.isSemiJoinDone());
    call.transformTo(newJoinRel);
}
Also used : ArrayList(java.util.ArrayList) SemiJoin(org.apache.calcite.rel.core.SemiJoin) Join(org.apache.calcite.rel.core.Join) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) SemiJoin(org.apache.calcite.rel.core.SemiJoin) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) RexNode(org.apache.calcite.rex.RexNode)

Example 12 with ImmutableIntList

use of org.apache.calcite.util.ImmutableIntList in project calcite by apache.

the class SemiJoinRule method perform.

protected void perform(RelOptRuleCall call, Project project, Join join, RelNode left, Aggregate aggregate) {
    final RelOptCluster cluster = join.getCluster();
    final RexBuilder rexBuilder = cluster.getRexBuilder();
    if (project != null) {
        final ImmutableBitSet bits = RelOptUtil.InputFinder.bits(project.getProjects(), null);
        final ImmutableBitSet rightBits = ImmutableBitSet.range(left.getRowType().getFieldCount(), join.getRowType().getFieldCount());
        if (bits.intersects(rightBits)) {
            return;
        }
    }
    final JoinInfo joinInfo = join.analyzeCondition();
    if (!joinInfo.rightSet().equals(ImmutableBitSet.range(aggregate.getGroupCount()))) {
        // By the way, neither a super-set nor a sub-set would work.
        return;
    }
    if (!joinInfo.isEqui()) {
        return;
    }
    final RelBuilder relBuilder = call.builder();
    relBuilder.push(left);
    switch(join.getJoinType()) {
        case INNER:
            final List<Integer> newRightKeyBuilder = Lists.newArrayList();
            final List<Integer> aggregateKeys = aggregate.getGroupSet().asList();
            for (int key : joinInfo.rightKeys) {
                newRightKeyBuilder.add(aggregateKeys.get(key));
            }
            final ImmutableIntList newRightKeys = ImmutableIntList.copyOf(newRightKeyBuilder);
            relBuilder.push(aggregate.getInput());
            final RexNode newCondition = RelOptUtil.createEquiJoinCondition(relBuilder.peek(2, 0), joinInfo.leftKeys, relBuilder.peek(2, 1), newRightKeys, rexBuilder);
            relBuilder.semiJoin(newCondition);
            break;
        case LEFT:
            // we can eliminate the semi-join.
            break;
        default:
            throw new AssertionError(join.getJoinType());
    }
    if (project != null) {
        relBuilder.project(project.getProjects(), project.getRowType().getFieldNames());
    }
    call.transformTo(relBuilder.build());
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) JoinInfo(org.apache.calcite.rel.core.JoinInfo) RelBuilder(org.apache.calcite.tools.RelBuilder) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RexBuilder(org.apache.calcite.rex.RexBuilder) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) RexNode(org.apache.calcite.rex.RexNode)

Example 13 with ImmutableIntList

use of org.apache.calcite.util.ImmutableIntList in project hive by apache.

the class HiveSemiJoinRule method perform.

protected void perform(RelOptRuleCall call, ImmutableBitSet topRefs, RelNode topOperator, Join join, RelNode left, Aggregate aggregate) {
    LOG.debug("Matched HiveSemiJoinRule");
    final RelOptCluster cluster = join.getCluster();
    final RexBuilder rexBuilder = cluster.getRexBuilder();
    final ImmutableBitSet rightBits = ImmutableBitSet.range(left.getRowType().getFieldCount(), join.getRowType().getFieldCount());
    if (topRefs.intersects(rightBits)) {
        return;
    }
    final JoinInfo joinInfo = join.analyzeCondition();
    if (!joinInfo.rightSet().equals(ImmutableBitSet.range(aggregate.getGroupCount()))) {
        // By the way, neither a super-set nor a sub-set would work.
        return;
    }
    if (join.getJoinType() == JoinRelType.LEFT) {
        // since for LEFT join we are only interested in rows from LEFT we can get rid of right side
        call.transformTo(topOperator.copy(topOperator.getTraitSet(), ImmutableList.of(left)));
        return;
    }
    if (join.getJoinType() != JoinRelType.INNER) {
        return;
    }
    if (!joinInfo.isEqui()) {
        return;
    }
    LOG.debug("All conditions matched for HiveSemiJoinRule. Going to apply transformation.");
    final List<Integer> newRightKeyBuilder = Lists.newArrayList();
    final List<Integer> aggregateKeys = aggregate.getGroupSet().asList();
    for (int key : joinInfo.rightKeys) {
        newRightKeyBuilder.add(aggregateKeys.get(key));
    }
    final ImmutableIntList newRightKeys = ImmutableIntList.copyOf(newRightKeyBuilder);
    final RelNode newRight = aggregate.getInput();
    final RexNode newCondition = RelOptUtil.createEquiJoinCondition(left, joinInfo.leftKeys, newRight, newRightKeys, rexBuilder);
    RelNode semi = null;
    // is not expected further down the pipeline. see jira for more details
    if (aggregate.getInput() instanceof HepRelVertex && ((HepRelVertex) aggregate.getInput()).getCurrentRel() instanceof Join) {
        Join rightJoin = (Join) (((HepRelVertex) aggregate.getInput()).getCurrentRel());
        List<RexNode> projects = new ArrayList<>();
        for (int i = 0; i < rightJoin.getRowType().getFieldCount(); i++) {
            projects.add(rexBuilder.makeInputRef(rightJoin, i));
        }
        RelNode topProject = call.builder().push(rightJoin).project(projects, rightJoin.getRowType().getFieldNames(), true).build();
        semi = call.builder().push(left).push(topProject).semiJoin(newCondition).build();
    } else {
        semi = call.builder().push(left).push(aggregate.getInput()).semiJoin(newCondition).build();
    }
    call.transformTo(topOperator.copy(topOperator.getTraitSet(), ImmutableList.of(semi)));
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ArrayList(java.util.ArrayList) Join(org.apache.calcite.rel.core.Join) JoinInfo(org.apache.calcite.rel.core.JoinInfo) HepRelVertex(org.apache.calcite.plan.hep.HepRelVertex) RelNode(org.apache.calcite.rel.RelNode) RexBuilder(org.apache.calcite.rex.RexBuilder) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) RexNode(org.apache.calcite.rex.RexNode)

Example 14 with ImmutableIntList

use of org.apache.calcite.util.ImmutableIntList in project hive by apache.

the class HiveJoin method getSortedInputs.

public ImmutableBitSet getSortedInputs() throws CalciteSemanticException {
    ImmutableBitSet.Builder sortedInputsBuilder = ImmutableBitSet.builder();
    JoinPredicateInfo joinPredInfo = HiveCalciteUtil.JoinPredicateInfo.constructJoinPredicateInfo(this);
    List<ImmutableIntList> joinKeysInChildren = new ArrayList<ImmutableIntList>();
    joinKeysInChildren.add(ImmutableIntList.copyOf(joinPredInfo.getProjsFromLeftPartOfJoinKeysInChildSchema()));
    joinKeysInChildren.add(ImmutableIntList.copyOf(joinPredInfo.getProjsFromRightPartOfJoinKeysInChildSchema()));
    final RelMetadataQuery mq = this.left.getCluster().getMetadataQuery();
    for (int i = 0; i < this.getInputs().size(); i++) {
        List<RelCollation> collations = mq.collations(this.getInputs().get(i));
        if (collations != null) {
            boolean correctOrderFound = RelCollations.contains(collations, joinKeysInChildren.get(i));
            if (correctOrderFound) {
                sortedInputsBuilder.set(i);
            }
        }
    }
    return sortedInputsBuilder.build();
}
Also used : RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) RelCollation(org.apache.calcite.rel.RelCollation) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) JoinPredicateInfo(org.apache.hadoop.hive.ql.optimizer.calcite.HiveCalciteUtil.JoinPredicateInfo) ArrayList(java.util.ArrayList) ImmutableIntList(org.apache.calcite.util.ImmutableIntList)

Example 15 with ImmutableIntList

use of org.apache.calcite.util.ImmutableIntList in project calcite by apache.

the class RelMetadataTest method checkCollation.

private void checkCollation(RelOptCluster cluster, RelOptTable empTable, RelOptTable deptTable) {
    final RexBuilder rexBuilder = cluster.getRexBuilder();
    final LogicalTableScan empScan = LogicalTableScan.create(cluster, empTable);
    List<RelCollation> collations = RelMdCollation.table(empScan.getTable());
    assertThat(collations.size(), equalTo(0));
    // ORDER BY field#0 ASC, field#1 ASC
    final RelCollation collation = RelCollations.of(new RelFieldCollation(0), new RelFieldCollation(1));
    collations = RelMdCollation.sort(collation);
    assertThat(collations.size(), equalTo(1));
    assertThat(collations.get(0).getFieldCollations().size(), equalTo(2));
    final Sort empSort = LogicalSort.create(empScan, collation, null, null);
    final List<RexNode> projects = ImmutableList.of(rexBuilder.makeInputRef(empSort, 1), rexBuilder.makeLiteral("foo"), rexBuilder.makeInputRef(empSort, 0), rexBuilder.makeCall(SqlStdOperatorTable.MINUS, rexBuilder.makeInputRef(empSort, 0), rexBuilder.makeInputRef(empSort, 3)));
    final RelMetadataQuery mq = RelMetadataQuery.instance();
    collations = RelMdCollation.project(mq, empSort, projects);
    assertThat(collations.size(), equalTo(1));
    assertThat(collations.get(0).getFieldCollations().size(), equalTo(2));
    assertThat(collations.get(0).getFieldCollations().get(0).getFieldIndex(), equalTo(2));
    assertThat(collations.get(0).getFieldCollations().get(1).getFieldIndex(), equalTo(0));
    final LogicalProject project = LogicalProject.create(empSort, projects, ImmutableList.of("a", "b", "c", "d"));
    final LogicalTableScan deptScan = LogicalTableScan.create(cluster, deptTable);
    final RelCollation deptCollation = RelCollations.of(new RelFieldCollation(0), new RelFieldCollation(1));
    final Sort deptSort = LogicalSort.create(deptScan, deptCollation, null, null);
    final ImmutableIntList leftKeys = ImmutableIntList.of(2);
    final ImmutableIntList rightKeys = ImmutableIntList.of(0);
    final EnumerableMergeJoin join;
    try {
        join = EnumerableMergeJoin.create(project, deptSort, rexBuilder.makeLiteral(true), leftKeys, rightKeys, JoinRelType.INNER);
    } catch (InvalidRelException e) {
        throw new RuntimeException(e);
    }
    collations = RelMdCollation.mergeJoin(mq, project, deptSort, leftKeys, rightKeys);
    assertThat(collations, equalTo(join.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE)));
    // Values (empty)
    collations = RelMdCollation.values(mq, empTable.getRowType(), ImmutableList.<ImmutableList<RexLiteral>>of());
    assertThat(collations.toString(), equalTo("[[0, 1, 2, 3, 4, 5, 6, 7, 8], " + "[1, 2, 3, 4, 5, 6, 7, 8], " + "[2, 3, 4, 5, 6, 7, 8], " + "[3, 4, 5, 6, 7, 8], " + "[4, 5, 6, 7, 8], " + "[5, 6, 7, 8], " + "[6, 7, 8], " + "[7, 8], " + "[8]]"));
    final LogicalValues emptyValues = LogicalValues.createEmpty(cluster, empTable.getRowType());
    assertThat(mq.collations(emptyValues), equalTo(collations));
    // Values (non-empty)
    final RelDataType rowType = cluster.getTypeFactory().builder().add("a", SqlTypeName.INTEGER).add("b", SqlTypeName.INTEGER).add("c", SqlTypeName.INTEGER).add("d", SqlTypeName.INTEGER).build();
    final ImmutableList.Builder<ImmutableList<RexLiteral>> tuples = ImmutableList.builder();
    // sort keys are [a], [a, b], [a, b, c], [a, b, c, d], [a, c], [b], [b, a],
    // [b, d]
    // algorithm deduces [a, b, c, d], [b, d] which is a useful sub-set
    addRow(tuples, rexBuilder, 1, 1, 1, 1);
    addRow(tuples, rexBuilder, 1, 2, 0, 3);
    addRow(tuples, rexBuilder, 2, 3, 2, 2);
    addRow(tuples, rexBuilder, 3, 3, 1, 4);
    collations = RelMdCollation.values(mq, rowType, tuples.build());
    assertThat(collations.toString(), equalTo("[[0, 1, 2, 3], [1, 3]]"));
    final LogicalValues values = LogicalValues.create(cluster, rowType, tuples.build());
    assertThat(mq.collations(values), equalTo(collations));
}
Also used : RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) InvalidRelException(org.apache.calcite.rel.InvalidRelException) ImmutableList(com.google.common.collect.ImmutableList) EnumerableMergeJoin(org.apache.calcite.adapter.enumerable.EnumerableMergeJoin) RelDataType(org.apache.calcite.rel.type.RelDataType) LogicalTableScan(org.apache.calcite.rel.logical.LogicalTableScan) LogicalValues(org.apache.calcite.rel.logical.LogicalValues) RelCollation(org.apache.calcite.rel.RelCollation) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) RexBuilder(org.apache.calcite.rex.RexBuilder) LogicalSort(org.apache.calcite.rel.logical.LogicalSort) Sort(org.apache.calcite.rel.core.Sort) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

ImmutableIntList (org.apache.calcite.util.ImmutableIntList)17 RexNode (org.apache.calcite.rex.RexNode)11 RexBuilder (org.apache.calcite.rex.RexBuilder)6 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)6 ArrayList (java.util.ArrayList)5 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)5 RelNode (org.apache.calcite.rel.RelNode)4 Join (org.apache.calcite.rel.core.Join)4 RelOptCluster (org.apache.calcite.plan.RelOptCluster)3 JoinInfo (org.apache.calcite.rel.core.JoinInfo)3 RelDataType (org.apache.calcite.rel.type.RelDataType)3 ImmutableList (com.google.common.collect.ImmutableList)2 Bindables (org.apache.calcite.interpreter.Bindables)2 RelOptTable (org.apache.calcite.plan.RelOptTable)2 HepRelVertex (org.apache.calcite.plan.hep.HepRelVertex)2 RelCollation (org.apache.calcite.rel.RelCollation)2 SemiJoin (org.apache.calcite.rel.core.SemiJoin)2 RelMetadataQuery (org.apache.calcite.rel.metadata.RelMetadataQuery)2 Pair (org.apache.calcite.util.Pair)2 HashMap (java.util.HashMap)1