Search in sources :

Example 46 with Join

use of org.apache.calcite.rel.core.Join in project hive by apache.

the class HiveJoinSwapConstraintsRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final Join topJoin = call.rel(0);
    final Join bottomJoin = call.rel(1);
    final RexBuilder rexBuilder = topJoin.getCluster().getRexBuilder();
    // 1) Check whether these joins can be swapped.
    if (topJoin.getJoinType().generatesNullsOnLeft() || bottomJoin.getJoinType().generatesNullsOnLeft() || bottomJoin.isSemiJoin()) {
        // Nothing to do
        return;
    }
    // 2) Check whether the bottom is a non-filtering column appending join.
    // - If the top one is a non-filtering column appending join, we do not
    // trigger the optimization, since we do not want to swap this type of
    // joins.
    // - If the bottom one is not a non-filtering column appending join,
    // we cannot trigger the optimization.
    RewritablePKFKJoinInfo topInfo = HiveRelOptUtil.isRewritablePKFKJoin(topJoin, topJoin.getLeft(), topJoin.getRight(), call.getMetadataQuery());
    RewritablePKFKJoinInfo bottomInfo = HiveRelOptUtil.isRewritablePKFKJoin(bottomJoin, bottomJoin.getLeft(), bottomJoin.getRight(), call.getMetadataQuery());
    if (topInfo.rewritable || !bottomInfo.rewritable) {
        // Nothing to do
        return;
    }
    // 3) Rewrite.
    // X is the left child of the join below
    // Y is the right child of the join below
    // Z is the right child of the top join
    int nFieldsX = bottomJoin.getLeft().getRowType().getFieldList().size();
    int nFieldsY = bottomJoin.getRight().getRowType().getFieldList().size();
    int nFieldsZ = topJoin.getRight().getRowType().getFieldList().size();
    int nTotalFields = nFieldsX + nFieldsY + nFieldsZ;
    List<RelDataTypeField> fields = new ArrayList<>();
    // create a list of fields for the full join result; note that
    // we can't simply use the fields because the row-type of a
    // semi-join would only include the left hand side fields
    List<RelDataTypeField> joinFields = topJoin.getRowType().getFieldList();
    for (int i = 0; i < (nFieldsX + nFieldsY); i++) {
        fields.add(joinFields.get(i));
    }
    joinFields = topJoin.getRight().getRowType().getFieldList();
    for (int i = 0; i < nFieldsZ; i++) {
        fields.add(joinFields.get(i));
    }
    // determine which operands below the join are the actual
    // rels that participate in it
    final Set<Integer> leftKeys = HiveCalciteUtil.getInputRefs(topJoin.getCondition());
    leftKeys.removeIf(i -> i >= topJoin.getLeft().getRowType().getFieldCount());
    int nKeysFromX = 0;
    for (int leftKey : leftKeys) {
        if (leftKey < nFieldsX) {
            nKeysFromX++;
        }
    }
    // the keys must all originate from the left
    if (nKeysFromX != leftKeys.size()) {
        // Nothing to do
        return;
    }
    // need to convert the conditions
    // (X, Y, Z) --> (X, Z, Y)
    int[] adjustments = new int[nTotalFields];
    setJoinAdjustments(adjustments, nFieldsX, nFieldsY, nFieldsZ, nFieldsZ, -nFieldsY);
    final RexNode newBottomCondition = topJoin.getCondition().accept(new RelOptUtil.RexInputConverter(rexBuilder, fields, adjustments));
    // create the new joins
    final Join newBottomJoin = topJoin.copy(topJoin.getTraitSet(), newBottomCondition, bottomJoin.getLeft(), topJoin.getRight(), topJoin.getJoinType(), topJoin.isSemiJoinDone());
    final RexNode newTopCondition;
    if (newBottomJoin.isSemiJoin()) {
        newTopCondition = bottomJoin.getCondition();
    } else {
        newTopCondition = bottomJoin.getCondition().accept(new RelOptUtil.RexInputConverter(rexBuilder, fields, adjustments));
    }
    final Join newTopJoin = bottomJoin.copy(bottomJoin.getTraitSet(), newTopCondition, newBottomJoin, bottomJoin.getRight(), bottomJoin.getJoinType(), bottomJoin.isSemiJoinDone());
    if (newBottomJoin.isSemiJoin()) {
        call.transformTo(newTopJoin);
    } else {
        // need to swap the columns to match the original join
        // (X, Y, Z) --> (X, Z, Y)
        List<RexNode> exprs = new ArrayList<>();
        for (int i = 0; i < nFieldsX; i++) {
            exprs.add(rexBuilder.makeInputRef(newTopJoin, i));
        }
        for (int i = nFieldsX + nFieldsZ; i < topJoin.getRowType().getFieldCount(); i++) {
            exprs.add(rexBuilder.makeInputRef(newTopJoin, i));
        }
        for (int i = nFieldsX; i < nFieldsX + nFieldsZ; i++) {
            exprs.add(rexBuilder.makeInputRef(newTopJoin, i));
        }
        call.transformTo(call.builder().push(newTopJoin).project(exprs).build());
    }
}
Also used : RewritablePKFKJoinInfo(org.apache.hadoop.hive.ql.optimizer.calcite.HiveRelOptUtil.RewritablePKFKJoinInfo) HiveRelOptUtil(org.apache.hadoop.hive.ql.optimizer.calcite.HiveRelOptUtil) RelOptUtil(org.apache.calcite.plan.RelOptUtil) ArrayList(java.util.ArrayList) Join(org.apache.calcite.rel.core.Join) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RexBuilder(org.apache.calcite.rex.RexBuilder) RexNode(org.apache.calcite.rex.RexNode)

