Search in sources :

Example 11 with JoinInfo

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

the class EstimateUniqueKeys method getUniqueKeys.

private static Set<ImmutableBitSet> getUniqueKeys(HiveJoin rel) {
    RelNode left = getRelNode(rel.getLeft());
    RelNode right = getRelNode(rel.getRight());
    // first add the different combinations of concatenated unique keys
    // from the left and the right, adjusting the right hand side keys to
    // reflect the addition of the left hand side
    // 
    // NOTE zfong 12/18/06 - If the number of tables in a join is large,
    // the number of combinations of unique key sets will explode.  If
    // that is undesirable, use RelMetadataQuery.areColumnsUnique() as
    // an alternative way of getting unique key information.
    final Set<ImmutableBitSet> retSet = new HashSet<>();
    final Set<ImmutableBitSet> leftSet = getUniqueKeys(left);
    Set<ImmutableBitSet> rightSet = null;
    final Set<ImmutableBitSet> tmpRightSet = getUniqueKeys(right);
    int nFieldsOnLeft = left.getRowType().getFieldCount();
    if (tmpRightSet != null) {
        rightSet = new HashSet<>();
        for (ImmutableBitSet colMask : tmpRightSet) {
            ImmutableBitSet.Builder tmpMask = ImmutableBitSet.builder();
            for (int bit : colMask) {
                tmpMask.set(bit + nFieldsOnLeft);
            }
            rightSet.add(tmpMask.build());
        }
        if (leftSet != null) {
            for (ImmutableBitSet colMaskRight : rightSet) {
                for (ImmutableBitSet colMaskLeft : leftSet) {
                    retSet.add(colMaskLeft.union(colMaskRight));
                }
            }
        }
    }
    // locate the columns that participate in equijoins
    final JoinInfo joinInfo = rel.analyzeCondition();
    RelMetadataQuery mq = rel.getCluster().getMetadataQuery();
    // determine if either or both the LHS and RHS are unique on the
    // equijoin columns
    final Boolean leftUnique = mq.areColumnsUnique(left, joinInfo.leftSet());
    final Boolean rightUnique = mq.areColumnsUnique(right, joinInfo.rightSet());
    // generating
    if ((rightUnique != null) && rightUnique && (leftSet != null) && !(rel.getJoinType().generatesNullsOnLeft())) {
        retSet.addAll(leftSet);
    }
    // same as above except left and right are reversed
    if ((leftUnique != null) && leftUnique && (rightSet != null) && !(rel.getJoinType().generatesNullsOnRight())) {
        retSet.addAll(rightSet);
    }
    return retSet;
}
Also used : JoinInfo(org.apache.calcite.rel.core.JoinInfo) RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) RelNode(org.apache.calcite.rel.RelNode) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) HashSet(java.util.HashSet)

Example 12 with JoinInfo

use of org.apache.calcite.rel.core.JoinInfo 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 13 with JoinInfo

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

the class HiveAggregateJoinTransposeRule method isGroupingUnique.

/**
 * Determines weather the give grouping is unique.
 *
 * Consider a join which might produce non-unique rows; but later the results are aggregated again.
 * This method determines if there are sufficient columns in the grouping which have been present previously as unique column(s).
 */
private boolean isGroupingUnique(RelNode input, ImmutableBitSet groups) {
    if (groups.isEmpty()) {
        return false;
    }
    if (input instanceof HepRelVertex) {
        HepRelVertex vertex = (HepRelVertex) input;
        return isGroupingUnique(vertex.getCurrentRel(), groups);
    }
    RelMetadataQuery mq = input.getCluster().getMetadataQuery();
    Set<ImmutableBitSet> uKeys = mq.getUniqueKeys(input);
    if (uKeys == null) {
        return false;
    }
    for (ImmutableBitSet u : uKeys) {
        if (groups.contains(u)) {
            return true;
        }
    }
    if (input instanceof Join) {
        Join join = (Join) input;
        JoinInfo ji = JoinInfo.of(join.getLeft(), join.getRight(), join.getCondition());
        if (ji.isEqui()) {
            ImmutableBitSet newGroup = groups.intersect(InputFinder.bits(join.getCondition()));
            RelNode l = join.getLeft();
            RelNode r = join.getRight();
            int joinFieldCount = join.getRowType().getFieldCount();
            int lFieldCount = l.getRowType().getFieldCount();
            ImmutableBitSet groupL = newGroup.get(0, lFieldCount);
            ImmutableBitSet groupR = newGroup.get(lFieldCount, joinFieldCount).shift(-lFieldCount);
            if (isGroupingUnique(l, groupL)) {
                return true;
            }
            if (isGroupingUnique(r, groupR)) {
                return true;
            }
        }
    }
    if (input instanceof Project) {
        Project project = (Project) input;
        ImmutableBitSet.Builder newGroup = ImmutableBitSet.builder();
        for (int g : groups.asList()) {
            RexNode rex = project.getProjects().get(g);
            if (rex instanceof RexInputRef) {
                RexInputRef rexInputRef = (RexInputRef) rex;
                newGroup.set(rexInputRef.getIndex());
            }
        }
        return isGroupingUnique(project.getInput(), newGroup.build());
    }
    return false;
}
Also used : JoinInfo(org.apache.calcite.rel.core.JoinInfo) HepRelVertex(org.apache.calcite.plan.hep.HepRelVertex) RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) Project(org.apache.calcite.rel.core.Project) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RelNode(org.apache.calcite.rel.RelNode) Join(org.apache.calcite.rel.core.Join) HiveJoin(org.apache.hadoop.hive.ql.optimizer.calcite.reloperators.HiveJoin) RexInputRef(org.apache.calcite.rex.RexInputRef) RexNode(org.apache.calcite.rex.RexNode)

