Search in sources :

Example 1 with DruidSemiJoin

use of io.druid.sql.calcite.rel.DruidSemiJoin in project druid by druid-io.

the class DruidSemiJoinRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final Project project = call.rel(0);
    final Join join = call.rel(1);
    final DruidRel left = call.rel(2);
    final DruidRel right = call.rel(3);
    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();
    final List<Integer> rightDimsOut = new ArrayList<>();
    for (DimensionSpec dimensionSpec : right.getQueryBuilder().getGrouping().getDimensions()) {
        rightDimsOut.add(right.getOutputRowSignature().getRowOrder().indexOf(dimensionSpec.getOutputName()));
    }
    if (!joinInfo.isEqui() || !joinInfo.rightSet().equals(ImmutableBitSet.of(rightDimsOut))) {
        // By the way, neither a super-set nor a sub-set would work.
        return;
    }
    final RelBuilder relBuilder = call.builder();
    final PlannerConfig plannerConfig = left.getPlannerContext().getPlannerConfig();
    if (join.getJoinType() == JoinRelType.LEFT) {
        // Join can be eliminated since the right-hand side cannot have any effect (nothing is being selected,
        // and LEFT means even if there is no match, a left-hand row will still be included).
        relBuilder.push(left);
    } else {
        final DruidSemiJoin druidSemiJoin = DruidSemiJoin.from(left, right, joinInfo.leftKeys, joinInfo.rightKeys, plannerConfig);
        if (druidSemiJoin == null) {
            return;
        }
        // Check maxQueryCount.
        if (plannerConfig.getMaxQueryCount() > 0 && druidSemiJoin.getQueryCount() > plannerConfig.getMaxQueryCount()) {
            return;
        }
        relBuilder.push(druidSemiJoin);
    }
    call.transformTo(relBuilder.project(project.getProjects(), project.getRowType().getFieldNames()).build());
}
Also used : JoinInfo(org.apache.calcite.rel.core.JoinInfo) Project(org.apache.calcite.rel.core.Project) DimensionSpec(io.druid.query.dimension.DimensionSpec) DruidSemiJoin(io.druid.sql.calcite.rel.DruidSemiJoin) RelBuilder(org.apache.calcite.tools.RelBuilder) DruidRel(io.druid.sql.calcite.rel.DruidRel) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) PlannerConfig(io.druid.sql.calcite.planner.PlannerConfig) ArrayList(java.util.ArrayList) DruidSemiJoin(io.druid.sql.calcite.rel.DruidSemiJoin) Join(org.apache.calcite.rel.core.Join)

Aggregations

DimensionSpec (io.druid.query.dimension.DimensionSpec)1 PlannerConfig (io.druid.sql.calcite.planner.PlannerConfig)1 DruidRel (io.druid.sql.calcite.rel.DruidRel)1 DruidSemiJoin (io.druid.sql.calcite.rel.DruidSemiJoin)1 ArrayList (java.util.ArrayList)1 Join (org.apache.calcite.rel.core.Join)1 JoinInfo (org.apache.calcite.rel.core.JoinInfo)1 Project (org.apache.calcite.rel.core.Project)1 RelBuilder (org.apache.calcite.tools.RelBuilder)1 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)1