Example 47 with Join

use of org.apache.calcite.rel.core.Join in project hive by apache.

the class HiveProjectJoinTransposeRule method onMatch.

// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
public void onMatch(RelOptRuleCall call) {
    Project origProj = call.rel(0);
    final Join join = call.rel(1);
    if (join.getJoinType() == JoinRelType.SEMI || join.getJoinType() == JoinRelType.ANTI) {
        // TODO: support SemiJoin
        return;
    }
    // locate all fields referenced in the projection and join condition;
    // determine which inputs are referenced in the projection and
    // join condition; if all fields are being referenced and there are no
    // special expressions, no point in proceeding any further
    PushProjector pushProject = new PushProjector(origProj, join.getCondition(), join, preserveExprCondition, call.builder());
    if (pushProject.locateAllRefs()) {
        return;
    }
    // create left and right projections, projecting only those
    // fields referenced on each side
    RelNode leftProjRel = pushProject.createProjectRefsAndExprs(join.getLeft(), true, false);
    RelNode rightProjRel = pushProject.createProjectRefsAndExprs(join.getRight(), true, true);
    // convert the join condition to reference the projected columns
    RexNode newJoinFilter = null;
    int[] adjustments = pushProject.getAdjustments();
    if (join.getCondition() != null) {
        List<RelDataTypeField> projJoinFieldList = new ArrayList<>();
        projJoinFieldList.addAll(join.getSystemFieldList());
        projJoinFieldList.addAll(leftProjRel.getRowType().getFieldList());
        projJoinFieldList.addAll(rightProjRel.getRowType().getFieldList());
        newJoinFilter = pushProject.convertRefsAndExprs(join.getCondition(), projJoinFieldList, adjustments);
    }
    // create a new join with the projected children
    Join newJoinRel = join.copy(join.getTraitSet(), newJoinFilter, leftProjRel, rightProjRel, join.getJoinType(), join.isSemiJoinDone());
    // put the original project on top of the join, converting it to
    // reference the modified projection list
    RelNode topProject = pushProject.createNewProject(newJoinRel, adjustments);
    call.transformTo(topProject);
}
Also used : Project(org.apache.calcite.rel.core.Project) PushProjector(org.apache.calcite.rel.rules.PushProjector) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) ArrayList(java.util.ArrayList) Join(org.apache.calcite.rel.core.Join) RexNode(org.apache.calcite.rex.RexNode)