Example 14 with JoinInfo

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

the class HiveSemiJoin method copy.

@Override
public HiveSemiJoin copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode right, JoinRelType joinType, boolean semiJoinDone) {
    try {
        final JoinInfo joinInfo = JoinInfo.of(left, right, condition);
        HiveSemiJoin semijoin = new HiveSemiJoin(getCluster(), traitSet, left, right, condition);
        // If available, copy state to registry for optimization rules
        HiveRulesRegistry registry = semijoin.getCluster().getPlanner().getContext().unwrap(HiveRulesRegistry.class);
        if (registry != null) {
            registry.copyPushedPredicates(this, semijoin);
        }
        return semijoin;
    } catch (InvalidRelException | CalciteSemanticException e) {
        // internal error.
        throw new AssertionError(e);
    }
}
Also used : JoinInfo(org.apache.calcite.rel.core.JoinInfo) InvalidRelException(org.apache.calcite.rel.InvalidRelException) HiveRulesRegistry(org.apache.hadoop.hive.ql.optimizer.calcite.rules.HiveRulesRegistry) CalciteSemanticException(org.apache.hadoop.hive.ql.optimizer.calcite.CalciteSemanticException)

Example 15 with JoinInfo

use of org.apache.calcite.rel.core.JoinInfo in project calcite by apache.

the class EnumerableMergeJoinRule method convert.

@Override
public RelNode convert(RelNode rel) {
    LogicalJoin join = (LogicalJoin) rel;
    final JoinInfo info = JoinInfo.of(join.getLeft(), join.getRight(), join.getCondition());
    if (join.getJoinType() != JoinRelType.INNER) {
        // (It supports non-equi join, using a post-filter; see below.)
        return null;
    }
    if (info.pairs().size() == 0) {
        // EnumerableMergeJoin CAN support cartesian join, but disable it for now.
        return null;
    }
    final List<RelNode> newInputs = Lists.newArrayList();
    final List<RelCollation> collations = Lists.newArrayList();
    int offset = 0;
    for (Ord<RelNode> ord : Ord.zip(join.getInputs())) {
        RelTraitSet traits = ord.e.getTraitSet().replace(EnumerableConvention.INSTANCE);
        if (!info.pairs().isEmpty()) {
            final List<RelFieldCollation> fieldCollations = Lists.newArrayList();
            for (int key : info.keys().get(ord.i)) {
                fieldCollations.add(new RelFieldCollation(key, RelFieldCollation.Direction.ASCENDING, RelFieldCollation.NullDirection.LAST));
            }
            final RelCollation collation = RelCollations.of(fieldCollations);
            collations.add(RelCollations.shift(collation, offset));
            traits = traits.replace(collation);
        }
        newInputs.add(convert(ord.e, traits));
        offset += ord.e.getRowType().getFieldCount();
    }
    final RelNode left = newInputs.get(0);
    final RelNode right = newInputs.get(1);
    final RelOptCluster cluster = join.getCluster();
    RelNode newRel;
    try {
        RelTraitSet traits = join.getTraitSet().replace(EnumerableConvention.INSTANCE);
        if (!collations.isEmpty()) {
            traits = traits.replace(collations);
        }
        newRel = new EnumerableMergeJoin(cluster, traits, left, right, info.getEquiCondition(left, right, cluster.getRexBuilder()), info.leftKeys, info.rightKeys, join.getVariablesSet(), join.getJoinType());
    } catch (InvalidRelException e) {
        EnumerableRules.LOGGER.debug(e.toString());
        return null;
    }
    if (!info.isEqui()) {
        newRel = new EnumerableFilter(cluster, newRel.getTraitSet(), newRel, info.getRemaining(cluster.getRexBuilder()));
    }
    return newRel;
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) InvalidRelException(org.apache.calcite.rel.InvalidRelException) RelTraitSet(org.apache.calcite.plan.RelTraitSet) JoinInfo(org.apache.calcite.rel.core.JoinInfo) RelCollation(org.apache.calcite.rel.RelCollation) RelNode(org.apache.calcite.rel.RelNode) LogicalJoin(org.apache.calcite.rel.logical.LogicalJoin) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation)

Aggregations

JoinInfo (org.apache.calcite.rel.core.JoinInfo)21 RelNode (org.apache.calcite.rel.RelNode)12 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)8 Join (org.apache.calcite.rel.core.Join)7 ArrayList (java.util.ArrayList)6 RexNode (org.apache.calcite.rex.RexNode)6 RelOptCluster (org.apache.calcite.plan.RelOptCluster)5 LogicalJoin (org.apache.calcite.rel.logical.LogicalJoin)5 RelDataType (org.apache.calcite.rel.type.RelDataType)5 Project (org.apache.calcite.rel.core.Project)4 RelMetadataQuery (org.apache.calcite.rel.metadata.RelMetadataQuery)4 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)4 Column (herddb.model.Column)3 JoinOp (herddb.model.planner.JoinOp)3 NestedLoopJoinOp (herddb.model.planner.NestedLoopJoinOp)3 PlannerOp (herddb.model.planner.PlannerOp)3 SemiJoinOp (herddb.model.planner.SemiJoinOp)3 CompiledSQLExpression (herddb.sql.expressions.CompiledSQLExpression)3 HepRelVertex (org.apache.calcite.plan.hep.HepRelVertex)3 InvalidRelException (org.apache.calcite.rel.InvalidRelException)3