Example 48 with Join

use of org.apache.calcite.rel.core.Join in project hive by apache.

the class HiveRemoveGBYSemiJoinRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final Join join = call.rel(0);
    if (join.getJoinType() != JoinRelType.SEMI && join.getJoinType() != JoinRelType.ANTI) {
        return;
    }
    final RelNode left = call.rel(1);
    final Aggregate rightAggregate = call.rel(2);
    // if grouping sets are involved do early return
    if (rightAggregate.getGroupType() != Aggregate.Group.SIMPLE) {
        return;
    }
    if (rightAggregate.indicator) {
        return;
    }
    // if there is any aggregate function this group by is not un-necessary
    if (!rightAggregate.getAggCallList().isEmpty()) {
        return;
    }
    JoinPredicateInfo joinPredInfo;
    try {
        joinPredInfo = HiveCalciteUtil.JoinPredicateInfo.constructJoinPredicateInfo(join);
    } catch (CalciteSemanticException e) {
        LOG.warn("Exception while extracting predicate info from {}", join);
        return;
    }
    if (!joinPredInfo.getNonEquiJoinPredicateElements().isEmpty()) {
        return;
    }
    ImmutableBitSet.Builder rightKeys = ImmutableBitSet.builder();
    for (JoinLeafPredicateInfo leftPredInfo : joinPredInfo.getEquiJoinPredicateElements()) {
        rightKeys.addAll(leftPredInfo.getProjsFromRightPartOfJoinKeysInChildSchema());
    }
    boolean shouldTransform = rightKeys.build().equals(ImmutableBitSet.range(rightAggregate.getGroupCount()));
    if (shouldTransform) {
        final RelBuilder relBuilder = call.builder();
        RelNode newRightInput = relBuilder.project(relBuilder.push(rightAggregate.getInput()).fields(rightAggregate.getGroupSet().asList())).build();
        RelNode newJoin;
        if (join.getJoinType() == JoinRelType.SEMI) {
            newJoin = call.builder().push(left).push(newRightInput).semiJoin(join.getCondition()).build();
        } else {
            newJoin = call.builder().push(left).push(newRightInput).antiJoin(join.getCondition()).build();
        }
        call.transformTo(newJoin);
    }
}
Also used : JoinLeafPredicateInfo(org.apache.hadoop.hive.ql.optimizer.calcite.HiveCalciteUtil.JoinLeafPredicateInfo) RelBuilder(org.apache.calcite.tools.RelBuilder) RelNode(org.apache.calcite.rel.RelNode) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) JoinPredicateInfo(org.apache.hadoop.hive.ql.optimizer.calcite.HiveCalciteUtil.JoinPredicateInfo) Join(org.apache.calcite.rel.core.Join) CalciteSemanticException(org.apache.hadoop.hive.ql.optimizer.calcite.CalciteSemanticException) Aggregate(org.apache.calcite.rel.core.Aggregate)

Example 49 with Join

use of org.apache.calcite.rel.core.Join in project hive by apache.

the class HiveSemiJoinProjectTransposeRule method onMatch.

// ~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
    Join semiJoin = call.rel(0);
    Project project = call.rel(1);
    // Convert the LHS semi-join keys to reference the child projection
    // expression; all projection expressions must be RexInputRefs,
    // otherwise, we wouldn't have created this semi-join.
    // convert the semijoin condition to reflect the LHS with the project
    // pulled up
    RexNode newCondition = adjustCondition(project, semiJoin);
    Join newSemiJoin = HiveSemiJoin.getSemiJoin(project.getCluster(), project.getTraitSet(), project.getInput(), semiJoin.getRight(), newCondition);
    // Create the new projection.  Note that the projection expressions
    // are the same as the original because they only reference the LHS
    // of the semijoin and the semijoin only projects out the LHS
    final RelBuilder relBuilder = call.builder();
    relBuilder.push(newSemiJoin);
    relBuilder.project(project.getProjects(), project.getRowType().getFieldNames());
    call.transformTo(relBuilder.build());
}
Also used : Project(org.apache.calcite.rel.core.Project) RelBuilder(org.apache.calcite.tools.RelBuilder) HiveSemiJoin(org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveSemiJoin) Join(org.apache.calcite.rel.core.Join) RexNode(org.apache.calcite.rex.RexNode)

Example 50 with Join

use of org.apache.calcite.rel.core.Join in project hive by apache.

the class HiveAntiSemiJoinRule method perform.

protected void perform(RelOptRuleCall call, Project project, Filter filter, Join join) {
    LOG.debug("Start Matching HiveAntiJoinRule");
    // https://issues.apache.org/jira/browse/HIVE-23991
    if (join.getCondition().isAlwaysTrue()) {
        return;
    }
    // We support conversion from left outer join only.
    if (join.getJoinType() != JoinRelType.LEFT) {
        return;
    }
    assert (filter != null);
    List<RexNode> filterList = getResidualFilterNodes(filter, join);
    if (filterList == null) {
        return;
    }
    // If any projection is there from right side, then we can not convert to anti join.
    boolean hasProjection = HiveCalciteUtil.hasAnyExpressionFromRightSide(join, project.getProjects());
    if (hasProjection) {
        return;
    }
    LOG.debug("Matched HiveAntiJoinRule");
    // Build anti join with same left, right child and condition as original left outer join.
    Join anti = HiveAntiJoin.getAntiJoin(join.getLeft().getCluster(), join.getLeft().getTraitSet(), join.getLeft(), join.getRight(), join.getCondition());
    RelNode newProject;
    if (filterList.isEmpty()) {
        newProject = project.copy(project.getTraitSet(), anti, project.getProjects(), project.getRowType());
    } else {
        // Collate the filter condition using AND as the filter was decomposed based
        // on AND condition (RelOptUtil.conjunctions).
        RexNode condition = filterList.size() == 1 ? filterList.get(0) : join.getCluster().getRexBuilder().makeCall(SqlStdOperatorTable.AND, filterList);
        Filter newFilter = filter.copy(filter.getTraitSet(), anti, condition);
        newProject = project.copy(project.getTraitSet(), newFilter, project.getProjects(), project.getRowType());
    }
    call.transformTo(newProject);
}
Also used : RelNode(org.apache.calcite.rel.RelNode) Filter(org.apache.calcite.rel.core.Filter) Join(org.apache.calcite.rel.core.Join) HiveAntiJoin(org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveAntiJoin) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

Join (org.apache.calcite.rel.core.Join)73 RelNode (org.apache.calcite.rel.RelNode)45 RexNode (org.apache.calcite.rex.RexNode)40 ArrayList (java.util.ArrayList)28 LogicalJoin (org.apache.calcite.rel.logical.LogicalJoin)25 Project (org.apache.calcite.rel.core.Project)22 RexBuilder (org.apache.calcite.rex.RexBuilder)20 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)18 RelBuilder (org.apache.calcite.tools.RelBuilder)17 HiveJoin (org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveJoin)14 Aggregate (org.apache.calcite.rel.core.Aggregate)13 Filter (org.apache.calcite.rel.core.Filter)12 SemiJoin (org.apache.calcite.rel.core.SemiJoin)11 RelOptCluster (org.apache.calcite.plan.RelOptCluster)10 JoinRelType (org.apache.calcite.rel.core.JoinRelType)9 RelMetadataQuery (org.apache.calcite.rel.metadata.RelMetadataQuery)9 Mappings (org.apache.calcite.util.mapping.Mappings)9 List (java.util.List)8 LogicalProject (org.apache.calcite.rel.logical.LogicalProject)8 RelDataType (org.apache.calcite.rel.type.RelDataType)8